1 | /* Assembler macros for x86. |
2 | Copyright (C) 2017-2024 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #ifndef _X86_SYSDEP_H |
20 | #define _X86_SYSDEP_H 1 |
21 | |
22 | #include <sysdeps/generic/sysdep.h> |
23 | |
24 | /* The extended state feature IDs in the state component bitmap. */ |
25 | #define X86_XSTATE_X87_ID 0 |
26 | #define X86_XSTATE_SSE_ID 1 |
27 | #define X86_XSTATE_AVX_ID 2 |
28 | #define X86_XSTATE_BNDREGS_ID 3 |
29 | #define X86_XSTATE_BNDCFG_ID 4 |
30 | #define X86_XSTATE_K_ID 5 |
31 | #define X86_XSTATE_ZMM_H_ID 6 |
32 | #define X86_XSTATE_ZMM_ID 7 |
33 | #define X86_XSTATE_PKRU_ID 9 |
34 | #define X86_XSTATE_TILECFG_ID 17 |
35 | #define X86_XSTATE_TILEDATA_ID 18 |
36 | #define X86_XSTATE_APX_F_ID 19 |
37 | |
38 | #ifdef __x86_64__ |
39 | /* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need |
40 | space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be |
41 | aligned to 16 bytes for fxsave and 64 bytes for xsave. It is non-zero |
42 | because MOV, instead of PUSH, is used to save registers onto stack. |
43 | |
44 | +==================+<- stack frame start aligned at 8 or 16 bytes |
45 | | |<- paddings for stack realignment of 64 bytes |
46 | |------------------|<- xsave buffer end aligned at 64 bytes |
47 | | |<- |
48 | | |<- |
49 | | |<- |
50 | |------------------|<- xsave buffer start at STATE_SAVE_OFFSET(%rsp) |
51 | | |<- 8-byte padding for 64-byte alignment |
52 | | |<- R9 |
53 | | |<- R8 |
54 | | |<- RDI |
55 | | |<- RSI |
56 | | |<- RDX |
57 | | |<- RCX |
58 | | |<- RAX |
59 | +==================+<- RSP aligned at 64 bytes |
60 | |
61 | */ |
62 | # define STATE_SAVE_OFFSET (8 * 7 + 8) |
63 | |
64 | /* _dl_tlsdesc_dynamic preserves RDI, RSI and RBX before realigning |
65 | stack. After realigning stack, it saves RCX, RDX, R8, R9, R10 and |
66 | R11. Allocate space for RDI, RSI and RBX to avoid clobbering saved |
67 | RDI, RSI and RBX values on stack by xsave. |
68 | |
69 | +==================+<- stack frame start aligned at 8 or 16 bytes |
70 | | |<- RDI saved in the red zone |
71 | | |<- RSI saved in the red zone |
72 | | |<- RBX saved in the red zone |
73 | | |<- paddings for stack realignment of 64 bytes |
74 | |------------------|<- xsave buffer end aligned at 64 bytes |
75 | | |<- |
76 | | |<- |
77 | | |<- |
78 | |------------------|<- xsave buffer start at STATE_SAVE_OFFSET(%rsp) |
79 | | |<- 8-byte padding for 64-byte alignment |
80 | | |<- 8-byte padding for 64-byte alignment |
81 | | |<- R11 |
82 | | |<- R10 |
83 | | |<- R9 |
84 | | |<- R8 |
85 | | |<- RDX |
86 | | |<- RCX |
87 | +==================+<- RSP aligned at 64 bytes |
88 | |
89 | Define the total register save area size for all integer registers by |
90 | adding 24 to STATE_SAVE_OFFSET since RDI, RSI and RBX are saved onto |
91 | stack without adjusting stack pointer first, using the red-zone. */ |
92 | # define TLSDESC_CALL_REGISTER_SAVE_AREA (STATE_SAVE_OFFSET + 24) |
93 | |
94 | /* Save SSE, AVX, AVX512, mask, bound and APX registers. Bound and APX |
95 | registers are mutually exclusive. */ |
96 | # define STATE_SAVE_MASK \ |
97 | ((1 << X86_XSTATE_SSE_ID) \ |
98 | | (1 << X86_XSTATE_AVX_ID) \ |
99 | | (1 << X86_XSTATE_BNDREGS_ID) \ |
100 | | (1 << X86_XSTATE_K_ID) \ |
101 | | (1 << X86_XSTATE_ZMM_H_ID) \ |
102 | | (1 << X86_XSTATE_ZMM_ID) \ |
103 | | (1 << X86_XSTATE_APX_F_ID)) |
104 | |
105 | /* AMX state mask. */ |
106 | # define AMX_STATE_SAVE_MASK \ |
107 | ((1 << X86_XSTATE_TILECFG_ID) | (1 << X86_XSTATE_TILEDATA_ID)) |
108 | |
109 | /* States to be included in xsave_state_full_size. */ |
110 | # define FULL_STATE_SAVE_MASK \ |
111 | (STATE_SAVE_MASK | AMX_STATE_SAVE_MASK) |
112 | #else |
113 | /* Offset for fxsave/xsave area used by _dl_tlsdesc_dynamic. Since i386 |
114 | uses PUSH to save registers onto stack, use 0 here. */ |
115 | # define STATE_SAVE_OFFSET 0 |
116 | # define TLSDESC_CALL_REGISTER_SAVE_AREA 0 |
117 | |
118 | /* Save SSE, AVX, AXV512, mask and bound registers. */ |
119 | # define STATE_SAVE_MASK \ |
120 | ((1 << X86_XSTATE_SSE_ID) \ |
121 | | (1 << X86_XSTATE_AVX_ID) \ |
122 | | (1 << X86_XSTATE_BNDREGS_ID) \ |
123 | | (1 << X86_XSTATE_K_ID) \ |
124 | | (1 << X86_XSTATE_ZMM_H_ID)) |
125 | |
126 | /* States to be included in xsave_state_size. */ |
127 | # define FULL_STATE_SAVE_MASK STATE_SAVE_MASK |
128 | #endif |
129 | |
130 | /* States which should be saved for TLSDESC_CALL and TLS_DESC_CALL. |
131 | Compiler assumes that all registers, including AMX and x87 FPU |
132 | stack registers, are unchanged after CALL, except for EFLAGS and |
133 | RAX/EAX. */ |
134 | #define TLSDESC_CALL_STATE_SAVE_MASK \ |
135 | (FULL_STATE_SAVE_MASK | (1 << X86_XSTATE_X87_ID)) |
136 | |
137 | /* Constants for bits in __x86_string_control: */ |
138 | |
139 | /* Avoid short distance REP MOVSB. */ |
140 | #define X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB (1 << 0) |
141 | |
142 | #ifdef __ASSEMBLER__ |
143 | |
144 | /* Syntactic details of assembler. */ |
145 | |
146 | /* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ |
147 | #define ALIGNARG(log2) 1<<log2 |
148 | #define ASM_SIZE_DIRECTIVE(name) .size name,.-name; |
149 | |
150 | /* Common entry 16 byte aligns. */ |
151 | #define ENTRY(name) ENTRY_P2ALIGN (name, 4) |
152 | |
153 | #undef END |
154 | #define END(name) \ |
155 | cfi_endproc; \ |
156 | ASM_SIZE_DIRECTIVE(name) |
157 | |
158 | #define ENTRY_CHK(name) ENTRY (name) |
159 | #define END_CHK(name) END (name) |
160 | |
161 | /* Since C identifiers are not normally prefixed with an underscore |
162 | on this system, the asm identifier `syscall_error' intrudes on the |
163 | C name space. Make sure we use an innocuous name. */ |
164 | #define syscall_error __syscall_error |
165 | #define mcount _mcount |
166 | |
167 | #undef PSEUDO_END |
168 | #define PSEUDO_END(name) \ |
169 | END (name) |
170 | |
171 | /* Local label name for asm code. */ |
172 | #ifndef L |
173 | /* ELF-like local names start with `.L'. */ |
174 | # define LOCAL_LABEL(name) .L##name |
175 | # define L(name) LOCAL_LABEL(name) |
176 | #endif |
177 | |
178 | #define atom_text_section .section ".text.atom", "ax" |
179 | |
180 | #endif /* __ASSEMBLER__ */ |
181 | |
182 | #endif /* _X86_SYSDEP_H */ |
183 | |