]>
Commit | Line | Data |
---|---|---|
d4697bc9 | 1 | /* Copyright (C) 2001-2014 Free Software Foundation, Inc. |
c9cf6dde AJ |
2 | This file is part of the GNU C Library. |
3 | ||
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://www.gnu.org/licenses/>. */ | |
c9cf6dde AJ |
17 | |
18 | #ifndef _LINUX_X86_64_SYSDEP_H | |
19 | #define _LINUX_X86_64_SYSDEP_H 1 | |
20 | ||
21 | /* There is some commonality. */ | |
22 | #include <sysdeps/unix/x86_64/sysdep.h> | |
89b91a92 | 23 | #include <tls.h> |
c9cf6dde | 24 | |
ce460d04 RM |
25 | #ifdef IS_IN_rtld |
26 | # include <dl-sysdep.h> /* Defines RTLD_PRIVATE_ERRNO. */ | |
27 | #endif | |
28 | ||
c9cf6dde AJ |
29 | /* For Linux we can use the system call table in the header file |
30 | /usr/include/asm/unistd.h | |
31 | of the kernel. But these symbols do not follow the SYS_* syntax | |
32 | so we have to redefine the `SYS_ify' macro here. */ | |
33 | #undef SYS_ify | |
34 | #define SYS_ify(syscall_name) __NR_##syscall_name | |
35 | ||
3899afcb RM |
36 | /* This is a kludge to make syscalls.list find these under the names |
37 | pread and pwrite, since some kernel headers define those names | |
38 | and some define the *64 names for the same system calls. */ | |
39 | #if !defined __NR_pread && defined __NR_pread64 | |
40 | # define __NR_pread __NR_pread64 | |
41 | #endif | |
42 | #if !defined __NR_pwrite && defined __NR_pwrite64 | |
43 | # define __NR_pwrite __NR_pwrite64 | |
44 | #endif | |
45 | ||
0fe8d5e6 AJ |
46 | /* This is to help the old kernel headers where __NR_semtimedop is not |
47 | available. */ | |
48 | #ifndef __NR_semtimedop | |
49 | # define __NR_semtimedop 220 | |
50 | #endif | |
51 | ||
52 | ||
c9cf6dde AJ |
53 | #ifdef __ASSEMBLER__ |
54 | ||
55 | /* Linux uses a negative return value to indicate syscall errors, | |
56 | unlike most Unices, which use the condition codes' carry flag. | |
57 | ||
58 | Since version 2.1 the return value of a system call might be | |
59 | negative even if the call succeeded. E.g., the `lseek' system call | |
60 | might return a large offset. Therefore we must not anymore test | |
61 | for < 0, but test for a real error by making sure the value in %eax | |
62 | is a real error number. Linus said he will make sure the no syscall | |
63 | returns a value in -1 .. -4095 as a valid result so we can savely | |
64 | test with -4095. */ | |
65 | ||
66 | /* We don't want the label for the error handle to be global when we define | |
67 | it here. */ | |
75fb247e UD |
68 | # ifdef PIC |
69 | # define SYSCALL_ERROR_LABEL 0f | |
70 | # else | |
71 | # define SYSCALL_ERROR_LABEL syscall_error | |
72 | # endif | |
c9cf6dde | 73 | |
75fb247e UD |
74 | # undef PSEUDO |
75 | # define PSEUDO(name, syscall_name, args) \ | |
c9cf6dde AJ |
76 | .text; \ |
77 | ENTRY (name) \ | |
ffa8d2a0 | 78 | DO_CALL (syscall_name, args); \ |
c9cf6dde | 79 | cmpq $-4095, %rax; \ |
842a39cd | 80 | jae SYSCALL_ERROR_LABEL |
c9cf6dde | 81 | |
75fb247e UD |
82 | # undef PSEUDO_END |
83 | # define PSEUDO_END(name) \ | |
c9cf6dde AJ |
84 | SYSCALL_ERROR_HANDLER \ |
85 | END (name) | |
86 | ||
75fb247e UD |
87 | # undef PSEUDO_NOERRNO |
88 | # define PSEUDO_NOERRNO(name, syscall_name, args) \ | |
9eb88290 UD |
89 | .text; \ |
90 | ENTRY (name) \ | |
91 | DO_CALL (syscall_name, args) | |
92 | ||
75fb247e UD |
93 | # undef PSEUDO_END_NOERRNO |
94 | # define PSEUDO_END_NOERRNO(name) \ | |
9eb88290 UD |
95 | END (name) |
96 | ||
75fb247e | 97 | # define ret_NOERRNO ret |
f38afd78 | 98 | |
75fb247e UD |
99 | # undef PSEUDO_ERRVAL |
100 | # define PSEUDO_ERRVAL(name, syscall_name, args) \ | |
bfef9264 UD |
101 | .text; \ |
102 | ENTRY (name) \ | |
103 | DO_CALL (syscall_name, args); \ | |
f38afd78 | 104 | negq %rax |
bfef9264 | 105 | |
75fb247e UD |
106 | # undef PSEUDO_END_ERRVAL |
107 | # define PSEUDO_END_ERRVAL(name) \ | |
bfef9264 UD |
108 | END (name) |
109 | ||
75fb247e | 110 | # define ret_ERRVAL ret |
9eb88290 | 111 | |
bbb3154b L |
112 | # if defined PIC && defined RTLD_PRIVATE_ERRNO |
113 | # define SYSCALL_SET_ERRNO \ | |
114 | lea rtld_errno(%rip), %RCX_LP; \ | |
0e44a77e L |
115 | neg %eax; \ |
116 | movl %eax, (%rcx) | |
d063d164 | 117 | # else |
75fb247e UD |
118 | # ifndef NOT_IN_libc |
119 | # define SYSCALL_ERROR_ERRNO __libc_errno | |
120 | # else | |
121 | # define SYSCALL_ERROR_ERRNO errno | |
122 | # endif | |
bbb3154b | 123 | # define SYSCALL_SET_ERRNO \ |
0a951d0e | 124 | movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ |
0e44a77e L |
125 | neg %eax; \ |
126 | movl %eax, %fs:(%rcx); | |
bbb3154b L |
127 | # endif |
128 | ||
129 | # ifndef PIC | |
130 | # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ | |
131 | # else | |
132 | # define SYSCALL_ERROR_HANDLER \ | |
133 | 0: \ | |
134 | SYSCALL_SET_ERRNO; \ | |
135 | or $-1, %RAX_LP; \ | |
5e292e4f | 136 | ret; |
75fb247e | 137 | # endif /* PIC */ |
c9cf6dde | 138 | |
092fd00d AJ |
139 | /* The Linux/x86-64 kernel expects the system call parameters in |
140 | registers according to the following table: | |
c9cf6dde | 141 | |
092fd00d | 142 | syscall number rax |
c9cf6dde AJ |
143 | arg 1 rdi |
144 | arg 2 rsi | |
145 | arg 3 rdx | |
092fd00d | 146 | arg 4 r10 |
c9cf6dde AJ |
147 | arg 5 r8 |
148 | arg 6 r9 | |
149 | ||
092fd00d | 150 | The Linux kernel uses and destroys internally these registers: |
c9cf6dde AJ |
151 | return address from |
152 | syscall rcx | |
c9cf6dde AJ |
153 | eflags from syscall r11 |
154 | ||
092fd00d AJ |
155 | Normal function call, including calls to the system call stub |
156 | functions in the libc, get the first six parameters passed in | |
157 | registers and the seventh parameter and later on the stack. The | |
158 | register use is as follows: | |
159 | ||
160 | system call number in the DO_CALL macro | |
161 | arg 1 rdi | |
162 | arg 2 rsi | |
163 | arg 3 rdx | |
164 | arg 4 rcx | |
165 | arg 5 r8 | |
166 | arg 6 r9 | |
167 | ||
168 | We have to take care that the stack is aligned to 16 bytes. When | |
169 | called the stack is not aligned since the return address has just | |
170 | been pushed. | |
171 | ||
9eb88290 | 172 | |
092fd00d | 173 | Syscalls of more than 6 arguments are not supported. */ |
c9cf6dde | 174 | |
75fb247e UD |
175 | # undef DO_CALL |
176 | # define DO_CALL(syscall_name, args) \ | |
c9cf6dde | 177 | DOARGS_##args \ |
ee618985 | 178 | movl $SYS_ify (syscall_name), %eax; \ |
c9cf6dde AJ |
179 | syscall; |
180 | ||
75fb247e UD |
181 | # define DOARGS_0 /* nothing */ |
182 | # define DOARGS_1 /* nothing */ | |
183 | # define DOARGS_2 /* nothing */ | |
184 | # define DOARGS_3 /* nothing */ | |
185 | # define DOARGS_4 movq %rcx, %r10; | |
186 | # define DOARGS_5 DOARGS_4 | |
187 | # define DOARGS_6 DOARGS_5 | |
c9cf6dde AJ |
188 | |
189 | #else /* !__ASSEMBLER__ */ | |
190 | /* Define a macro which expands inline into the wrapper code for a system | |
191 | call. */ | |
75fb247e UD |
192 | # undef INLINE_SYSCALL |
193 | # define INLINE_SYSCALL(name, nr, args...) \ | |
369b849f | 194 | ({ \ |
78b767a0 | 195 | unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \ |
6aca81bb | 196 | if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \ |
369b849f | 197 | { \ |
6aca81bb | 198 | __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ |
78b767a0 | 199 | resultvar = (unsigned long int) -1; \ |
369b849f | 200 | } \ |
78b767a0 | 201 | (long int) resultvar; }) |
369b849f | 202 | |
31a39bd8 L |
203 | /* Define a macro with explicit types for arguments, which expands inline |
204 | into the wrapper code for a system call. It should be used when size | |
205 | of any argument > size of long int. */ | |
206 | # undef INLINE_SYSCALL_TYPES | |
207 | # define INLINE_SYSCALL_TYPES(name, nr, args...) \ | |
208 | ({ \ | |
209 | unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \ | |
210 | if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0)) \ | |
211 | { \ | |
212 | __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ | |
213 | resultvar = (unsigned long int) -1; \ | |
214 | } \ | |
215 | (long int) resultvar; }) | |
216 | ||
75fb247e UD |
217 | # undef INTERNAL_SYSCALL_DECL |
218 | # define INTERNAL_SYSCALL_DECL(err) do { } while (0) | |
6aca81bb | 219 | |
75fb247e | 220 | # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ |
c9cf6dde | 221 | ({ \ |
78b767a0 | 222 | unsigned long int resultvar; \ |
c9cf6dde | 223 | LOAD_ARGS_##nr (args) \ |
381a0c26 | 224 | LOAD_REGS_##nr \ |
c9cf6dde | 225 | asm volatile ( \ |
c9cf6dde AJ |
226 | "syscall\n\t" \ |
227 | : "=a" (resultvar) \ | |
2edb61e3 | 228 | : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ |
78b767a0 | 229 | (long int) resultvar; }) |
75fb247e UD |
230 | # undef INTERNAL_SYSCALL |
231 | # define INTERNAL_SYSCALL(name, err, nr, args...) \ | |
2edb61e3 | 232 | INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args) |
c9cf6dde | 233 | |
31a39bd8 L |
234 | # define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \ |
235 | ({ \ | |
236 | unsigned long int resultvar; \ | |
237 | LOAD_ARGS_TYPES_##nr (args) \ | |
238 | LOAD_REGS_TYPES_##nr (args) \ | |
239 | asm volatile ( \ | |
240 | "syscall\n\t" \ | |
241 | : "=a" (resultvar) \ | |
242 | : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ | |
243 | (long int) resultvar; }) | |
244 | # undef INTERNAL_SYSCALL_TYPES | |
245 | # define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \ | |
246 | INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args) | |
247 | ||
75fb247e UD |
248 | # undef INTERNAL_SYSCALL_ERROR_P |
249 | # define INTERNAL_SYSCALL_ERROR_P(val, err) \ | |
78b767a0 | 250 | ((unsigned long int) (long int) (val) >= -4095L) |
369b849f | 251 | |
75fb247e UD |
252 | # undef INTERNAL_SYSCALL_ERRNO |
253 | # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) | |
254 | ||
255 | # ifdef SHARED | |
256 | # define INLINE_VSYSCALL(name, nr, args...) \ | |
257 | ({ \ | |
258 | __label__ out; \ | |
259 | __label__ iserr; \ | |
260 | INTERNAL_SYSCALL_DECL (sc_err); \ | |
261 | long int sc_ret; \ | |
262 | \ | |
3c87d79d UD |
263 | __typeof (__vdso_##name) vdsop = __vdso_##name; \ |
264 | PTR_DEMANGLE (vdsop); \ | |
265 | if (vdsop != NULL) \ | |
75fb247e | 266 | { \ |
3c87d79d | 267 | sc_ret = vdsop (args); \ |
75fb247e UD |
268 | if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ |
269 | goto out; \ | |
270 | if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \ | |
271 | goto iserr; \ | |
272 | } \ | |
273 | \ | |
274 | sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \ | |
275 | if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ | |
276 | { \ | |
277 | iserr: \ | |
a77d3c17 UD |
278 | __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ |
279 | sc_ret = -1L; \ | |
75fb247e UD |
280 | } \ |
281 | out: \ | |
282 | sc_ret; \ | |
283 | }) | |
284 | # define INTERNAL_VSYSCALL(name, err, nr, args...) \ | |
285 | ({ \ | |
286 | __label__ out; \ | |
287 | long int v_ret; \ | |
288 | \ | |
3c87d79d UD |
289 | __typeof (__vdso_##name) vdsop = __vdso_##name; \ |
290 | PTR_DEMANGLE (vdsop); \ | |
291 | if (vdsop != NULL) \ | |
75fb247e | 292 | { \ |
3c87d79d | 293 | v_ret = vdsop (args); \ |
75fb247e UD |
294 | if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \ |
295 | || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \ | |
296 | goto out; \ | |
297 | } \ | |
298 | v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \ | |
299 | out: \ | |
300 | v_ret; \ | |
301 | }) | |
302 | ||
75fb247e UD |
303 | # else |
304 | # define INLINE_VSYSCALL(name, nr, args...) \ | |
305 | INLINE_SYSCALL (name, nr, ##args) | |
306 | # define INTERNAL_VSYSCALL(name, err, nr, args...) \ | |
307 | INTERNAL_SYSCALL (name, err, nr, ##args) | |
308 | # endif | |
369b849f | 309 | |
75fb247e UD |
310 | # define LOAD_ARGS_0() |
311 | # define LOAD_REGS_0 | |
312 | # define ASM_ARGS_0 | |
c9cf6dde | 313 | |
31a39bd8 L |
314 | # define LOAD_ARGS_TYPES_1(t1, a1) \ |
315 | t1 __arg1 = (t1) (a1); \ | |
c9cf6dde | 316 | LOAD_ARGS_0 () |
31a39bd8 L |
317 | # define LOAD_REGS_TYPES_1(t1, a1) \ |
318 | register t1 _a1 asm ("rdi") = __arg1; \ | |
381a0c26 | 319 | LOAD_REGS_0 |
75fb247e | 320 | # define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1) |
31a39bd8 L |
321 | # define LOAD_ARGS_1(a1) \ |
322 | LOAD_ARGS_TYPES_1 (long int, a1) | |
323 | # define LOAD_REGS_1 \ | |
324 | LOAD_REGS_TYPES_1 (long int, a1) | |
325 | ||
326 | # define LOAD_ARGS_TYPES_2(t1, a1, t2, a2) \ | |
327 | t2 __arg2 = (t2) (a2); \ | |
328 | LOAD_ARGS_TYPES_1 (t1, a1) | |
329 | # define LOAD_REGS_TYPES_2(t1, a1, t2, a2) \ | |
330 | register t2 _a2 asm ("rsi") = __arg2; \ | |
331 | LOAD_REGS_TYPES_1(t1, a1) | |
75fb247e | 332 | # define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2) |
31a39bd8 L |
333 | # define LOAD_ARGS_2(a1, a2) \ |
334 | LOAD_ARGS_TYPES_2 (long int, a1, long int, a2) | |
335 | # define LOAD_REGS_2 \ | |
336 | LOAD_REGS_TYPES_2 (long int, a1, long int, a2) | |
337 | ||
338 | # define LOAD_ARGS_TYPES_3(t1, a1, t2, a2, t3, a3) \ | |
339 | t3 __arg3 = (t3) (a3); \ | |
340 | LOAD_ARGS_TYPES_2 (t1, a1, t2, a2) | |
341 | # define LOAD_REGS_TYPES_3(t1, a1, t2, a2, t3, a3) \ | |
342 | register t3 _a3 asm ("rdx") = __arg3; \ | |
343 | LOAD_REGS_TYPES_2(t1, a1, t2, a2) | |
75fb247e | 344 | # define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3) |
31a39bd8 L |
345 | # define LOAD_ARGS_3(a1, a2, a3) \ |
346 | LOAD_ARGS_TYPES_3 (long int, a1, long int, a2, long int, a3) | |
347 | # define LOAD_REGS_3 \ | |
348 | LOAD_REGS_TYPES_3 (long int, a1, long int, a2, long int, a3) | |
349 | ||
350 | # define LOAD_ARGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \ | |
351 | t4 __arg4 = (t4) (a4); \ | |
352 | LOAD_ARGS_TYPES_3 (t1, a1, t2, a2, t3, a3) | |
353 | # define LOAD_REGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4) \ | |
354 | register t4 _a4 asm ("r10") = __arg4; \ | |
355 | LOAD_REGS_TYPES_3(t1, a2, t2, a2, t3, a3) | |
75fb247e | 356 | # define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4) |
31a39bd8 L |
357 | # define LOAD_ARGS_4(a1, a2, a3, a4) \ |
358 | LOAD_ARGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \ | |
359 | long int, a4) | |
360 | # define LOAD_REGS_4 \ | |
361 | LOAD_REGS_TYPES_4 (long int, a1, long int, a2, long int, a3, \ | |
362 | long int, a4) | |
363 | ||
364 | # define LOAD_ARGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \ | |
365 | t5 __arg5 = (t5) (a5); \ | |
366 | LOAD_ARGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4) | |
367 | # define LOAD_REGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \ | |
368 | register t5 _a5 asm ("r8") = __arg5; \ | |
369 | LOAD_REGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4) | |
75fb247e | 370 | # define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5) |
31a39bd8 L |
371 | # define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ |
372 | LOAD_ARGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \ | |
373 | long int, a4, long int, a5) | |
374 | # define LOAD_REGS_5 \ | |
375 | LOAD_REGS_TYPES_5 (long int, a1, long int, a2, long int, a3, \ | |
376 | long int, a4, long int, a5) | |
377 | ||
378 | # define LOAD_ARGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \ | |
379 | t6 __arg6 = (t6) (a6); \ | |
380 | LOAD_ARGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) | |
381 | # define LOAD_REGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \ | |
382 | register t6 _a6 asm ("r9") = __arg6; \ | |
383 | LOAD_REGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) | |
75fb247e | 384 | # define ASM_ARGS_6 ASM_ARGS_5, "r" (_a6) |
31a39bd8 L |
385 | # define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ |
386 | LOAD_ARGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \ | |
387 | long int, a4, long int, a5, long int, a6) | |
388 | # define LOAD_REGS_6 \ | |
389 | LOAD_REGS_TYPES_6 (long int, a1, long int, a2, long int, a3, \ | |
390 | long int, a4, long int, a5, long int, a6) | |
c9cf6dde AJ |
391 | |
392 | #endif /* __ASSEMBLER__ */ | |
393 | ||
827b7087 UD |
394 | |
395 | /* Pointer mangling support. */ | |
396 | #if defined NOT_IN_libc && defined IS_IN_rtld | |
397 | /* We cannot use the thread descriptor because in ld.so we use setjmp | |
398 | earlier than the descriptor is initialized. */ | |
3467f5c3 | 399 | # ifdef __ASSEMBLER__ |
e02f153a L |
400 | # define PTR_MANGLE(reg) xor __pointer_chk_guard_local(%rip), reg; \ |
401 | rol $2*LP_SIZE+1, reg | |
402 | # define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ | |
403 | xor __pointer_chk_guard_local(%rip), reg | |
3467f5c3 | 404 | # else |
e02f153a L |
405 | # define PTR_MANGLE(reg) asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \ |
406 | "rol $2*" LP_SIZE "+1, %0" \ | |
4a44ce79 | 407 | : "=r" (reg) : "0" (reg)) |
e02f153a L |
408 | # define PTR_DEMANGLE(reg) asm ("ror $2*" LP_SIZE "+1, %0\n" \ |
409 | "xor __pointer_chk_guard_local(%%rip), %0" \ | |
7725f874 | 410 | : "=r" (reg) : "0" (reg)) |
3467f5c3 | 411 | # endif |
827b7087 | 412 | #else |
3467f5c3 | 413 | # ifdef __ASSEMBLER__ |
e02f153a L |
414 | # define PTR_MANGLE(reg) xor %fs:POINTER_GUARD, reg; \ |
415 | rol $2*LP_SIZE+1, reg | |
416 | # define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \ | |
417 | xor %fs:POINTER_GUARD, reg | |
3467f5c3 | 418 | # else |
e02f153a L |
419 | # define PTR_MANGLE(var) asm ("xor %%fs:%c2, %0\n" \ |
420 | "rol $2*" LP_SIZE "+1, %0" \ | |
4a44ce79 UD |
421 | : "=r" (var) \ |
422 | : "0" (var), \ | |
423 | "i" (offsetof (tcbhead_t, \ | |
424 | pointer_guard))) | |
e02f153a L |
425 | # define PTR_DEMANGLE(var) asm ("ror $2*" LP_SIZE "+1, %0\n" \ |
426 | "xor %%fs:%c2, %0" \ | |
3467f5c3 UD |
427 | : "=r" (var) \ |
428 | : "0" (var), \ | |
429 | "i" (offsetof (tcbhead_t, \ | |
430 | pointer_guard))) | |
3467f5c3 | 431 | # endif |
827b7087 UD |
432 | #endif |
433 | ||
c9cf6dde | 434 | #endif /* linux/x86_64/sysdep.h */ |