progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / base / regdump-x86ish.S
CommitLineData
4bc8424a
MW
1/// -*- mode: asm; asm-comment-char: ?/ -*-
2///
3/// Register dump and debugging 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#include "regdump.h"
33
34 .text
35 .arch pentium4
36 .arch .xsave
37
38///--------------------------------------------------------------------------
39/// Main code.
40
41FUNC(regdump_gpsave)
42 endprologue
43 // On entry, r/esp should point to a return address and
44 // `REGDUMP_GPSIZE' bytes of word-aligned storage to be the
45 // general-purpose save area, with flags saved in the bottom word,
46 // r/eax saved in the fourth, and (on 32-bit x86) ebx in the fifth.
47 // On exit, the initial registers are saved in this space, and
48 // modified: r/ebp points to the general-purpose save area, ecx
49 // contains the number of bytes required in the extended save area,
50 // ebx is preserved on 32-bit x86, and other general-purpose
51 // registers are clobbered or used to communicate with
52 // `regdump_xtsave' below. Doing anything other than lowering the
53 // stack pointer and calling `regdump_xtsave' is not recommended.
54
55 // Other code will insist that df is clear.
56 cld
57
58 // Save r/ebp and establish it pointing to the save area.
a90d420c
MW
59 mov [SP + WORDSZ + REGIX_BP*WORDSZ], BP
60 lea BP, [SP + WORDSZ]
4bc8424a
MW
61
62 // Save the other easy general-purpose registers.
63#if !CPUFAM_X86
a90d420c 64 mov [BP + REGIX_BX*WORDSZ], BX
4bc8424a 65#endif
a90d420c
MW
66 mov [BP + REGIX_CX*WORDSZ], CX
67 mov [BP + REGIX_DX*WORDSZ], DX
68 mov [BP + REGIX_SI*WORDSZ], SI
69 mov [BP + REGIX_DI*WORDSZ], DI
4bc8424a 70#if CPUFAM_AMD64
a90d420c
MW
71 mov [BP + REGIX_R8*WORDSZ], r8
72 mov [BP + REGIX_R9*WORDSZ], r9
73 mov [BP + REGIX_R10*WORDSZ], r10
74 mov [BP + REGIX_R11*WORDSZ], r11
75 mov [BP + REGIX_R12*WORDSZ], r12
76 mov [BP + REGIX_R13*WORDSZ], r13
77 mov [BP + REGIX_R14*WORDSZ], r14
78 mov [BP + REGIX_R15*WORDSZ], r15
4bc8424a
MW
79#endif
80
81 // Determine the previous stack pointer and save it.
82#if CPUFAM_AMD64 && ABI_SYSV
a90d420c 83 lea AX, [BP + 128 + REGDUMP_GPSIZE]
4bc8424a 84#else
a90d420c 85 lea AX, [BP + REGDUMP_GPSIZE]
4bc8424a 86#endif
a90d420c 87 mov [BP + REGIX_SP*WORDSZ], AX
4bc8424a
MW
88
89 // Collect the return address and save it as r/eip.
a90d420c
MW
90 mov AX, [SP]
91 mov [BP + REGIX_IP*WORDSZ], AX
4bc8424a
MW
92
93 // Save the segment registers.
a90d420c
MW
94 lea AX, [BP + REGIX_GPLIM*WORDSZ]
95 mov [AX + 2*REGIX_CS], cs
96 mov [AX + 2*REGIX_DS], ds
97 mov [AX + 2*REGIX_SS], ss
98 mov [AX + 2*REGIX_ES], es
99 mov [AX + 2*REGIX_FS], fs
100 mov [AX + 2*REGIX_GS], gs
4bc8424a
MW
101
102 // Determine the extended save area size. Preserve ebx on 32-bit x86
103 // here, because the caller needs it for PLT-indirect calls.
104#if CPUFAM_X86
105 push ebx
106#endif
107 mov eax, 0x01
108 cpuid
109 test ecx, 1 << 26
110 je 1f
111
112 mov eax, 0x0d
113 mov ecx, 0x00
114 cpuid
115 add ecx, regmap_size + 64 // map + align
116 jmp 8f
117
1181: mov ecx, 512 + regmap_size + 16 // fxsave + map + align
119
120 // Done.
1218:
122#if CPUFAM_X86
123 pop ebx
124#endif
125 ret
126
127ENDFUNC
128
129FUNC(regdump_gprstr)
130 endprologue
131 // On entry, r/ebp points to a general-purpose save area, established
132 // by `regdump_gpsave'. On exit, the general-purpose registers
133 // (other than the stack pointer) are restored to their original
134 // values.
135
136 // We assume nobody actually fiddled with the segment registers. So
137 // just the actual integer registers to do.
a90d420c
MW
138 mov AX, [BP + REGIX_AX*WORDSZ]
139 mov BX, [BP + REGIX_BX*WORDSZ]
140 mov CX, [BP + REGIX_CX*WORDSZ]
141 mov DX, [BP + REGIX_DX*WORDSZ]
142 mov SI, [BP + REGIX_SI*WORDSZ]
143 mov DI, [BP + REGIX_DI*WORDSZ]
4bc8424a 144#if CPUFAM_AMD64
a90d420c
MW
145 mov r8, [BP + REGIX_R8*WORDSZ]
146 mov r9, [BP + REGIX_R9*WORDSZ]
147 mov r10, [BP + REGIX_R10*WORDSZ]
148 mov r11, [BP + REGIX_R11*WORDSZ]
149 mov r12, [BP + REGIX_R12*WORDSZ]
150 mov r13, [BP + REGIX_R13*WORDSZ]
151 mov r14, [BP + REGIX_R14*WORDSZ]
152 mov r15, [BP + REGIX_R15*WORDSZ]
4bc8424a 153#endif
a90d420c 154 mov BP, [BP + REGIX_BP*WORDSZ]
4bc8424a
MW
155
156 // Done.
157 ret
158
159ENDFUNC
160
161#ifdef CPUFAM_AMD64
162# define fxsave fxsave64
163# define fxrstor fxrstor64
164# define xsave xsave64
165# define xrstor xrstor64
166#endif
167
168FUNC(regdump_xtsave)
169 endprologue
170 // On entry, r/esp points to a return address and extended save area,
171 // of size determined by `regdump_gpsave' above. On exit, the save
172 // area is filled in and a handy map placed at its base, the x87
173 // floating-point state is reset, r/ebp is left pointing to the
174 // register map, ebx is preserved on 32-bit x86, and the other
175 // general registers are clobbered.
176
177 // Start by filling in the easy parts of the map.
a90d420c
MW
178 mov [SP + WORDSZ + regmap_gp], BP
179 lea BP, [SP + WORDSZ]
4bc8424a
MW
180
181 xor eax, eax // clears rax too on amd64
a90d420c 182 mov [BP + regmap_avx], AX
4bc8424a
MW
183
184 // Find out whether we use `xsave'. (Preserve ebx.)
185#if CPUFAM_X86
186 push ebx
187#endif
188 mov eax, 0x01
189 cpuid
190 test ecx, 1 << 26
191 je 5f
192
193 // We have the `xsave' machinery. Select the base address.
a90d420c
MW
194 lea SI, [SP + WORDSZ + regmap_size + 63]
195 and SI, ~63
196 mov [BP + regmap_fx], SI
4bc8424a
MW
197
198 // Clear out the header area.
199 xor eax, eax
a90d420c 200 lea DI, [SI + 512]
4bc8424a
MW
201 mov ecx, 16
202 rep stosd
203
204 // Save the registers.
205 mov eax, 0x00000007
206 xor edx, edx
a90d420c 207 xsave [SI]
4bc8424a
MW
208
209 // Establish the AVX pointer, if available.
a90d420c 210 test dword ptr [SI + 512], 4 // = xstate_bv
4bc8424a
MW
211 je 8f
212
213 mov eax, 13
214 mov ecx, 2
215 cpuid
a90d420c
MW
216 add BX, SI
217 mov [BP + regmap_avx], BX
4bc8424a
MW
218
219 jmp 8f
220
221 // We have only `fxsave'. Set the base address.
a90d420c
MW
2225: lea SI, [SP + WORDSZ + regmap_size + 15]
223 and SI, ~15
224 mov [BP + regmap_fx], SI
4bc8424a
MW
225
226 // Save the registers.
a90d420c 227 fxsave [SI]
4bc8424a
MW
228
229 // Clear the x87 state; otherwise it can cause trouble later.
2308: fninit
231
232 // Done.
233#if CPUFAM_X86
234 pop ebx
235#endif
236 ret
237
238ENDFUNC
239
240FUNC(regdump_xtrstr)
241 endprologue
242 // On entry, r/ebp points to a register-save map. On exit, the
243 // extended registers are restored from the save area; r/ebp is left
244 // pointing to the general-purpose save area, ebx is preserved on
245 // 32-bit x86, and the other general registers are clobbered.
246
247 // Find the extended register dump.
a90d420c 248 mov SI, [BP + regmap_fx]
4bc8424a
MW
249
250 // Probe to find out whether we have `xsave'.
251#if CPUFAM_X86
252 push ebx
253#endif
254 mov eax, 0x01
255 cpuid
256 test ecx, 1 << 26
257 je 1f
258
259 // We have the `xsave' machinery.
260 mov eax, 0x00000007
261 xor edx, edx
a90d420c 262 xrstor [SI]
4bc8424a
MW
263 jmp 8f
264
265 // We must fake it up.
a90d420c 2661: fxrstor [SI]
4bc8424a
MW
267
268 // Done.
a90d420c 2698: mov BP, [BP + regmap_gp]
4bc8424a
MW
270#if CPUFAM_X86
271 pop ebx
272#endif
273 ret
274
275ENDFUNC
276
277///----- That's all, folks --------------------------------------------------