]>
Commit | Line | Data |
---|---|---|
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 |