]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/s390/htm.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / s390 / htm.h
CommitLineData
8bfc4a2a
SL
1/* Shared HTM header. Work around false transactional execution facility
2 intrinsics.
3
bfff8b1b 4 Copyright (C) 2016-2017 Free Software Foundation, Inc.
8bfc4a2a
SL
5 This file is part of the GNU C Library.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, see
19 <http://www.gnu.org/licenses/>. */
20
21#ifndef _HTM_H
22#define _HTM_H 1
23
24#include <htmintrin.h>
25
26#ifdef __s390x__
27# define TX_FPRS_BYTES 64
28# define TX_SAVE_FPRS \
29 " std %%f8, 0(%[R_FPRS])\n\t" \
30 " std %%f9, 8(%[R_FPRS])\n\t" \
31 " std %%f10, 16(%[R_FPRS])\n\t" \
32 " std %%f11, 24(%[R_FPRS])\n\t" \
33 " std %%f12, 32(%[R_FPRS])\n\t" \
34 " std %%f13, 40(%[R_FPRS])\n\t" \
35 " std %%f14, 48(%[R_FPRS])\n\t" \
36 " std %%f15, 56(%[R_FPRS])\n\t"
37
38# define TX_RESTORE_FPRS \
39 " ld %%f8, 0(%[R_FPRS])\n\t" \
40 " ld %%f9, 8(%[R_FPRS])\n\t" \
41 " ld %%f10, 16(%[R_FPRS])\n\t" \
42 " ld %%f11, 24(%[R_FPRS])\n\t" \
43 " ld %%f12, 32(%[R_FPRS])\n\t" \
44 " ld %%f13, 40(%[R_FPRS])\n\t" \
45 " ld %%f14, 48(%[R_FPRS])\n\t" \
46 " ld %%f15, 56(%[R_FPRS])\n\t"
47
48#else
49
50# define TX_FPRS_BYTES 16
51# define TX_SAVE_FPRS \
52 " std %%f4, 0(%[R_FPRS])\n\t" \
53 " std %%f6, 8(%[R_FPRS])\n\t"
54
55# define TX_RESTORE_FPRS \
56 " ld %%f4, 0(%[R_FPRS])\n\t" \
57 " ld %%f6, 8(%[R_FPRS])\n\t"
58
59#endif /* ! __s390x__ */
60
61/* Use own inline assembly instead of __builtin_tbegin, as tbegin
62 has to filter program interruptions which can't be done with the builtin.
63 Now the fprs have to be saved / restored here, too.
64 The fpc is also not saved / restored with the builtin.
65 The used inline assembly does not clobber the volatile fprs / vrs!
66 Clobbering the latter ones would force the compiler to save / restore
67 the call saved fprs as those overlap with the vrs, but they only need to be
68 restored if the transaction fails but not if the transaction is successfully
69 started. Thus the user of the tbegin macros in this header file has to
70 compile the file / function with -msoft-float. It prevents gcc from using
71 fprs / vrs. */
53c5c3d5
SL
72#define __libc_tbegin(tdb) __libc_tbegin_base(tdb,,,)
73
74#define __libc_tbegin_retry_output_regs , [R_TX_CNT] "+&d" (__tx_cnt)
75#define __libc_tbegin_retry_input_regs(retry_cnt) , [R_RETRY] "d" (retry_cnt)
76#define __libc_tbegin_retry_abort_path_insn \
77 /* If tbegin returned _HTM_TBEGIN_TRANSIENT, retry immediately so \
78 that max tbegin_cnt transactions are tried. Otherwise return and \
79 let the caller of this macro do the fallback path. */ \
80 " jnh 1f\n\t" /* cc 1/3: jump to fallback path. */ \
81 /* tbegin returned _HTM_TBEGIN_TRANSIENT: retry with transaction. */ \
82 " crje %[R_TX_CNT], %[R_RETRY], 1f\n\t" /* Reached max retries? */ \
83 " ahi %[R_TX_CNT], 1\n\t" \
84 " ppa %[R_TX_CNT], 0, 1\n\t" /* Transaction-Abort Assist. */ \
85 " j 2b\n\t" /* Loop to tbegin. */
86
87/* Same as __libc_tbegin except if tbegin aborts with _HTM_TBEGIN_TRANSIENT.
88 Then this macros restores the fpc, fprs and automatically retries up to
89 retry_cnt tbegins. Further saving of the state is omitted as it is already
90 saved. This macro calls tbegin at most as retry_cnt + 1 times. */
91#define __libc_tbegin_retry(tdb, retry_cnt) \
92 ({ int __ret; \
93 int __tx_cnt = 0; \
94 __ret = __libc_tbegin_base(tdb, \
95 __libc_tbegin_retry_abort_path_insn, \
96 __libc_tbegin_retry_output_regs, \
97 __libc_tbegin_retry_input_regs(retry_cnt)); \
98 __ret; \
99 })
100
101#define __libc_tbegin_base(tdb, abort_path_insn, output_regs, input_regs) \
8bfc4a2a
SL
102 ({ int __ret; \
103 int __fpc; \
104 char __fprs[TX_FPRS_BYTES]; \
105 __asm__ __volatile__ (".machine push\n\t" \
106 ".machinemode \"zarch_nohighgprs\"\n\t" \
107 ".machine \"all\"\n\t" \
108 /* Save state at the outermost transaction. \
109 As extracting nesting depth is expensive \
110 on at least zEC12, save fprs at inner \
111 transactions, too. \
112 The fpc and fprs are saved here as they \
113 are not saved by tbegin. There exist no \
114 call-saved vrs, thus they are not saved \
115 here. */ \
116 " efpc %[R_FPC]\n\t" \
117 TX_SAVE_FPRS \
118 /* Begin transaction: save all gprs, allow \
119 ar modification and fp operations. Some \
120 program-interruptions (e.g. a null \
121 pointer access) are filtered and the \
122 trancsaction will abort. In this case \
123 the normal lock path will execute it \
124 again and result in a core dump wich does \
125 now show at tbegin but the real executed \
126 instruction. */ \
53c5c3d5 127 "2: tbegin 0, 0xFF0E\n\t" \
8bfc4a2a
SL
128 /* Branch away in abort case (this is the \
129 prefered sequence. See PoP in chapter 5 \
130 Transactional-Execution Facility \
131 Operation). */ \
132 " jnz 0f\n\t" \
133 /* Transaction has successfully started. */ \
134 " lhi %[R_RET], 0\n\t" \
135 " j 1f\n\t" \
136 /* Transaction has aborted. Now we are at \
137 the outermost transaction. Restore fprs \
138 and fpc. */ \
139 "0: ipm %[R_RET]\n\t" \
140 " srl %[R_RET], 28\n\t" \
141 " sfpc %[R_FPC]\n\t" \
142 TX_RESTORE_FPRS \
53c5c3d5 143 abort_path_insn \
8bfc4a2a
SL
144 "1:\n\t" \
145 ".machine pop\n" \
146 : [R_RET] "=&d" (__ret), \
147 [R_FPC] "=&d" (__fpc) \
53c5c3d5 148 output_regs \
8bfc4a2a 149 : [R_FPRS] "a" (__fprs) \
53c5c3d5 150 input_regs \
8bfc4a2a
SL
151 : "cc", "memory"); \
152 __ret; \
153 })
154
155/* These builtins are correct. Use them. */
156#define __libc_tend() \
157 ({ __asm__ __volatile__ (".machine push\n\t" \
158 ".machinemode \"zarch_nohighgprs\"\n\t" \
159 ".machine \"all\"\n\t"); \
160 int __ret = __builtin_tend (); \
161 __asm__ __volatile__ (".machine pop"); \
162 __ret; \
163 })
164
165#define __libc_tabort(abortcode) \
166 __asm__ __volatile__ (".machine push\n\t" \
167 ".machinemode \"zarch_nohighgprs\"\n\t" \
168 ".machine \"all\"\n\t"); \
169 __builtin_tabort (abortcode); \
170 __asm__ __volatile__ (".machine pop")
171
172#define __libc_tx_nesting_depth() \
173 ({ __asm__ __volatile__ (".machine push\n\t" \
174 ".machinemode \"zarch_nohighgprs\"\n\t" \
175 ".machine \"all\"\n\t"); \
176 int __ret = __builtin_tx_nesting_depth (); \
177 __asm__ __volatile__ (".machine pop"); \
178 __ret; \
179 })
180
181#endif