progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / base / dispatch-x86ish.S
... / ...
CommitLineData
1/// -*- mode: asm; asm-comment-char: ?/ -*-
2///
3/// CPU dispatch support for x86
4///
5/// (c) 2019 Straylight/Edgeware
6///
7
8///----- Licensing notice ---------------------------------------------------
9///
10/// This file is part of Catacomb.
11///
12/// Catacomb is free software: you can redistribute it and/or modify it
13/// under the terms of the GNU Library General Public License as published
14/// by the Free Software Foundation; either version 2 of the License, or
15/// (at your option) any later version.
16///
17/// Catacomb is distributed in the hope that it will be useful, but
18/// WITHOUT ANY WARRANTY; without even the implied warranty of
19/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20/// Library General Public License for more details.
21///
22/// You should have received a copy of the GNU Library General Public
23/// License along with Catacomb. If not, write to the Free Software
24/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25/// USA.
26
27///--------------------------------------------------------------------------
28/// Preliminaries.
29
30#include "config.h"
31#include "asm-common.h"
32
33 EFLAGS_ID = 1 << 21
34
35 .text
36
37///--------------------------------------------------------------------------
38/// Probing for CPUID.
39
40FUNC(dispatch_x86ish_cpuid)
41 // Enter with a pointer to 16 bytes of storage for the output A, B,
42 // C, D values in the first argument, and input A and C values in the
43 // second and third. Fill the output buffer with `cpuid' results and
44 // return zero if we can; otherwise fill with zero and return -1.
45
46#if CPUFAM_X86
47# define OUT edi
48 pushreg ebx
49 pushreg edi
50 mov OUT, [SP + 12]
51 mov eax, [SP + 16]
52 mov ecx, [SP + 20]
53#endif
54#if CPUFAM_AMD64 && ABI_SYSV
55# define OUT rdi
56 pushreg rbx
57 mov eax, esi
58 mov ecx, edx
59#endif
60#if CPUFAM_AMD64 && ABI_WIN
61# define OUT r9
62 pushreg rbx
63 mov OUT, rcx
64 mov eax, edx
65 mov ecx, r8d
66#endif
67 endprologue
68
69 // First, check that this is even a thing, using the complicated
70 // dance with the flags register. This is unnecessary on AMD64,
71 // which postdates the introduction of `cpuid'.
72#if CPUFAM_X86
73 pushf
74 pop DX // current flags in d
75
76 or DX, EFLAGS_ID // force the id bit on and check it
77 push DX
78 popf
79 pushf
80 pop DX
81 test edx, EFLAGS_ID
82 jz 8f
83
84 and DX, ~EFLAGS_ID // force the id bit off and check it
85 push DX
86 popf
87 pushf
88 pop DX
89 test edx, EFLAGS_ID
90 jnz 8f
91#endif
92
93 // OK, that seemed to work.
94 cpuid
95
96 mov [OUT + 0], eax
97 mov [OUT + 4], ebx
98 mov [OUT + 8], ecx
99 mov [OUT + 12], edx
100 xor eax, eax
101
102 // We're done.
1039:
104#if CPUFAM_X86
105 popreg edi
106 popreg ebx
107#endif
108#if CPUFAM_AMD64
109 popreg rbx
110#endif
111 ret
112
113 // Failed.
114#if CPUFAM_X86
1158: xor eax, eax
116 mov [OUT + 0], eax
117 mov [OUT + 4], eax
118 mov [OUT + 8], eax
119 mov [OUT + 12], eax
120 mov eax, -1
121 jmp 9b
122#endif
123
124#undef OUT
125ENDFUNC
126
127///--------------------------------------------------------------------------
128/// Probing for XMM register availability.
129
130FUNC(dispatch_x86ish_xmmregisters_p)
131 // Enter with no arguments. Return nonzero if the XMM registers are
132 // usable.
133
134 pushreg BP
135 setfp
136 stalloc 512
137 and SP, ~15
138 endprologue
139
140 // Save the floating point and SIMD registers, and try to clobber
141 // xmm0.
142 lea DX, [SP + 160]
143 fxsave [SP]
144 mov eax, [DX]
145 xor dword ptr [DX], 0xaaaa5555
146 fxrstor [SP]
147
148 // Save them again, and read back the low word of xmm0. Undo the
149 // clobbering and restore.
150 fxsave [SP]
151 mov ecx, [DX]
152 mov [DX], eax
153 fxrstor [SP]
154
155 // The register are live if we read different things.
156 xor eax, ecx
157
158 // Done.
159 dropfp
160 popreg BP
161 ret
162ENDFUNC
163
164///--------------------------------------------------------------------------
165/// Checking extended control registers.
166
167FUNC(dispatch_x86ish_xgetbv)
168 // Call with two arguments: a pointer Z_OUT to 8 bytes of output space, and
169 // a 32-bit integer C. Read the 64-bit value of XCR(C), and store it
170 // at Z_OUT.
171
172#if CPUFAM_X86
173# define Z_OUT edi
174 pushreg edi
175 mov Z_OUT, [esp + 8]
176 mov ecx, [esp + 12]
177#endif
178#if CPUFAM_AMD64 && ABI_SYSV
179# define Z_OUT rdi
180 mov ecx, esi
181#endif
182#if CPUFAM_AMD64 && ABI_WIN
183# define Z_OUT r8
184 mov r8, rcx
185 mov ecx, edx
186#endif
187 endprologue
188
189 xgetbv
190 mov [Z_OUT + 0], eax
191 mov [Z_OUT + 4], edx
192
193#if CPUFAM_X86
194 popreg edi
195#endif
196 ret
197
198#undef Z_OUT
199ENDFUNC
200
201///--------------------------------------------------------------------------
202/// Checking `rdrand'.
203
204FUNC(dispatch_x86ish_rdrand)
205 // Enter with two arguments: a code OP requesting either `rdrand' (0)
206 // or `rdseed' (1), and a pointer X_OUT to a 32-bit word. Try to
207 // generate a random word using the requested instruction'. If
208 // successful, set *X_OUT to the generated word, and return zero;
209 // otherwise, return -1.
210
211#if CPUFAM_X86
212# define OP eax
213# define X_OUT edx
214# define COUNT ecx
215 mov OP, [SP + 4]
216 mov X_OUT, [SP + 8]
217#endif
218#if CPUFAM_AMD64 && ABI_SYSV
219# define OP edi
220# define X_OUT rsi
221# define COUNT ecx
222#endif
223#if CPUFAM_AMD64 && ABI_WIN
224# define OP rcx
225# define X_OUT rdx
226# define COUNT r8d
227#endif
228 endprologue
229
230 cmp OP, 0
231 mov COUNT, 16 // fairly persistent
232 jne 1f
233
2340: rdrand eax
235 jc 9f
236 dec COUNT
237 jnz 0b
238 jmp 8f
239
2401: rdseed eax
241 jc 9f
242 dec COUNT
243 jnz 1b
244 jmp 8f
245
246 // Failed to come up with a random value.
2478: mov eax, -1
248 ret
249
250 // Success.
2519: mov [X_OUT], eax
252 xor eax, eax
253 ret
254
255#undef X_OUT
256#undef COUNT
257
258ENDFUNC
259
260///----- That's all, folks --------------------------------------------------