1 #pragma once
2 
3 #ifdef __cplusplus
4 extern "C"
5 {
6 #endif
7 
8 #if defined(__GNUC__)
9 
10 FORCEINLINE
11 VOID
12 __lgdt(_Out_ PVOID Descriptor)
13 {
14     PVOID* desc = (PVOID*)Descriptor;
15     __asm__ __volatile__(
16         "lgdt %0"
17             : "=m" (*desc)
18             : /* no input */
19             : "memory");
20 }
21 
22 FORCEINLINE
23 VOID
24 __sgdt(_Out_ PVOID Descriptor)
25 {
26     PVOID* desc = (PVOID*)Descriptor;
27     __asm__ __volatile__(
28         "sgdt %0"
29             : "=m" (*desc)
30             : /* no input */
31             : "memory");
32 }
33 
34 FORCEINLINE
35 VOID
36 Ke386FxStore(IN PFX_SAVE_AREA SaveArea)
37 {
38     asm volatile ("fxrstor (%0)" : : "r"(SaveArea));
39 }
40 
41 FORCEINLINE
42 VOID
43 Ke386FxSave(IN PFX_SAVE_AREA SaveArea)
44 {
45     asm volatile ("fxsave (%0)" : : "r"(SaveArea));
46 }
47 
48 FORCEINLINE
49 VOID
50 Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)
51 {
52     asm volatile ("fnsave (%0); wait" : : "r"(SaveArea));
53 }
54 
55 FORCEINLINE
56 VOID
57 Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)
58 {
59     extern ULONG KeI386FxsrPresent;
60     if (KeI386FxsrPresent)
61     {
62         __asm__ __volatile__ ("fxsave %0\n" : : "m"(*SaveArea));
63     }
64     else
65     {
66         __asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(*SaveArea));
67     }
68 }
69 
70 FORCEINLINE
71 VOID
72 Ke386RestoreFpuState(_In_ PFX_SAVE_AREA SaveArea)
73 {
74     extern ULONG KeI386FxsrPresent;
75     if (KeI386FxsrPresent)
76     {
77         __asm__ __volatile__ ("fxrstor %0\n" : : "m"(*SaveArea));
78     }
79     else
80     {
81         __asm__ __volatile__ ("frstor %0\n\t" : "=m" (*SaveArea));
82     }
83 }
84 
85 FORCEINLINE
86 VOID
87 Ke386ClearFpExceptions(VOID)
88 {
89     __asm__ __volatile__ ("fnclex");
90 }
91 
92 FORCEINLINE
93 VOID
94 __sldt(PVOID Descriptor)
95 {
96     __asm__ __volatile__(
97         "sldt %0"
98             : "=m" (*((short*)Descriptor))
99             : /* no input */
100             : "memory");
101 }
102 
103 #define Ke386SetLocalDescriptorTable(X) \
104     __asm__("lldt %w0\n\t" \
105     : /* no outputs */ \
106     : "q" (X));
107 
108 #define Ke386SetTr(X)                   __asm__ __volatile__("ltr %%ax" : :"a" (X));
109 
110 FORCEINLINE
111 USHORT
112 Ke386GetTr(VOID)
113 {
114     USHORT Tr;
115     __asm__("str %0\n\t"
116     : "=m" (Tr));
117     return Tr;
118 }
119 
120 #define _Ke386GetSeg(N)           ({ \
121                                      unsigned int __d; \
122                                      __asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \
123                                      __d; \
124                                   })
125 
126 #define _Ke386SetSeg(N,X)         __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
127 
128 #define Ke386FnInit()               __asm__("fninit\n\t");
129 #define Ke386ClearDirectionFlag()   __asm__ __volatile__ ("cld")
130 
131 
132 //
133 // CR Macros
134 //
135 #define Ke386SetCr2(X)              __asm__ __volatile__("movl %0,%%cr2" : :"r" (X));
136 
137 //
138 // Segment Macros
139 //
140 #define Ke386GetSs()                _Ke386GetSeg(ss)
141 #define Ke386GetFs()                _Ke386GetSeg(fs)
142 #define Ke386GetDs()                _Ke386GetSeg(ds)
143 #define Ke386GetEs()                _Ke386GetSeg(es)
144 #define Ke386GetGs()                _Ke386GetSeg(gs)
145 #define Ke386SetFs(X)               _Ke386SetSeg(fs, X)
146 #define Ke386SetDs(X)               _Ke386SetSeg(ds, X)
147 #define Ke386SetEs(X)               _Ke386SetSeg(es, X)
148 #define Ke386SetSs(X)               _Ke386SetSeg(ss, X)
149 #define Ke386SetGs(X)               _Ke386SetSeg(gs, X)
150 
151 #elif defined(_MSC_VER)
152 
153 FORCEINLINE
154 VOID
155 Ke386FnInit(VOID)
156 {
157     __asm fninit;
158 }
159 
160 FORCEINLINE
161 VOID
162 __sgdt(OUT PVOID Descriptor)
163 {
164     __asm
165     {
166         mov eax, Descriptor
167         sgdt [eax]
168     }
169 }
170 
171 FORCEINLINE
172 VOID
173 __fxsave(OUT PFX_SAVE_AREA SaveArea)
174 {
175     __asm mov eax, SaveArea
176     __asm fxsave [eax]
177 }
178 
179 FORCEINLINE
180 VOID
181 __fxrstor(IN PFX_SAVE_AREA SaveArea)
182 {
183     __asm mov eax, SaveArea
184     __asm fxrstor [eax]
185 }
186 
187 FORCEINLINE
188 VOID
189 __frstor(_In_ PFX_SAVE_AREA SaveArea)
190 {
191     __asm mov eax, SaveArea
192     __asm frstor [eax]
193 }
194 
195 FORCEINLINE
196 VOID
197 __fnsave(OUT PFLOATING_SAVE_AREA SaveArea)
198 {
199     __asm mov eax, SaveArea
200     __asm fnsave [eax]
201     __asm wait;
202 }
203 
204 FORCEINLINE
205 VOID
206 __lgdt(IN PVOID Descriptor)
207 {
208     __asm
209     {
210         mov eax, Descriptor
211         lgdt [eax]
212     }
213 }
214 
215 FORCEINLINE
216 VOID
217 __sldt(PVOID Descriptor)
218 {
219     __asm
220     {
221         sldt ax
222         mov ecx, Descriptor
223         mov [ecx], ax
224     }
225 }
226 
227 FORCEINLINE
228 VOID
229 Ke386SetLocalDescriptorTable(IN USHORT Descriptor)
230 {
231     __asm lldt Descriptor;
232 }
233 
234 FORCEINLINE
235 VOID
236 Ke386SetTr(IN USHORT Tr)
237 {
238     __asm ltr Tr;
239 }
240 
241 FORCEINLINE
242 USHORT
243 Ke386GetTr(VOID)
244 {
245     __asm str ax;
246 }
247 
248 //
249 // CR Macros
250 //
251 FORCEINLINE
252 VOID
253 Ke386SetCr2(IN ULONG Value)
254 {
255     __asm mov eax, Value;
256     __asm mov cr2, eax;
257 }
258 
259 //
260 // Segment Macros
261 //
262 FORCEINLINE
263 USHORT
264 Ke386GetSs(VOID)
265 {
266     __asm mov ax, ss;
267 }
268 
269 FORCEINLINE
270 USHORT
271 Ke386GetFs(VOID)
272 {
273     __asm mov ax, fs;
274 }
275 
276 FORCEINLINE
277 USHORT
278 Ke386GetDs(VOID)
279 {
280     __asm mov ax, ds;
281 }
282 
283 FORCEINLINE
284 USHORT
285 Ke386GetEs(VOID)
286 {
287     __asm mov ax, es;
288 }
289 
290 FORCEINLINE
291 VOID
292 Ke386SetSs(IN USHORT Value)
293 {
294     __asm mov ax, Value;
295     __asm mov ss, ax;
296 }
297 
298 FORCEINLINE
299 VOID
300 Ke386SetFs(IN USHORT Value)
301 {
302     __asm mov ax, Value;
303     __asm mov fs, ax;
304 }
305 
306 FORCEINLINE
307 VOID
308 Ke386SetDs(IN USHORT Value)
309 {
310     __asm mov ax, Value;
311     __asm mov ds, ax;
312 }
313 
314 FORCEINLINE
315 VOID
316 Ke386SetEs(IN USHORT Value)
317 {
318     __asm mov ax, Value;
319     __asm mov es, ax;
320 }
321 
322 FORCEINLINE
323 VOID
324 Ke386SetGs(IN USHORT Value)
325 {
326     __asm mov ax, Value;
327     __asm mov gs, ax;
328 }
329 
330 extern ULONG KeI386FxsrPresent;
331 
332 FORCEINLINE
333 VOID
334 Ke386SaveFpuState(IN PVOID SaveArea)
335 {
336     if (KeI386FxsrPresent)
337     {
338         __fxsave((PFX_SAVE_AREA)SaveArea);
339     }
340     else
341     {
342         __fnsave((PFLOATING_SAVE_AREA)SaveArea);
343     }
344 }
345 
346 FORCEINLINE
347 VOID
348 Ke386RestoreFpuState(_In_ PVOID SaveArea)
349 {
350     if (KeI386FxsrPresent)
351     {
352         __fxrstor((PFX_SAVE_AREA)SaveArea);
353     }
354     else
355     {
356         __frstor((PFX_SAVE_AREA)SaveArea);
357     }
358 }
359 
360 FORCEINLINE
361 VOID
362 Ke386ClearFpExceptions(VOID)
363 {
364     __asm fnclex;
365 }
366 
367 #define Ke386FnSave __fnsave
368 #define Ke386FxSave __fxsave
369 // The name suggest, that the original author didn't understand what frstor means
370 #define Ke386FxStore __fxrstor
371 
372 #else
373 #error Unknown compiler for inline assembler
374 #endif
375 
376 #define Ke386GetGlobalDescriptorTable __sgdt
377 #define Ke386SetGlobalDescriptorTable __lgdt
378 #define Ke386GetLocalDescriptorTable __sldt
379 
380 #ifdef __cplusplus
381 } // extern "C"
382 #endif
383 
384 /* EOF */
385