VirtualBox

source: vbox/trunk/include/iprt/asm-amd64-x86.h@ 77807

Last change on this file since 77807 was 76886, checked in by vboxsync, 6 years ago

VMM (and related changes): Add support for Shanghai/Zhaoxin CPUs. Modified and improved contribution by Journey Ren submitted under MIT license. Thank you!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 77.7 KB
RevLine 
[1]1/** @file
[29245]2 * IPRT - AMD64 and x86 Specific Assembly Functions.
[1]3 */
4
5/*
[76553]6 * Copyright (C) 2006-2019 Oracle Corporation
[1]7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
[5999]11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
[1]24 */
25
[76557]26#ifndef IPRT_INCLUDED_asm_amd64_x86_h
27#define IPRT_INCLUDED_asm_amd64_x86_h
[76507]28#ifndef RT_WITHOUT_PRAGMA_ONCE
29# pragma once
30#endif
[1]31
[29250]32#include <iprt/types.h>
[54254]33#include <iprt/assert.h>
[29270]34#if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)
35# error "Not on AMD64 or x86"
36#endif
[1]37
[29250]38#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN
[62634]39# pragma warning(push)
40# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
41# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
[29250]42# include <intrin.h>
[62634]43# pragma warning(pop)
[1]44 /* Emit the intrinsics at all optimization levels. */
[29250]45# pragma intrinsic(_ReadWriteBarrier)
46# pragma intrinsic(__cpuid)
47# pragma intrinsic(_enable)
48# pragma intrinsic(_disable)
49# pragma intrinsic(__rdtsc)
50# pragma intrinsic(__readmsr)
51# pragma intrinsic(__writemsr)
52# pragma intrinsic(__outbyte)
53# pragma intrinsic(__outbytestring)
54# pragma intrinsic(__outword)
55# pragma intrinsic(__outwordstring)
56# pragma intrinsic(__outdword)
57# pragma intrinsic(__outdwordstring)
58# pragma intrinsic(__inbyte)
59# pragma intrinsic(__inbytestring)
60# pragma intrinsic(__inword)
61# pragma intrinsic(__inwordstring)
62# pragma intrinsic(__indword)
63# pragma intrinsic(__indwordstring)
64# pragma intrinsic(__invlpg)
65# pragma intrinsic(__wbinvd)
66# pragma intrinsic(__readcr0)
67# pragma intrinsic(__readcr2)
68# pragma intrinsic(__readcr3)
69# pragma intrinsic(__readcr4)
70# pragma intrinsic(__writecr0)
71# pragma intrinsic(__writecr3)
72# pragma intrinsic(__writecr4)
73# pragma intrinsic(__readdr)
74# pragma intrinsic(__writedr)
75# ifdef RT_ARCH_AMD64
76# pragma intrinsic(__readcr8)
77# pragma intrinsic(__writecr8)
[1]78# endif
[60201]79# if RT_INLINE_ASM_USES_INTRIN >= 14
80# pragma intrinsic(__halt)
81# endif
[48572]82# if RT_INLINE_ASM_USES_INTRIN >= 15
83# pragma intrinsic(__readeflags)
84# pragma intrinsic(__writeeflags)
[54251]85# pragma intrinsic(__rdtscp)
[48572]86# endif
[1]87#endif
88
89
[58749]90/*
[75131]91 * Undefine all symbols we have Watcom C/C++ #pragma aux'es for.
[58749]92 */
93#if defined(__WATCOMC__) && ARCH_BITS == 16
94# include "asm-amd64-x86-watcom-16.h"
95#elif defined(__WATCOMC__) && ARCH_BITS == 32
96# include "asm-amd64-x86-watcom-32.h"
97#endif
[29245]98
[58749]99
[29245]100/** @defgroup grp_rt_asm_amd64_x86 AMD64 and x86 Specific ASM Routines
101 * @ingroup grp_rt_asm
[1]102 * @{
103 */
104
[54254]105/** @todo find a more proper place for these structures? */
106
[1]107#pragma pack(1)
108/** IDTR */
109typedef struct RTIDTR
110{
111 /** Size of the IDT. */
112 uint16_t cbIdt;
113 /** Address of the IDT. */
[58705]114#if ARCH_BITS != 64
115 uint32_t pIdt;
116#else
117 uint64_t pIdt;
118#endif
[68606]119} RTIDTR, RT_FAR *PRTIDTR;
[1]120#pragma pack()
121
122#pragma pack(1)
[54254]123/** @internal */
124typedef struct RTIDTRALIGNEDINT
125{
126 /** Alignment padding. */
[58705]127 uint16_t au16Padding[ARCH_BITS == 64 ? 3 : 1];
[54254]128 /** The IDTR structure. */
129 RTIDTR Idtr;
130} RTIDTRALIGNEDINT;
131#pragma pack()
132
133/** Wrapped RTIDTR for preventing misalignment exceptions. */
134typedef union RTIDTRALIGNED
135{
136 /** Try make sure this structure has optimal alignment. */
137 uint64_t auAlignmentHack[ARCH_BITS == 64 ? 2 : 1];
138 /** Aligned structure. */
139 RTIDTRALIGNEDINT s;
140} RTIDTRALIGNED;
[58705]141AssertCompileSize(RTIDTRALIGNED, ((ARCH_BITS == 64) + 1) * 8);
[54254]142/** Pointer to a an RTIDTR alignment wrapper. */
[68606]143typedef RTIDTRALIGNED RT_FAR *PRIDTRALIGNED;
[54254]144
145
146#pragma pack(1)
[1]147/** GDTR */
148typedef struct RTGDTR
149{
150 /** Size of the GDT. */
151 uint16_t cbGdt;
152 /** Address of the GDT. */
[58705]153#if ARCH_BITS != 64
154 uint32_t pGdt;
155#else
156 uint64_t pGdt;
157#endif
[68606]158} RTGDTR, RT_FAR *PRTGDTR;
[1]159#pragma pack()
160
[54254]161#pragma pack(1)
162/** @internal */
163typedef struct RTGDTRALIGNEDINT
164{
165 /** Alignment padding. */
[58705]166 uint16_t au16Padding[ARCH_BITS == 64 ? 3 : 1];
[54254]167 /** The GDTR structure. */
168 RTGDTR Gdtr;
169} RTGDTRALIGNEDINT;
170#pragma pack()
[1]171
[54254]172/** Wrapped RTGDTR for preventing misalignment exceptions. */
173typedef union RTGDTRALIGNED
174{
175 /** Try make sure this structure has optimal alignment. */
176 uint64_t auAlignmentHack[ARCH_BITS == 64 ? 2 : 1];
177 /** Aligned structure. */
178 RTGDTRALIGNEDINT s;
179} RTGDTRALIGNED;
[58705]180AssertCompileSize(RTIDTRALIGNED, ((ARCH_BITS == 64) + 1) * 8);
[54254]181/** Pointer to a an RTGDTR alignment wrapper. */
[68606]182typedef RTGDTRALIGNED RT_FAR *PRGDTRALIGNED;
[54254]183
184
[1]185/**
186 * Gets the content of the IDTR CPU register.
187 * @param pIdtr Where to store the IDTR contents.
188 */
189#if RT_INLINE_ASM_EXTERNAL
[75131]190RT_ASM_DECL_PRAGMA_WATCOM(void) ASMGetIDTR(PRTIDTR pIdtr);
[1]191#else
192DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)
193{
194# if RT_INLINE_ASM_GNU_STYLE
[19305]195 __asm__ __volatile__("sidt %0" : "=m" (*pIdtr));
[1]196# else
197 __asm
198 {
[3636]199# ifdef RT_ARCH_AMD64
[1]200 mov rax, [pIdtr]
201 sidt [rax]
202# else
203 mov eax, [pIdtr]
204 sidt [eax]
205# endif
206 }
207# endif
208}
209#endif
210
211
212/**
[54254]213 * Gets the content of the IDTR.LIMIT CPU register.
214 * @returns IDTR limit.
215 */
216#if RT_INLINE_ASM_EXTERNAL
[75131]217RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMGetIdtrLimit(void);
[54254]218#else
219DECLINLINE(uint16_t) ASMGetIdtrLimit(void)
220{
221 RTIDTRALIGNED TmpIdtr;
222# if RT_INLINE_ASM_GNU_STYLE
223 __asm__ __volatile__("sidt %0" : "=m" (TmpIdtr.s.Idtr));
224# else
225 __asm
226 {
227 sidt [TmpIdtr.s.Idtr]
228 }
229# endif
230 return TmpIdtr.s.Idtr.cbIdt;
231}
232#endif
233
234
235/**
[1]236 * Sets the content of the IDTR CPU register.
237 * @param pIdtr Where to load the IDTR contents from
238 */
239#if RT_INLINE_ASM_EXTERNAL
[75131]240RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetIDTR(const RTIDTR RT_FAR *pIdtr);
[1]241#else
[68606]242DECLINLINE(void) ASMSetIDTR(const RTIDTR RT_FAR *pIdtr)
[1]243{
244# if RT_INLINE_ASM_GNU_STYLE
[19305]245 __asm__ __volatile__("lidt %0" : : "m" (*pIdtr));
[1]246# else
247 __asm
248 {
[3636]249# ifdef RT_ARCH_AMD64
[1]250 mov rax, [pIdtr]
251 lidt [rax]
252# else
253 mov eax, [pIdtr]
254 lidt [eax]
255# endif
256 }
257# endif
258}
259#endif
260
261
262/**
263 * Gets the content of the GDTR CPU register.
264 * @param pGdtr Where to store the GDTR contents.
265 */
266#if RT_INLINE_ASM_EXTERNAL
[75131]267RT_ASM_DECL_PRAGMA_WATCOM(void) ASMGetGDTR(PRTGDTR pGdtr);
[1]268#else
269DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)
270{
271# if RT_INLINE_ASM_GNU_STYLE
[19305]272 __asm__ __volatile__("sgdt %0" : "=m" (*pGdtr));
[1]273# else
274 __asm
275 {
[3636]276# ifdef RT_ARCH_AMD64
[1]277 mov rax, [pGdtr]
278 sgdt [rax]
279# else
280 mov eax, [pGdtr]
281 sgdt [eax]
282# endif
283 }
284# endif
285}
286#endif
287
[50424]288
[1]289/**
[50424]290 * Sets the content of the GDTR CPU register.
[57926]291 * @param pGdtr Where to load the GDTR contents from
[50424]292 */
293#if RT_INLINE_ASM_EXTERNAL
[75131]294RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetGDTR(const RTGDTR RT_FAR *pGdtr);
[50424]295#else
[68606]296DECLINLINE(void) ASMSetGDTR(const RTGDTR RT_FAR *pGdtr)
[50424]297{
298# if RT_INLINE_ASM_GNU_STYLE
299 __asm__ __volatile__("lgdt %0" : : "m" (*pGdtr));
300# else
301 __asm
302 {
303# ifdef RT_ARCH_AMD64
304 mov rax, [pGdtr]
305 lgdt [rax]
306# else
307 mov eax, [pGdtr]
308 lgdt [eax]
309# endif
310 }
311# endif
312}
313#endif
314
315
316
317/**
[1]318 * Get the cs register.
319 * @returns cs.
320 */
321#if RT_INLINE_ASM_EXTERNAL
[75131]322RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetCS(void);
[1]323#else
324DECLINLINE(RTSEL) ASMGetCS(void)
325{
326 RTSEL SelCS;
327# if RT_INLINE_ASM_GNU_STYLE
328 __asm__ __volatile__("movw %%cs, %0\n\t" : "=r" (SelCS));
329# else
330 __asm
331 {
332 mov ax, cs
333 mov [SelCS], ax
334 }
335# endif
336 return SelCS;
337}
338#endif
339
340
341/**
342 * Get the DS register.
343 * @returns DS.
344 */
345#if RT_INLINE_ASM_EXTERNAL
[75131]346RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetDS(void);
[1]347#else
348DECLINLINE(RTSEL) ASMGetDS(void)
349{
350 RTSEL SelDS;
351# if RT_INLINE_ASM_GNU_STYLE
352 __asm__ __volatile__("movw %%ds, %0\n\t" : "=r" (SelDS));
353# else
354 __asm
355 {
356 mov ax, ds
357 mov [SelDS], ax
358 }
359# endif
360 return SelDS;
361}
362#endif
363
364
365/**
366 * Get the ES register.
367 * @returns ES.
368 */
369#if RT_INLINE_ASM_EXTERNAL
[75131]370RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetES(void);
[1]371#else
372DECLINLINE(RTSEL) ASMGetES(void)
373{
374 RTSEL SelES;
375# if RT_INLINE_ASM_GNU_STYLE
376 __asm__ __volatile__("movw %%es, %0\n\t" : "=r" (SelES));
377# else
378 __asm
379 {
380 mov ax, es
381 mov [SelES], ax
382 }
383# endif
384 return SelES;
385}
386#endif
387
388
389/**
390 * Get the FS register.
391 * @returns FS.
392 */
393#if RT_INLINE_ASM_EXTERNAL
[75131]394RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetFS(void);
[1]395#else
396DECLINLINE(RTSEL) ASMGetFS(void)
397{
398 RTSEL SelFS;
399# if RT_INLINE_ASM_GNU_STYLE
400 __asm__ __volatile__("movw %%fs, %0\n\t" : "=r" (SelFS));
401# else
402 __asm
403 {
404 mov ax, fs
405 mov [SelFS], ax
406 }
407# endif
408 return SelFS;
409}
410# endif
411
412
413/**
414 * Get the GS register.
415 * @returns GS.
416 */
417#if RT_INLINE_ASM_EXTERNAL
[75131]418RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetGS(void);
[1]419#else
420DECLINLINE(RTSEL) ASMGetGS(void)
421{
422 RTSEL SelGS;
423# if RT_INLINE_ASM_GNU_STYLE
424 __asm__ __volatile__("movw %%gs, %0\n\t" : "=r" (SelGS));
425# else
426 __asm
427 {
428 mov ax, gs
429 mov [SelGS], ax
430 }
431# endif
432 return SelGS;
433}
434#endif
435
436
437/**
438 * Get the SS register.
439 * @returns SS.
440 */
441#if RT_INLINE_ASM_EXTERNAL
[75131]442RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetSS(void);
[1]443#else
444DECLINLINE(RTSEL) ASMGetSS(void)
445{
446 RTSEL SelSS;
447# if RT_INLINE_ASM_GNU_STYLE
448 __asm__ __volatile__("movw %%ss, %0\n\t" : "=r" (SelSS));
449# else
450 __asm
451 {
452 mov ax, ss
453 mov [SelSS], ax
454 }
455# endif
456 return SelSS;
457}
458#endif
459
460
461/**
462 * Get the TR register.
463 * @returns TR.
464 */
465#if RT_INLINE_ASM_EXTERNAL
[75131]466RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetTR(void);
[1]467#else
468DECLINLINE(RTSEL) ASMGetTR(void)
469{
470 RTSEL SelTR;
471# if RT_INLINE_ASM_GNU_STYLE
472 __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));
473# else
474 __asm
475 {
476 str ax
477 mov [SelTR], ax
478 }
479# endif
480 return SelTR;
481}
482#endif
483
484
485/**
[46925]486 * Get the LDTR register.
487 * @returns LDTR.
488 */
489#if RT_INLINE_ASM_EXTERNAL
[75131]490RT_ASM_DECL_PRAGMA_WATCOM(RTSEL) ASMGetLDTR(void);
[46925]491#else
492DECLINLINE(RTSEL) ASMGetLDTR(void)
493{
494 RTSEL SelLDTR;
495# if RT_INLINE_ASM_GNU_STYLE
496 __asm__ __volatile__("sldt %w0\n\t" : "=r" (SelLDTR));
497# else
498 __asm
499 {
500 sldt ax
501 mov [SelLDTR], ax
502 }
503# endif
504 return SelLDTR;
505}
506#endif
507
508
509/**
[48990]510 * Get the access rights for the segment selector.
511 *
[50425]512 * @returns The access rights on success or UINT32_MAX on failure.
[48990]513 * @param uSel The selector value.
514 *
[50425]515 * @remarks Using UINT32_MAX for failure is chosen because valid access rights
516 * always have bits 0:7 as 0 (on both Intel & AMD).
[48990]517 */
518#if RT_INLINE_ASM_EXTERNAL
[75131]519RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMGetSegAttr(uint32_t uSel);
[48990]520#else
[49001]521DECLINLINE(uint32_t) ASMGetSegAttr(uint32_t uSel)
[48990]522{
523 uint32_t uAttr;
524 /* LAR only accesses 16-bit of the source operand, but eax for the
525 destination operand is required for getting the full 32-bit access rights. */
526# if RT_INLINE_ASM_GNU_STYLE
[48993]527 __asm__ __volatile__("lar %1, %%eax\n\t"
[48990]528 "jz done%=\n\t"
[48993]529 "movl $0xffffffff, %%eax\n\t"
[48990]530 "done%=:\n\t"
[48993]531 "movl %%eax, %0\n\t"
[48990]532 : "=r" (uAttr)
533 : "r" (uSel)
534 : "cc", "%eax");
535# else
536 __asm
537 {
[48993]538 lar eax, [uSel]
[48990]539 jz done
[48993]540 mov eax, 0ffffffffh
[48990]541 done:
[48993]542 mov [uAttr], eax
[48990]543 }
544# endif
545 return uAttr;
546}
547#endif
548
549
550/**
[1]551 * Get the [RE]FLAGS register.
552 * @returns [RE]FLAGS.
553 */
[48572]554#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]555RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTREG) ASMGetFlags(void);
[1]556#else
557DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
558{
559 RTCCUINTREG uFlags;
560# if RT_INLINE_ASM_GNU_STYLE
[3636]561# ifdef RT_ARCH_AMD64
[1]562 __asm__ __volatile__("pushfq\n\t"
563 "popq %0\n\t"
[22279]564 : "=r" (uFlags));
[1]565# else
566 __asm__ __volatile__("pushfl\n\t"
567 "popl %0\n\t"
[22279]568 : "=r" (uFlags));
[1]569# endif
[48572]570# elif RT_INLINE_ASM_USES_INTRIN >= 15
571 uFlags = __readeflags();
[1]572# else
573 __asm
574 {
[3636]575# ifdef RT_ARCH_AMD64
[1]576 pushfq
577 pop [uFlags]
578# else
579 pushfd
580 pop [uFlags]
581# endif
582 }
583# endif
584 return uFlags;
585}
586#endif
587
588
589/**
590 * Set the [RE]FLAGS register.
591 * @param uFlags The new [RE]FLAGS value.
592 */
[48572]593#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]594RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetFlags(RTCCUINTREG uFlags);
[1]595#else
596DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
597{
598# if RT_INLINE_ASM_GNU_STYLE
[3636]599# ifdef RT_ARCH_AMD64
[1]600 __asm__ __volatile__("pushq %0\n\t"
601 "popfq\n\t"
[5550]602 : : "g" (uFlags));
[1]603# else
604 __asm__ __volatile__("pushl %0\n\t"
605 "popfl\n\t"
[5550]606 : : "g" (uFlags));
[1]607# endif
[48572]608# elif RT_INLINE_ASM_USES_INTRIN >= 15
609 __writeeflags(uFlags);
[1]610# else
611 __asm
612 {
[3636]613# ifdef RT_ARCH_AMD64
[1]614 push [uFlags]
615 popfq
616# else
617 push [uFlags]
618 popfd
619# endif
620 }
621# endif
622}
623#endif
624
625
626/**
[57220]627 * Modifies the [RE]FLAGS register.
628 * @returns Original value.
629 * @param fAndEfl Flags to keep (applied first).
630 * @param fOrEfl Flags to be set.
631 */
632#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]633RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTREG) ASMChangeFlags(RTCCUINTREG fAndEfl, RTCCUINTREG fOrEfl);
[57220]634#else
635DECLINLINE(RTCCUINTREG) ASMChangeFlags(RTCCUINTREG fAndEfl, RTCCUINTREG fOrEfl)
636{
637 RTCCUINTREG fOldEfl;
638# if RT_INLINE_ASM_GNU_STYLE
639# ifdef RT_ARCH_AMD64
640 __asm__ __volatile__("pushfq\n\t"
641 "movq (%%rsp), %0\n\t"
642 "andq %0, %1\n\t"
643 "orq %3, %1\n\t"
644 "mov %1, (%%rsp)\n\t"
645 "popfq\n\t"
[57312]646 : "=&r" (fOldEfl),
[57250]647 "=r" (fAndEfl)
[57220]648 : "1" (fAndEfl),
[57312]649 "rn" (fOrEfl) );
[57220]650# else
651 __asm__ __volatile__("pushfl\n\t"
652 "movl (%%esp), %0\n\t"
653 "andl %1, (%%esp)\n\t"
654 "orl %2, (%%esp)\n\t"
655 "popfl\n\t"
[57312]656 : "=&r" (fOldEfl)
657 : "rn" (fAndEfl),
658 "rn" (fOrEfl) );
[57220]659# endif
660# elif RT_INLINE_ASM_USES_INTRIN >= 15
661 fOldEfl = __readeflags();
662 __writeeflags((fOldEfl & fAndEfl) | fOrEfl);
663# else
664 __asm
665 {
666# ifdef RT_ARCH_AMD64
667 mov rdx, [fAndEfl]
668 mov rcx, [fOrEfl]
669 pushfq
670 mov rax, [rsp]
671 and rdx, rax
672 or rdx, rcx
673 mov [rsp], rdx
674 popfq
675 mov [fOldEfl], rax
676# else
677 mov edx, [fAndEfl]
678 mov ecx, [fOrEfl]
679 pushfd
680 mov eax, [esp]
681 and edx, eax
682 or edx, ecx
683 mov [esp], edx
684 popfd
685 mov [fOldEfl], eax
686# endif
687 }
688# endif
689 return fOldEfl;
690}
691#endif
692
693
694/**
695 * Modifies the [RE]FLAGS register by ORing in one or more flags.
696 * @returns Original value.
697 * @param fOrEfl The flags to be set (ORed in).
698 */
699#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]700RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTREG) ASMAddFlags(RTCCUINTREG fOrEfl);
[57220]701#else
702DECLINLINE(RTCCUINTREG) ASMAddFlags(RTCCUINTREG fOrEfl)
703{
704 RTCCUINTREG fOldEfl;
705# if RT_INLINE_ASM_GNU_STYLE
706# ifdef RT_ARCH_AMD64
707 __asm__ __volatile__("pushfq\n\t"
708 "movq (%%rsp), %0\n\t"
709 "orq %1, (%%rsp)\n\t"
710 "popfq\n\t"
[57312]711 : "=&r" (fOldEfl)
712 : "rn" (fOrEfl) );
[57220]713# else
714 __asm__ __volatile__("pushfl\n\t"
715 "movl (%%esp), %0\n\t"
716 "orl %1, (%%esp)\n\t"
717 "popfl\n\t"
[57312]718 : "=&r" (fOldEfl)
719 : "rn" (fOrEfl) );
[57220]720# endif
721# elif RT_INLINE_ASM_USES_INTRIN >= 15
722 fOldEfl = __readeflags();
723 __writeeflags(fOldEfl | fOrEfl);
724# else
725 __asm
726 {
727# ifdef RT_ARCH_AMD64
728 mov rcx, [fOrEfl]
729 pushfq
730 mov rdx, [rsp]
731 or [rsp], rcx
732 popfq
733 mov [fOldEfl], rax
734# else
735 mov ecx, [fOrEfl]
736 pushfd
737 mov edx, [esp]
738 or [esp], ecx
739 popfd
740 mov [fOldEfl], eax
741# endif
742 }
743# endif
744 return fOldEfl;
745}
746#endif
747
748
749/**
750 * Modifies the [RE]FLAGS register by AND'ing out one or more flags.
751 * @returns Original value.
752 * @param fAndEfl The flags to keep.
753 */
754#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]755RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTREG) ASMClearFlags(RTCCUINTREG fAndEfl);
[57220]756#else
757DECLINLINE(RTCCUINTREG) ASMClearFlags(RTCCUINTREG fAndEfl)
758{
759 RTCCUINTREG fOldEfl;
760# if RT_INLINE_ASM_GNU_STYLE
761# ifdef RT_ARCH_AMD64
762 __asm__ __volatile__("pushfq\n\t"
763 "movq (%%rsp), %0\n\t"
764 "andq %1, (%%rsp)\n\t"
765 "popfq\n\t"
[57312]766 : "=&r" (fOldEfl)
767 : "rn" (fAndEfl) );
[57220]768# else
769 __asm__ __volatile__("pushfl\n\t"
770 "movl (%%esp), %0\n\t"
771 "andl %1, (%%esp)\n\t"
772 "popfl\n\t"
[57312]773 : "=&r" (fOldEfl)
774 : "rn" (fAndEfl) );
[57220]775# endif
776# elif RT_INLINE_ASM_USES_INTRIN >= 15
777 fOldEfl = __readeflags();
778 __writeeflags(fOldEfl & fAndEfl);
779# else
780 __asm
781 {
782# ifdef RT_ARCH_AMD64
783 mov rdx, [fAndEfl]
784 pushfq
785 mov rdx, [rsp]
786 and [rsp], rdx
787 popfq
788 mov [fOldEfl], rax
789# else
790 mov edx, [fAndEfl]
791 pushfd
792 mov edx, [esp]
793 and [esp], edx
794 popfd
795 mov [fOldEfl], eax
796# endif
797 }
798# endif
799 return fOldEfl;
800}
801#endif
802
803
804/**
[1]805 * Gets the content of the CPU timestamp counter register.
806 *
807 * @returns TSC.
808 */
809#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]810RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMReadTSC(void);
[1]811#else
812DECLINLINE(uint64_t) ASMReadTSC(void)
813{
814 RTUINT64U u;
815# if RT_INLINE_ASM_GNU_STYLE
[19305]816 __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));
[1]817# else
818# if RT_INLINE_ASM_USES_INTRIN
819 u.u = __rdtsc();
820# else
821 __asm
822 {
823 rdtsc
824 mov [u.s.Lo], eax
825 mov [u.s.Hi], edx
826 }
827# endif
828# endif
829 return u.u;
830}
831#endif
832
833
834/**
[54251]835 * Gets the content of the CPU timestamp counter register and the
836 * assoicated AUX value.
837 *
838 * @returns TSC.
839 * @param puAux Where to store the AUX value.
840 */
841#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
[75131]842RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMReadTscWithAux(uint32_t RT_FAR *puAux);
[54251]843#else
[68606]844DECLINLINE(uint64_t) ASMReadTscWithAux(uint32_t RT_FAR *puAux)
[54251]845{
846 RTUINT64U u;
847# if RT_INLINE_ASM_GNU_STYLE
[54260]848 /* rdtscp is not supported by ancient linux build VM of course :-( */
849 /*__asm__ __volatile__("rdtscp\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi), "=c" (*puAux)); */
850 __asm__ __volatile__(".byte 0x0f,0x01,0xf9\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi), "=c" (*puAux));
[54251]851# else
852# if RT_INLINE_ASM_USES_INTRIN >= 15
853 u.u = __rdtscp(puAux);
854# else
855 __asm
856 {
857 rdtscp
858 mov [u.s.Lo], eax
859 mov [u.s.Hi], edx
860 mov eax, [puAux]
861 mov [eax], ecx
862 }
863# endif
864# endif
865 return u.u;
866}
867#endif
868
869
870/**
[1]871 * Performs the cpuid instruction returning all registers.
872 *
873 * @param uOperator CPUID operation (eax).
874 * @param pvEAX Where to store eax.
875 * @param pvEBX Where to store ebx.
876 * @param pvECX Where to store ecx.
877 * @param pvEDX Where to store edx.
878 * @remark We're using void pointers to ease the use of special bitfield structures and such.
879 */
880#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[68606]881DECLASM(void) ASMCpuId(uint32_t uOperator, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX);
[1]882#else
[68606]883DECLINLINE(void) ASMCpuId(uint32_t uOperator, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX)
[1]884{
885# if RT_INLINE_ASM_GNU_STYLE
[3636]886# ifdef RT_ARCH_AMD64
[639]887 RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
[31413]888 __asm__ __volatile__ ("cpuid\n\t"
889 : "=a" (uRAX),
890 "=b" (uRBX),
891 "=c" (uRCX),
892 "=d" (uRDX)
[39993]893 : "0" (uOperator), "2" (0));
[68606]894 *(uint32_t RT_FAR *)pvEAX = (uint32_t)uRAX;
895 *(uint32_t RT_FAR *)pvEBX = (uint32_t)uRBX;
896 *(uint32_t RT_FAR *)pvECX = (uint32_t)uRCX;
897 *(uint32_t RT_FAR *)pvEDX = (uint32_t)uRDX;
[639]898# else
[31413]899 __asm__ __volatile__ ("xchgl %%ebx, %1\n\t"
900 "cpuid\n\t"
901 "xchgl %%ebx, %1\n\t"
902 : "=a" (*(uint32_t *)pvEAX),
903 "=r" (*(uint32_t *)pvEBX),
904 "=c" (*(uint32_t *)pvECX),
905 "=d" (*(uint32_t *)pvEDX)
[39993]906 : "0" (uOperator), "2" (0));
[639]907# endif
[1]908
909# elif RT_INLINE_ASM_USES_INTRIN
910 int aInfo[4];
911 __cpuid(aInfo, uOperator);
[68606]912 *(uint32_t RT_FAR *)pvEAX = aInfo[0];
913 *(uint32_t RT_FAR *)pvEBX = aInfo[1];
914 *(uint32_t RT_FAR *)pvECX = aInfo[2];
915 *(uint32_t RT_FAR *)pvEDX = aInfo[3];
[1]916
917# else
918 uint32_t uEAX;
919 uint32_t uEBX;
920 uint32_t uECX;
921 uint32_t uEDX;
922 __asm
923 {
924 push ebx
925 mov eax, [uOperator]
926 cpuid
927 mov [uEAX], eax
928 mov [uEBX], ebx
929 mov [uECX], ecx
930 mov [uEDX], edx
931 pop ebx
932 }
[68606]933 *(uint32_t RT_FAR *)pvEAX = uEAX;
934 *(uint32_t RT_FAR *)pvEBX = uEBX;
935 *(uint32_t RT_FAR *)pvECX = uECX;
936 *(uint32_t RT_FAR *)pvEDX = uEDX;
[1]937# endif
938}
939#endif
940
941
942/**
[44260]943 * Performs the CPUID instruction with EAX and ECX input returning ALL output
944 * registers.
[6175]945 *
946 * @param uOperator CPUID operation (eax).
947 * @param uIdxECX ecx index
948 * @param pvEAX Where to store eax.
949 * @param pvEBX Where to store ebx.
950 * @param pvECX Where to store ecx.
951 * @param pvEDX Where to store edx.
952 * @remark We're using void pointers to ease the use of special bitfield structures and such.
953 */
[44260]954#if RT_INLINE_ASM_EXTERNAL || RT_INLINE_ASM_USES_INTRIN
[68606]955DECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX);
[6175]956#else
[68606]957DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX)
[6175]958{
959# if RT_INLINE_ASM_GNU_STYLE
960# ifdef RT_ARCH_AMD64
961 RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
962 __asm__ ("cpuid\n\t"
963 : "=a" (uRAX),
964 "=b" (uRBX),
965 "=c" (uRCX),
966 "=d" (uRDX)
967 : "0" (uOperator),
968 "2" (uIdxECX));
[68606]969 *(uint32_t RT_FAR *)pvEAX = (uint32_t)uRAX;
970 *(uint32_t RT_FAR *)pvEBX = (uint32_t)uRBX;
971 *(uint32_t RT_FAR *)pvECX = (uint32_t)uRCX;
972 *(uint32_t RT_FAR *)pvEDX = (uint32_t)uRDX;
[6175]973# else
974 __asm__ ("xchgl %%ebx, %1\n\t"
975 "cpuid\n\t"
976 "xchgl %%ebx, %1\n\t"
977 : "=a" (*(uint32_t *)pvEAX),
978 "=r" (*(uint32_t *)pvEBX),
979 "=c" (*(uint32_t *)pvECX),
980 "=d" (*(uint32_t *)pvEDX)
981 : "0" (uOperator),
982 "2" (uIdxECX));
983# endif
984
985# elif RT_INLINE_ASM_USES_INTRIN
986 int aInfo[4];
[44260]987 __cpuidex(aInfo, uOperator, uIdxECX);
[68606]988 *(uint32_t RT_FAR *)pvEAX = aInfo[0];
989 *(uint32_t RT_FAR *)pvEBX = aInfo[1];
990 *(uint32_t RT_FAR *)pvECX = aInfo[2];
991 *(uint32_t RT_FAR *)pvEDX = aInfo[3];
[6175]992
993# else
994 uint32_t uEAX;
995 uint32_t uEBX;
996 uint32_t uECX;
997 uint32_t uEDX;
998 __asm
999 {
1000 push ebx
1001 mov eax, [uOperator]
1002 mov ecx, [uIdxECX]
1003 cpuid
1004 mov [uEAX], eax
1005 mov [uEBX], ebx
1006 mov [uECX], ecx
1007 mov [uEDX], edx
1008 pop ebx
1009 }
[68606]1010 *(uint32_t RT_FAR *)pvEAX = uEAX;
1011 *(uint32_t RT_FAR *)pvEBX = uEBX;
1012 *(uint32_t RT_FAR *)pvECX = uECX;
1013 *(uint32_t RT_FAR *)pvEDX = uEDX;
[6175]1014# endif
1015}
1016#endif
1017
1018
1019/**
[49182]1020 * CPUID variant that initializes all 4 registers before the CPUID instruction.
1021 *
1022 * @returns The EAX result value.
1023 * @param uOperator CPUID operation (eax).
1024 * @param uInitEBX The value to assign EBX prior to the CPUID instruction.
1025 * @param uInitECX The value to assign ECX prior to the CPUID instruction.
1026 * @param uInitEDX The value to assign EDX prior to the CPUID instruction.
1027 * @param pvEAX Where to store eax. Optional.
1028 * @param pvEBX Where to store ebx. Optional.
1029 * @param pvECX Where to store ecx. Optional.
1030 * @param pvEDX Where to store edx. Optional.
1031 */
1032DECLASM(uint32_t) ASMCpuIdExSlow(uint32_t uOperator, uint32_t uInitEBX, uint32_t uInitECX, uint32_t uInitEDX,
[68606]1033 void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX);
[49182]1034
1035
1036/**
[1]1037 * Performs the cpuid instruction returning ecx and edx.
1038 *
1039 * @param uOperator CPUID operation (eax).
1040 * @param pvECX Where to store ecx.
1041 * @param pvEDX Where to store edx.
1042 * @remark We're using void pointers to ease the use of special bitfield structures and such.
1043 */
1044#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1045RT_ASM_DECL_PRAGMA_WATCOM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void RT_FAR *pvECX, void RT_FAR *pvEDX);
[1]1046#else
[68606]1047DECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void RT_FAR *pvECX, void RT_FAR *pvEDX)
[1]1048{
1049 uint32_t uEBX;
1050 ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX);
1051}
1052#endif
1053
1054
1055/**
[30801]1056 * Performs the cpuid instruction returning eax.
[1]1057 *
1058 * @param uOperator CPUID operation (eax).
[30801]1059 * @returns EAX after cpuid operation.
[1]1060 */
1061#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1062RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMCpuId_EAX(uint32_t uOperator);
[1]1063#else
[30801]1064DECLINLINE(uint32_t) ASMCpuId_EAX(uint32_t uOperator)
[1]1065{
[30801]1066 RTCCUINTREG xAX;
[1]1067# if RT_INLINE_ASM_GNU_STYLE
[3636]1068# ifdef RT_ARCH_AMD64
[30801]1069 __asm__ ("cpuid"
1070 : "=a" (xAX)
1071 : "0" (uOperator)
1072 : "rbx", "rcx", "rdx");
1073# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1074 __asm__ ("push %%ebx\n\t"
1075 "cpuid\n\t"
1076 "pop %%ebx\n\t"
1077 : "=a" (xAX)
1078 : "0" (uOperator)
1079 : "ecx", "edx");
1080# else
1081 __asm__ ("cpuid"
1082 : "=a" (xAX)
1083 : "0" (uOperator)
1084 : "edx", "ecx", "ebx");
1085# endif
1086
1087# elif RT_INLINE_ASM_USES_INTRIN
1088 int aInfo[4];
1089 __cpuid(aInfo, uOperator);
[30802]1090 xAX = aInfo[0];
[30801]1091
1092# else
1093 __asm
1094 {
1095 push ebx
1096 mov eax, [uOperator]
1097 cpuid
1098 mov [xAX], eax
1099 pop ebx
1100 }
1101# endif
1102 return (uint32_t)xAX;
1103}
1104#endif
1105
1106
1107/**
1108 * Performs the cpuid instruction returning ebx.
1109 *
1110 * @param uOperator CPUID operation (eax).
1111 * @returns EBX after cpuid operation.
1112 */
1113#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1114RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMCpuId_EBX(uint32_t uOperator);
[30801]1115#else
1116DECLINLINE(uint32_t) ASMCpuId_EBX(uint32_t uOperator)
1117{
1118 RTCCUINTREG xBX;
1119# if RT_INLINE_ASM_GNU_STYLE
1120# ifdef RT_ARCH_AMD64
[639]1121 RTCCUINTREG uSpill;
1122 __asm__ ("cpuid"
1123 : "=a" (uSpill),
[30801]1124 "=b" (xBX)
[639]1125 : "0" (uOperator)
[30801]1126 : "rdx", "rcx");
[14808]1127# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
[1]1128 __asm__ ("push %%ebx\n\t"
1129 "cpuid\n\t"
[30801]1130 "mov %%ebx, %%edx\n\t"
[1]1131 "pop %%ebx\n\t"
1132 : "=a" (uOperator),
[30801]1133 "=d" (xBX)
[1]1134 : "0" (uOperator)
1135 : "ecx");
1136# else
1137 __asm__ ("cpuid"
1138 : "=a" (uOperator),
[30801]1139 "=b" (xBX)
[1]1140 : "0" (uOperator)
[30801]1141 : "edx", "ecx");
[1]1142# endif
1143
1144# elif RT_INLINE_ASM_USES_INTRIN
1145 int aInfo[4];
1146 __cpuid(aInfo, uOperator);
[30803]1147 xBX = aInfo[1];
[1]1148
1149# else
1150 __asm
1151 {
1152 push ebx
1153 mov eax, [uOperator]
1154 cpuid
[30801]1155 mov [xBX], ebx
[1]1156 pop ebx
1157 }
1158# endif
[30801]1159 return (uint32_t)xBX;
[1]1160}
1161#endif
1162
1163
1164/**
1165 * Performs the cpuid instruction returning ecx.
1166 *
1167 * @param uOperator CPUID operation (eax).
1168 * @returns ECX after cpuid operation.
1169 */
1170#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1171RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMCpuId_ECX(uint32_t uOperator);
[1]1172#else
1173DECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)
1174{
[639]1175 RTCCUINTREG xCX;
[1]1176# if RT_INLINE_ASM_GNU_STYLE
[3636]1177# ifdef RT_ARCH_AMD64
[639]1178 RTCCUINTREG uSpill;
1179 __asm__ ("cpuid"
1180 : "=a" (uSpill),
1181 "=c" (xCX)
1182 : "0" (uOperator)
1183 : "rbx", "rdx");
[14808]1184# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
[1]1185 __asm__ ("push %%ebx\n\t"
1186 "cpuid\n\t"
1187 "pop %%ebx\n\t"
1188 : "=a" (uOperator),
[639]1189 "=c" (xCX)
[1]1190 : "0" (uOperator)
1191 : "edx");
1192# else
1193 __asm__ ("cpuid"
1194 : "=a" (uOperator),
[639]1195 "=c" (xCX)
[1]1196 : "0" (uOperator)
1197 : "ebx", "edx");
1198
1199# endif
1200
1201# elif RT_INLINE_ASM_USES_INTRIN
1202 int aInfo[4];
1203 __cpuid(aInfo, uOperator);
[639]1204 xCX = aInfo[2];
[1]1205
1206# else
1207 __asm
1208 {
1209 push ebx
1210 mov eax, [uOperator]
1211 cpuid
[639]1212 mov [xCX], ecx
[1]1213 pop ebx
1214 }
1215# endif
[639]1216 return (uint32_t)xCX;
[1]1217}
1218#endif
1219
1220
1221/**
[30801]1222 * Performs the cpuid instruction returning edx.
1223 *
1224 * @param uOperator CPUID operation (eax).
1225 * @returns EDX after cpuid operation.
1226 */
1227#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1228RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMCpuId_EDX(uint32_t uOperator);
[30801]1229#else
1230DECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)
1231{
1232 RTCCUINTREG xDX;
1233# if RT_INLINE_ASM_GNU_STYLE
1234# ifdef RT_ARCH_AMD64
1235 RTCCUINTREG uSpill;
1236 __asm__ ("cpuid"
1237 : "=a" (uSpill),
1238 "=d" (xDX)
1239 : "0" (uOperator)
1240 : "rbx", "rcx");
1241# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1242 __asm__ ("push %%ebx\n\t"
1243 "cpuid\n\t"
1244 "pop %%ebx\n\t"
1245 : "=a" (uOperator),
1246 "=d" (xDX)
1247 : "0" (uOperator)
1248 : "ecx");
1249# else
1250 __asm__ ("cpuid"
1251 : "=a" (uOperator),
1252 "=d" (xDX)
1253 : "0" (uOperator)
1254 : "ebx", "ecx");
1255# endif
1256
1257# elif RT_INLINE_ASM_USES_INTRIN
1258 int aInfo[4];
1259 __cpuid(aInfo, uOperator);
1260 xDX = aInfo[3];
1261
1262# else
1263 __asm
1264 {
1265 push ebx
1266 mov eax, [uOperator]
1267 cpuid
1268 mov [xDX], edx
1269 pop ebx
1270 }
1271# endif
1272 return (uint32_t)xDX;
1273}
1274#endif
1275
1276
1277/**
[1]1278 * Checks if the current CPU supports CPUID.
1279 *
1280 * @returns true if CPUID is supported.
1281 */
[59310]1282#ifdef __WATCOMC__
1283DECLASM(bool) ASMHasCpuId(void);
1284#else
[1]1285DECLINLINE(bool) ASMHasCpuId(void)
1286{
[59310]1287# ifdef RT_ARCH_AMD64
[1]1288 return true; /* ASSUME that all amd64 compatible CPUs have cpuid. */
[59310]1289# else /* !RT_ARCH_AMD64 */
[1]1290 bool fRet = false;
[59310]1291# if RT_INLINE_ASM_GNU_STYLE
[1]1292 uint32_t u1;
1293 uint32_t u2;
1294 __asm__ ("pushf\n\t"
1295 "pop %1\n\t"
1296 "mov %1, %2\n\t"
1297 "xorl $0x200000, %1\n\t"
1298 "push %1\n\t"
1299 "popf\n\t"
1300 "pushf\n\t"
1301 "pop %1\n\t"
1302 "cmpl %1, %2\n\t"
1303 "setne %0\n\t"
1304 "push %2\n\t"
1305 "popf\n\t"
1306 : "=m" (fRet), "=r" (u1), "=r" (u2));
[59310]1307# else
[1]1308 __asm
1309 {
1310 pushfd
1311 pop eax
1312 mov ebx, eax
1313 xor eax, 0200000h
1314 push eax
1315 popfd
1316 pushfd
1317 pop eax
1318 cmp eax, ebx
1319 setne fRet
1320 push ebx
1321 popfd
1322 }
[59310]1323# endif
[1]1324 return fRet;
[59310]1325# endif /* !RT_ARCH_AMD64 */
[1]1326}
[59310]1327#endif
[1]1328
1329
1330/**
[1027]1331 * Gets the APIC ID of the current CPU.
1332 *
1333 * @returns the APIC ID.
1334 */
1335#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1336RT_ASM_DECL_PRAGMA_WATCOM(uint8_t) ASMGetApicId(void);
[1027]1337#else
1338DECLINLINE(uint8_t) ASMGetApicId(void)
1339{
1340 RTCCUINTREG xBX;
1341# if RT_INLINE_ASM_GNU_STYLE
[3636]1342# ifdef RT_ARCH_AMD64
[1027]1343 RTCCUINTREG uSpill;
[31413]1344 __asm__ __volatile__ ("cpuid"
1345 : "=a" (uSpill),
1346 "=b" (xBX)
1347 : "0" (1)
1348 : "rcx", "rdx");
[14808]1349# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
[1027]1350 RTCCUINTREG uSpill;
[31413]1351 __asm__ __volatile__ ("mov %%ebx,%1\n\t"
1352 "cpuid\n\t"
1353 "xchgl %%ebx,%1\n\t"
1354 : "=a" (uSpill),
[31427]1355 "=rm" (xBX)
[31413]1356 : "0" (1)
1357 : "ecx", "edx");
[1027]1358# else
1359 RTCCUINTREG uSpill;
[31413]1360 __asm__ __volatile__ ("cpuid"
1361 : "=a" (uSpill),
1362 "=b" (xBX)
1363 : "0" (1)
1364 : "ecx", "edx");
[1027]1365# endif
1366
1367# elif RT_INLINE_ASM_USES_INTRIN
1368 int aInfo[4];
1369 __cpuid(aInfo, 1);
1370 xBX = aInfo[1];
1371
1372# else
1373 __asm
1374 {
1375 push ebx
1376 mov eax, 1
1377 cpuid
1378 mov [xBX], ebx
1379 pop ebx
1380 }
1381# endif
1382 return (uint8_t)(xBX >> 24);
1383}
1384#endif
1385
[8882]1386
[1027]1387/**
[21943]1388 * Tests if it a genuine Intel CPU based on the ASMCpuId(0) output.
[8889]1389 *
1390 * @returns true/false.
1391 * @param uEBX EBX return from ASMCpuId(0)
1392 * @param uECX ECX return from ASMCpuId(0)
1393 * @param uEDX EDX return from ASMCpuId(0)
1394 */
1395DECLINLINE(bool) ASMIsIntelCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
1396{
[24452]1397 return uEBX == UINT32_C(0x756e6547)
1398 && uECX == UINT32_C(0x6c65746e)
1399 && uEDX == UINT32_C(0x49656e69);
[8889]1400}
1401
1402
1403/**
[21943]1404 * Tests if this is a genuine Intel CPU.
[8889]1405 *
1406 * @returns true/false.
[21943]1407 * @remarks ASSUMES that cpuid is supported by the CPU.
[8889]1408 */
1409DECLINLINE(bool) ASMIsIntelCpu(void)
1410{
1411 uint32_t uEAX, uEBX, uECX, uEDX;
[15216]1412 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
[8889]1413 return ASMIsIntelCpuEx(uEBX, uECX, uEDX);
1414}
1415
1416
1417/**
[44169]1418 * Tests if it an authentic AMD CPU based on the ASMCpuId(0) output.
[24452]1419 *
1420 * @returns true/false.
1421 * @param uEBX EBX return from ASMCpuId(0)
1422 * @param uECX ECX return from ASMCpuId(0)
1423 * @param uEDX EDX return from ASMCpuId(0)
1424 */
1425DECLINLINE(bool) ASMIsAmdCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
1426{
1427 return uEBX == UINT32_C(0x68747541)
1428 && uECX == UINT32_C(0x444d4163)
1429 && uEDX == UINT32_C(0x69746e65);
1430}
1431
1432
1433/**
1434 * Tests if this is an authentic AMD CPU.
1435 *
1436 * @returns true/false.
1437 * @remarks ASSUMES that cpuid is supported by the CPU.
1438 */
1439DECLINLINE(bool) ASMIsAmdCpu(void)
1440{
1441 uint32_t uEAX, uEBX, uECX, uEDX;
1442 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
1443 return ASMIsAmdCpuEx(uEBX, uECX, uEDX);
1444}
1445
1446
1447/**
[44169]1448 * Tests if it a centaur hauling VIA CPU based on the ASMCpuId(0) output.
1449 *
1450 * @returns true/false.
1451 * @param uEBX EBX return from ASMCpuId(0).
1452 * @param uECX ECX return from ASMCpuId(0).
1453 * @param uEDX EDX return from ASMCpuId(0).
1454 */
1455DECLINLINE(bool) ASMIsViaCentaurCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
1456{
1457 return uEBX == UINT32_C(0x746e6543)
1458 && uECX == UINT32_C(0x736c7561)
1459 && uEDX == UINT32_C(0x48727561);
1460}
1461
1462
1463/**
1464 * Tests if this is a centaur hauling VIA CPU.
1465 *
1466 * @returns true/false.
1467 * @remarks ASSUMES that cpuid is supported by the CPU.
1468 */
1469DECLINLINE(bool) ASMIsViaCentaurCpu(void)
1470{
1471 uint32_t uEAX, uEBX, uECX, uEDX;
1472 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
[61070]1473 return ASMIsViaCentaurCpuEx(uEBX, uECX, uEDX);
[44169]1474}
1475
1476
1477/**
[76886]1478 * Tests if it a Shanghai CPU based on the ASMCpuId(0) output.
1479 *
1480 * @returns true/false.
1481 * @param uEBX EBX return from ASMCpuId(0).
1482 * @param uECX ECX return from ASMCpuId(0).
1483 * @param uEDX EDX return from ASMCpuId(0).
1484 */
1485DECLINLINE(bool) ASMIsShanghaiCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
1486{
1487 return uEBX == UINT32_C(0x68532020)
1488 && uECX == UINT32_C(0x20206961)
1489 && uEDX == UINT32_C(0x68676e61);
1490}
1491
1492
1493/**
1494 * Tests if this is a Shanghai CPU.
1495 *
1496 * @returns true/false.
1497 * @remarks ASSUMES that cpuid is supported by the CPU.
1498 */
1499DECLINLINE(bool) ASMIsShanghaiCpu(void)
1500{
1501 uint32_t uEAX, uEBX, uECX, uEDX;
1502 ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
1503 return ASMIsShanghaiCpuEx(uEBX, uECX, uEDX);
1504}
1505
1506
1507/**
[44169]1508 * Checks whether ASMCpuId_EAX(0x00000000) indicates a valid range.
1509 *
1510 *
1511 * @returns true/false.
1512 * @param uEAX The EAX value of CPUID leaf 0x00000000.
1513 *
1514 * @note This only succeeds if there are at least two leaves in the range.
1515 * @remarks The upper range limit is just some half reasonable value we've
1516 * picked out of thin air.
1517 */
1518DECLINLINE(bool) ASMIsValidStdRange(uint32_t uEAX)
1519{
1520 return uEAX >= UINT32_C(0x00000001) && uEAX <= UINT32_C(0x000fffff);
1521}
1522
1523
1524/**
1525 * Checks whether ASMCpuId_EAX(0x80000000) indicates a valid range.
1526 *
1527 * This only succeeds if there are at least two leaves in the range.
1528 *
1529 * @returns true/false.
1530 * @param uEAX The EAX value of CPUID leaf 0x80000000.
1531 *
1532 * @note This only succeeds if there are at least two leaves in the range.
1533 * @remarks The upper range limit is just some half reasonable value we've
1534 * picked out of thin air.
1535 */
1536DECLINLINE(bool) ASMIsValidExtRange(uint32_t uEAX)
1537{
1538 return uEAX >= UINT32_C(0x80000001) && uEAX <= UINT32_C(0x800fffff);
1539}
1540
1541
1542/**
[70942]1543 * Checks whether ASMCpuId_EAX(0x40000000) indicates a valid range.
1544 *
1545 * This only succeeds if there are at least two leaves in the range.
1546 *
1547 * @returns true/false.
1548 * @param uEAX The EAX value of CPUID leaf 0x40000000.
1549 *
1550 * @note Unlike ASMIsValidStdRange() and ASMIsValidExtRange(), a single leaf
1551 * is okay here. So, you always need to check the range.
1552 * @remarks The upper range limit is take from the intel docs.
1553 */
1554DECLINLINE(bool) ASMIsValidHypervisorRange(uint32_t uEAX)
1555{
1556 return uEAX >= UINT32_C(0x40000000) && uEAX <= UINT32_C(0x4fffffff);
1557}
1558
1559
1560/**
[8882]1561 * Extracts the CPU family from ASMCpuId(1) or ASMCpuId(0x80000001)
1562 *
1563 * @returns Family.
1564 * @param uEAX EAX return from ASMCpuId(1) or ASMCpuId(0x80000001).
1565 */
1566DECLINLINE(uint32_t) ASMGetCpuFamily(uint32_t uEAX)
1567{
1568 return ((uEAX >> 8) & 0xf) == 0xf
1569 ? ((uEAX >> 20) & 0x7f) + 0xf
1570 : ((uEAX >> 8) & 0xf);
1571}
1572
1573
1574/**
[8889]1575 * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), Intel variant.
1576 *
1577 * @returns Model.
1578 * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
1579 */
1580DECLINLINE(uint32_t) ASMGetCpuModelIntel(uint32_t uEAX)
1581{
1582 return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6) /* family! */
1583 ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
1584 : ((uEAX >> 4) & 0xf);
1585}
1586
1587
1588/**
1589 * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), AMD variant.
1590 *
1591 * @returns Model.
1592 * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
1593 */
1594DECLINLINE(uint32_t) ASMGetCpuModelAMD(uint32_t uEAX)
1595{
1596 return ((uEAX >> 8) & 0xf) == 0xf
1597 ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
1598 : ((uEAX >> 4) & 0xf);
1599}
1600
1601
1602/**
[8882]1603 * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001)
1604 *
1605 * @returns Model.
1606 * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
[8889]1607 * @param fIntel Whether it's an intel CPU. Use ASMIsIntelCpuEx() or ASMIsIntelCpu().
[8882]1608 */
[8889]1609DECLINLINE(uint32_t) ASMGetCpuModel(uint32_t uEAX, bool fIntel)
[8882]1610{
[8889]1611 return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6 && fIntel) /* family! */
[8882]1612 ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
1613 : ((uEAX >> 4) & 0xf);
1614}
1615
1616
1617/**
1618 * Extracts the CPU stepping from ASMCpuId(1) or ASMCpuId(0x80000001)
1619 *
1620 * @returns Model.
1621 * @param uEAX EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
1622 */
1623DECLINLINE(uint32_t) ASMGetCpuStepping(uint32_t uEAX)
1624{
1625 return uEAX & 0xf;
1626}
1627
1628
1629/**
[1]1630 * Get cr0.
1631 * @returns cr0.
1632 */
1633#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1634RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetCR0(void);
[1]1635#else
[58705]1636DECLINLINE(RTCCUINTXREG) ASMGetCR0(void)
[1]1637{
[58705]1638 RTCCUINTXREG uCR0;
[1]1639# if RT_INLINE_ASM_USES_INTRIN
1640 uCR0 = __readcr0();
1641
1642# elif RT_INLINE_ASM_GNU_STYLE
[3636]1643# ifdef RT_ARCH_AMD64
[8253]1644 __asm__ __volatile__("movq %%cr0, %0\t\n" : "=r" (uCR0));
[1]1645# else
[8253]1646 __asm__ __volatile__("movl %%cr0, %0\t\n" : "=r" (uCR0));
[1]1647# endif
1648# else
1649 __asm
1650 {
[3636]1651# ifdef RT_ARCH_AMD64
[1]1652 mov rax, cr0
1653 mov [uCR0], rax
1654# else
1655 mov eax, cr0
1656 mov [uCR0], eax
1657# endif
1658 }
1659# endif
1660 return uCR0;
1661}
1662#endif
1663
1664
1665/**
1666 * Sets the CR0 register.
1667 * @param uCR0 The new CR0 value.
1668 */
1669#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1670RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetCR0(RTCCUINTXREG uCR0);
[1]1671#else
[58705]1672DECLINLINE(void) ASMSetCR0(RTCCUINTXREG uCR0)
[1]1673{
1674# if RT_INLINE_ASM_USES_INTRIN
1675 __writecr0(uCR0);
1676
1677# elif RT_INLINE_ASM_GNU_STYLE
[3636]1678# ifdef RT_ARCH_AMD64
[1]1679 __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0));
1680# else
1681 __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0));
1682# endif
1683# else
1684 __asm
1685 {
[3636]1686# ifdef RT_ARCH_AMD64
[1]1687 mov rax, [uCR0]
1688 mov cr0, rax
1689# else
1690 mov eax, [uCR0]
1691 mov cr0, eax
1692# endif
1693 }
1694# endif
1695}
1696#endif
1697
1698
1699/**
1700 * Get cr2.
1701 * @returns cr2.
1702 */
1703#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1704RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetCR2(void);
[1]1705#else
[58705]1706DECLINLINE(RTCCUINTXREG) ASMGetCR2(void)
[1]1707{
[58705]1708 RTCCUINTXREG uCR2;
[1]1709# if RT_INLINE_ASM_USES_INTRIN
1710 uCR2 = __readcr2();
1711
1712# elif RT_INLINE_ASM_GNU_STYLE
[3636]1713# ifdef RT_ARCH_AMD64
[8253]1714 __asm__ __volatile__("movq %%cr2, %0\t\n" : "=r" (uCR2));
[1]1715# else
[8253]1716 __asm__ __volatile__("movl %%cr2, %0\t\n" : "=r" (uCR2));
[1]1717# endif
1718# else
1719 __asm
1720 {
[3636]1721# ifdef RT_ARCH_AMD64
[1]1722 mov rax, cr2
1723 mov [uCR2], rax
1724# else
1725 mov eax, cr2
1726 mov [uCR2], eax
1727# endif
1728 }
1729# endif
1730 return uCR2;
1731}
1732#endif
1733
1734
1735/**
1736 * Sets the CR2 register.
1737 * @param uCR2 The new CR0 value.
1738 */
1739#if RT_INLINE_ASM_EXTERNAL
[75131]1740RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetCR2(RTCCUINTXREG uCR2);
[1]1741#else
[58705]1742DECLINLINE(void) ASMSetCR2(RTCCUINTXREG uCR2)
[1]1743{
1744# if RT_INLINE_ASM_GNU_STYLE
[3636]1745# ifdef RT_ARCH_AMD64
[1]1746 __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2));
1747# else
1748 __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2));
1749# endif
1750# else
1751 __asm
1752 {
[3636]1753# ifdef RT_ARCH_AMD64
[1]1754 mov rax, [uCR2]
1755 mov cr2, rax
1756# else
1757 mov eax, [uCR2]
1758 mov cr2, eax
1759# endif
1760 }
1761# endif
1762}
1763#endif
1764
1765
1766/**
1767 * Get cr3.
1768 * @returns cr3.
1769 */
1770#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1771RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetCR3(void);
[1]1772#else
[58705]1773DECLINLINE(RTCCUINTXREG) ASMGetCR3(void)
[1]1774{
[58705]1775 RTCCUINTXREG uCR3;
[1]1776# if RT_INLINE_ASM_USES_INTRIN
1777 uCR3 = __readcr3();
1778
1779# elif RT_INLINE_ASM_GNU_STYLE
[3636]1780# ifdef RT_ARCH_AMD64
[8253]1781 __asm__ __volatile__("movq %%cr3, %0\t\n" : "=r" (uCR3));
[1]1782# else
[8253]1783 __asm__ __volatile__("movl %%cr3, %0\t\n" : "=r" (uCR3));
[1]1784# endif
1785# else
1786 __asm
1787 {
[3636]1788# ifdef RT_ARCH_AMD64
[1]1789 mov rax, cr3
1790 mov [uCR3], rax
1791# else
1792 mov eax, cr3
1793 mov [uCR3], eax
1794# endif
1795 }
1796# endif
1797 return uCR3;
1798}
1799#endif
1800
1801
1802/**
1803 * Sets the CR3 register.
1804 *
1805 * @param uCR3 New CR3 value.
1806 */
1807#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1808RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetCR3(RTCCUINTXREG uCR3);
[1]1809#else
[58705]1810DECLINLINE(void) ASMSetCR3(RTCCUINTXREG uCR3)
[1]1811{
1812# if RT_INLINE_ASM_USES_INTRIN
1813 __writecr3(uCR3);
1814
1815# elif RT_INLINE_ASM_GNU_STYLE
[3636]1816# ifdef RT_ARCH_AMD64
[19305]1817 __asm__ __volatile__("movq %0, %%cr3\n\t" : : "r" (uCR3));
[1]1818# else
[19305]1819 __asm__ __volatile__("movl %0, %%cr3\n\t" : : "r" (uCR3));
[1]1820# endif
1821# else
1822 __asm
1823 {
[3636]1824# ifdef RT_ARCH_AMD64
[1]1825 mov rax, [uCR3]
1826 mov cr3, rax
1827# else
1828 mov eax, [uCR3]
1829 mov cr3, eax
1830# endif
1831 }
1832# endif
1833}
1834#endif
1835
1836
1837/**
1838 * Reloads the CR3 register.
1839 */
1840#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1841RT_ASM_DECL_PRAGMA_WATCOM(void) ASMReloadCR3(void);
[1]1842#else
1843DECLINLINE(void) ASMReloadCR3(void)
1844{
1845# if RT_INLINE_ASM_USES_INTRIN
1846 __writecr3(__readcr3());
1847
1848# elif RT_INLINE_ASM_GNU_STYLE
[58705]1849 RTCCUINTXREG u;
[3636]1850# ifdef RT_ARCH_AMD64
[19305]1851 __asm__ __volatile__("movq %%cr3, %0\n\t"
1852 "movq %0, %%cr3\n\t"
1853 : "=r" (u));
[1]1854# else
[19305]1855 __asm__ __volatile__("movl %%cr3, %0\n\t"
1856 "movl %0, %%cr3\n\t"
1857 : "=r" (u));
[1]1858# endif
1859# else
1860 __asm
1861 {
[3636]1862# ifdef RT_ARCH_AMD64
[1]1863 mov rax, cr3
1864 mov cr3, rax
1865# else
1866 mov eax, cr3
1867 mov cr3, eax
1868# endif
1869 }
1870# endif
1871}
1872#endif
1873
1874
1875/**
1876 * Get cr4.
1877 * @returns cr4.
1878 */
1879#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1880RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetCR4(void);
[1]1881#else
[58705]1882DECLINLINE(RTCCUINTXREG) ASMGetCR4(void)
[1]1883{
[58705]1884 RTCCUINTXREG uCR4;
[1]1885# if RT_INLINE_ASM_USES_INTRIN
1886 uCR4 = __readcr4();
1887
1888# elif RT_INLINE_ASM_GNU_STYLE
[3636]1889# ifdef RT_ARCH_AMD64
[8253]1890 __asm__ __volatile__("movq %%cr4, %0\t\n" : "=r" (uCR4));
[1]1891# else
[8253]1892 __asm__ __volatile__("movl %%cr4, %0\t\n" : "=r" (uCR4));
[1]1893# endif
1894# else
1895 __asm
1896 {
[3636]1897# ifdef RT_ARCH_AMD64
[1]1898 mov rax, cr4
1899 mov [uCR4], rax
1900# else
1901 push eax /* just in case */
1902 /*mov eax, cr4*/
[21236]1903 _emit 0x0f
1904 _emit 0x20
1905 _emit 0xe0
[1]1906 mov [uCR4], eax
1907 pop eax
1908# endif
1909 }
1910# endif
1911 return uCR4;
1912}
1913#endif
1914
1915
1916/**
1917 * Sets the CR4 register.
1918 *
1919 * @param uCR4 New CR4 value.
1920 */
1921#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]1922RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetCR4(RTCCUINTXREG uCR4);
[1]1923#else
[58705]1924DECLINLINE(void) ASMSetCR4(RTCCUINTXREG uCR4)
[1]1925{
1926# if RT_INLINE_ASM_USES_INTRIN
1927 __writecr4(uCR4);
1928
1929# elif RT_INLINE_ASM_GNU_STYLE
[3636]1930# ifdef RT_ARCH_AMD64
[19305]1931 __asm__ __volatile__("movq %0, %%cr4\n\t" : : "r" (uCR4));
[1]1932# else
[19305]1933 __asm__ __volatile__("movl %0, %%cr4\n\t" : : "r" (uCR4));
[1]1934# endif
1935# else
1936 __asm
1937 {
[3636]1938# ifdef RT_ARCH_AMD64
[1]1939 mov rax, [uCR4]
1940 mov cr4, rax
1941# else
1942 mov eax, [uCR4]
1943 _emit 0x0F
1944 _emit 0x22
1945 _emit 0xE0 /* mov cr4, eax */
1946# endif
1947 }
1948# endif
1949}
1950#endif
1951
1952
1953/**
1954 * Get cr8.
1955 * @returns cr8.
1956 * @remark The lock prefix hack for access from non-64-bit modes is NOT used and 0 is returned.
1957 */
1958#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[58705]1959DECLASM(RTCCUINTXREG) ASMGetCR8(void);
[1]1960#else
[58705]1961DECLINLINE(RTCCUINTXREG) ASMGetCR8(void)
[1]1962{
[3636]1963# ifdef RT_ARCH_AMD64
[58705]1964 RTCCUINTXREG uCR8;
[1]1965# if RT_INLINE_ASM_USES_INTRIN
1966 uCR8 = __readcr8();
1967
1968# elif RT_INLINE_ASM_GNU_STYLE
[8253]1969 __asm__ __volatile__("movq %%cr8, %0\t\n" : "=r" (uCR8));
[1]1970# else
1971 __asm
1972 {
1973 mov rax, cr8
1974 mov [uCR8], rax
1975 }
1976# endif
1977 return uCR8;
[3636]1978# else /* !RT_ARCH_AMD64 */
[1]1979 return 0;
[3636]1980# endif /* !RT_ARCH_AMD64 */
[1]1981}
1982#endif
1983
1984
1985/**
[55107]1986 * Get XCR0 (eXtended feature Control Register 0).
1987 * @returns xcr0.
1988 */
1989DECLASM(uint64_t) ASMGetXcr0(void);
1990
1991/**
1992 * Sets the XCR0 register.
1993 * @param uXcr0 The new XCR0 value.
1994 */
1995DECLASM(void) ASMSetXcr0(uint64_t uXcr0);
1996
[55309]1997struct X86XSAVEAREA;
[55308]1998/**
1999 * Save extended CPU state.
2000 * @param pXStateArea Where to save the state.
2001 * @param fComponents Which state components to save.
2002 */
[68606]2003DECLASM(void) ASMXSave(struct X86XSAVEAREA RT_FAR *pXStateArea, uint64_t fComponents);
[55107]2004
2005/**
[55308]2006 * Loads extended CPU state.
2007 * @param pXStateArea Where to load the state from.
2008 * @param fComponents Which state components to load.
2009 */
[68606]2010DECLASM(void) ASMXRstor(struct X86XSAVEAREA const RT_FAR *pXStateArea, uint64_t fComponents);
[55308]2011
2012
[66395]2013struct X86FXSTATE;
[55308]2014/**
[66395]2015 * Save FPU and SSE CPU state.
[66402]2016 * @param pXStateArea Where to save the state.
[66395]2017 */
[68606]2018DECLASM(void) ASMFxSave(struct X86FXSTATE RT_FAR *pXStateArea);
[66395]2019
2020/**
2021 * Load FPU and SSE CPU state.
[66402]2022 * @param pXStateArea Where to load the state from.
[66395]2023 */
[68606]2024DECLASM(void) ASMFxRstor(struct X86FXSTATE const RT_FAR *pXStateArea);
[66395]2025
2026
2027/**
[1]2028 * Enables interrupts (EFLAGS.IF).
2029 */
2030#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2031RT_ASM_DECL_PRAGMA_WATCOM(void) ASMIntEnable(void);
[1]2032#else
2033DECLINLINE(void) ASMIntEnable(void)
2034{
2035# if RT_INLINE_ASM_GNU_STYLE
2036 __asm("sti\n");
2037# elif RT_INLINE_ASM_USES_INTRIN
2038 _enable();
2039# else
2040 __asm sti
2041# endif
2042}
2043#endif
2044
2045
2046/**
2047 * Disables interrupts (!EFLAGS.IF).
2048 */
2049#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2050RT_ASM_DECL_PRAGMA_WATCOM(void) ASMIntDisable(void);
[1]2051#else
2052DECLINLINE(void) ASMIntDisable(void)
2053{
2054# if RT_INLINE_ASM_GNU_STYLE
2055 __asm("cli\n");
2056# elif RT_INLINE_ASM_USES_INTRIN
2057 _disable();
2058# else
2059 __asm cli
2060# endif
2061}
2062#endif
2063
2064
2065/**
[1228]2066 * Disables interrupts and returns previous xFLAGS.
2067 */
2068#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2069RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTREG) ASMIntDisableFlags(void);
[1228]2070#else
2071DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
2072{
2073 RTCCUINTREG xFlags;
2074# if RT_INLINE_ASM_GNU_STYLE
[3636]2075# ifdef RT_ARCH_AMD64
[1228]2076 __asm__ __volatile__("pushfq\n\t"
2077 "cli\n\t"
2078 "popq %0\n\t"
[22280]2079 : "=r" (xFlags));
[1228]2080# else
2081 __asm__ __volatile__("pushfl\n\t"
2082 "cli\n\t"
2083 "popl %0\n\t"
[22280]2084 : "=r" (xFlags));
[1228]2085# endif
[3636]2086# elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86)
[1228]2087 xFlags = ASMGetFlags();
2088 _disable();
2089# else
2090 __asm {
2091 pushfd
2092 cli
2093 pop [xFlags]
2094 }
2095# endif
2096 return xFlags;
2097}
2098#endif
2099
2100
2101/**
[21535]2102 * Are interrupts enabled?
2103 *
2104 * @returns true / false.
2105 */
[53405]2106DECLINLINE(bool) ASMIntAreEnabled(void)
[21535]2107{
2108 RTCCUINTREG uFlags = ASMGetFlags();
2109 return uFlags & 0x200 /* X86_EFL_IF */ ? true : false;
2110}
2111
2112
2113/**
[19305]2114 * Halts the CPU until interrupted.
2115 */
[60201]2116#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 14
[75131]2117RT_ASM_DECL_PRAGMA_WATCOM(void) ASMHalt(void);
[19305]2118#else
2119DECLINLINE(void) ASMHalt(void)
2120{
2121# if RT_INLINE_ASM_GNU_STYLE
2122 __asm__ __volatile__("hlt\n\t");
[60201]2123# elif RT_INLINE_ASM_USES_INTRIN
2124 __halt();
[19305]2125# else
2126 __asm {
2127 hlt
2128 }
2129# endif
2130}
2131#endif
2132
2133
2134/**
[1]2135 * Reads a machine specific register.
2136 *
2137 * @returns Register content.
2138 * @param uRegister Register to read.
2139 */
2140#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2141RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMRdMsr(uint32_t uRegister);
[1]2142#else
2143DECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister)
2144{
2145 RTUINT64U u;
2146# if RT_INLINE_ASM_GNU_STYLE
[8277]2147 __asm__ __volatile__("rdmsr\n\t"
2148 : "=a" (u.s.Lo),
2149 "=d" (u.s.Hi)
2150 : "c" (uRegister));
[1]2151
2152# elif RT_INLINE_ASM_USES_INTRIN
2153 u.u = __readmsr(uRegister);
2154
2155# else
2156 __asm
2157 {
2158 mov ecx, [uRegister]
2159 rdmsr
2160 mov [u.s.Lo], eax
2161 mov [u.s.Hi], edx
2162 }
2163# endif
2164
2165 return u.u;
2166}
2167#endif
2168
2169
2170/**
2171 * Writes a machine specific register.
2172 *
2173 * @returns Register content.
2174 * @param uRegister Register to write to.
2175 * @param u64Val Value to write.
2176 */
2177#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2178RT_ASM_DECL_PRAGMA_WATCOM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val);
[1]2179#else
2180DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)
2181{
2182 RTUINT64U u;
2183
2184 u.u = u64Val;
2185# if RT_INLINE_ASM_GNU_STYLE
2186 __asm__ __volatile__("wrmsr\n\t"
2187 ::"a" (u.s.Lo),
2188 "d" (u.s.Hi),
2189 "c" (uRegister));
2190
2191# elif RT_INLINE_ASM_USES_INTRIN
2192 __writemsr(uRegister, u.u);
2193
2194# else
2195 __asm
2196 {
2197 mov ecx, [uRegister]
2198 mov edx, [u.s.Hi]
2199 mov eax, [u.s.Lo]
2200 wrmsr
2201 }
2202# endif
2203}
2204#endif
2205
2206
2207/**
[49845]2208 * Reads a machine specific register, extended version (for AMD).
2209 *
2210 * @returns Register content.
2211 * @param uRegister Register to read.
2212 * @param uXDI RDI/EDI value.
2213 */
2214#if RT_INLINE_ASM_EXTERNAL
[75131]2215RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI);
[49845]2216#else
[58705]2217DECLINLINE(uint64_t) ASMRdMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI)
[49845]2218{
2219 RTUINT64U u;
2220# if RT_INLINE_ASM_GNU_STYLE
2221 __asm__ __volatile__("rdmsr\n\t"
2222 : "=a" (u.s.Lo),
2223 "=d" (u.s.Hi)
2224 : "c" (uRegister),
2225 "D" (uXDI));
2226
2227# else
2228 __asm
2229 {
2230 mov ecx, [uRegister]
2231 xchg edi, [uXDI]
2232 rdmsr
2233 mov [u.s.Lo], eax
2234 mov [u.s.Hi], edx
2235 xchg edi, [uXDI]
2236 }
2237# endif
2238
2239 return u.u;
2240}
2241#endif
2242
2243
2244/**
2245 * Writes a machine specific register, extended version (for AMD).
2246 *
2247 * @returns Register content.
2248 * @param uRegister Register to write to.
2249 * @param uXDI RDI/EDI value.
2250 * @param u64Val Value to write.
2251 */
2252#if RT_INLINE_ASM_EXTERNAL
[75131]2253RT_ASM_DECL_PRAGMA_WATCOM(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI, uint64_t u64Val);
[49845]2254#else
[58705]2255DECLINLINE(void) ASMWrMsrEx(uint32_t uRegister, RTCCUINTXREG uXDI, uint64_t u64Val)
[49845]2256{
2257 RTUINT64U u;
2258
2259 u.u = u64Val;
2260# if RT_INLINE_ASM_GNU_STYLE
2261 __asm__ __volatile__("wrmsr\n\t"
2262 ::"a" (u.s.Lo),
2263 "d" (u.s.Hi),
2264 "c" (uRegister),
2265 "D" (uXDI));
2266
2267# else
2268 __asm
2269 {
2270 mov ecx, [uRegister]
2271 xchg edi, [uXDI]
2272 mov edx, [u.s.Hi]
2273 mov eax, [u.s.Lo]
2274 wrmsr
2275 xchg edi, [uXDI]
2276 }
2277# endif
2278}
2279#endif
2280
2281
2282
2283/**
[1]2284 * Reads low part of a machine specific register.
2285 *
2286 * @returns Register content.
2287 * @param uRegister Register to read.
2288 */
2289#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2290RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMRdMsr_Low(uint32_t uRegister);
[1]2291#else
2292DECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister)
2293{
2294 uint32_t u32;
2295# if RT_INLINE_ASM_GNU_STYLE
[8264]2296 __asm__ __volatile__("rdmsr\n\t"
[8277]2297 : "=a" (u32)
2298 : "c" (uRegister)
2299 : "edx");
[1]2300
2301# elif RT_INLINE_ASM_USES_INTRIN
2302 u32 = (uint32_t)__readmsr(uRegister);
2303
2304#else
2305 __asm
2306 {
2307 mov ecx, [uRegister]
2308 rdmsr
2309 mov [u32], eax
2310 }
2311# endif
2312
2313 return u32;
2314}
2315#endif
2316
2317
2318/**
2319 * Reads high part of a machine specific register.
2320 *
2321 * @returns Register content.
2322 * @param uRegister Register to read.
2323 */
2324#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2325RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMRdMsr_High(uint32_t uRegister);
[1]2326#else
2327DECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister)
2328{
2329 uint32_t u32;
2330# if RT_INLINE_ASM_GNU_STYLE
[8264]2331 __asm__ __volatile__("rdmsr\n\t"
[8277]2332 : "=d" (u32)
2333 : "c" (uRegister)
2334 : "eax");
[1]2335
2336# elif RT_INLINE_ASM_USES_INTRIN
2337 u32 = (uint32_t)(__readmsr(uRegister) >> 32);
2338
2339# else
2340 __asm
2341 {
2342 mov ecx, [uRegister]
2343 rdmsr
2344 mov [u32], edx
2345 }
2346# endif
2347
2348 return u32;
2349}
2350#endif
2351
2352
2353/**
[12221]2354 * Gets dr0.
[1]2355 *
[12221]2356 * @returns dr0.
[1]2357 */
[12221]2358#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2359RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR0(void);
[1]2360#else
[58705]2361DECLINLINE(RTCCUINTXREG) ASMGetDR0(void)
[1]2362{
[58705]2363 RTCCUINTXREG uDR0;
[12221]2364# if RT_INLINE_ASM_USES_INTRIN
2365 uDR0 = __readdr(0);
2366# elif RT_INLINE_ASM_GNU_STYLE
[3636]2367# ifdef RT_ARCH_AMD64
[12221]2368 __asm__ __volatile__("movq %%dr0, %0\n\t" : "=r" (uDR0));
[1]2369# else
[12221]2370 __asm__ __volatile__("movl %%dr0, %0\n\t" : "=r" (uDR0));
[1]2371# endif
2372# else
2373 __asm
2374 {
[3636]2375# ifdef RT_ARCH_AMD64
[12221]2376 mov rax, dr0
2377 mov [uDR0], rax
[1]2378# else
[12221]2379 mov eax, dr0
2380 mov [uDR0], eax
[1]2381# endif
2382 }
2383# endif
[12221]2384 return uDR0;
[1]2385}
2386#endif
2387
2388
2389/**
[12221]2390 * Gets dr1.
[1]2391 *
[12221]2392 * @returns dr1.
[1]2393 */
[12221]2394#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2395RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR1(void);
[1]2396#else
[58705]2397DECLINLINE(RTCCUINTXREG) ASMGetDR1(void)
[1]2398{
[58705]2399 RTCCUINTXREG uDR1;
[12221]2400# if RT_INLINE_ASM_USES_INTRIN
2401 uDR1 = __readdr(1);
2402# elif RT_INLINE_ASM_GNU_STYLE
[3636]2403# ifdef RT_ARCH_AMD64
[12221]2404 __asm__ __volatile__("movq %%dr1, %0\n\t" : "=r" (uDR1));
[1]2405# else
[12221]2406 __asm__ __volatile__("movl %%dr1, %0\n\t" : "=r" (uDR1));
[1]2407# endif
2408# else
2409 __asm
2410 {
[3636]2411# ifdef RT_ARCH_AMD64
[12221]2412 mov rax, dr1
2413 mov [uDR1], rax
[1]2414# else
[12221]2415 mov eax, dr1
2416 mov [uDR1], eax
[1]2417# endif
2418 }
2419# endif
[12221]2420 return uDR1;
[1]2421}
2422#endif
2423
2424
2425/**
[12221]2426 * Gets dr2.
[1]2427 *
[12221]2428 * @returns dr2.
[1]2429 */
[12221]2430#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2431RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR2(void);
[1]2432#else
[58705]2433DECLINLINE(RTCCUINTXREG) ASMGetDR2(void)
[1]2434{
[58705]2435 RTCCUINTXREG uDR2;
[12221]2436# if RT_INLINE_ASM_USES_INTRIN
2437 uDR2 = __readdr(2);
2438# elif RT_INLINE_ASM_GNU_STYLE
[3636]2439# ifdef RT_ARCH_AMD64
[12221]2440 __asm__ __volatile__("movq %%dr2, %0\n\t" : "=r" (uDR2));
[1]2441# else
[12221]2442 __asm__ __volatile__("movl %%dr2, %0\n\t" : "=r" (uDR2));
[1]2443# endif
2444# else
2445 __asm
2446 {
[3636]2447# ifdef RT_ARCH_AMD64
[12221]2448 mov rax, dr2
2449 mov [uDR2], rax
[1]2450# else
[12221]2451 mov eax, dr2
2452 mov [uDR2], eax
[1]2453# endif
2454 }
2455# endif
[12221]2456 return uDR2;
[1]2457}
2458#endif
2459
[12221]2460
[12086]2461/**
[12221]2462 * Gets dr3.
[12086]2463 *
[12221]2464 * @returns dr3.
[12086]2465 */
[12221]2466#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2467RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR3(void);
[12086]2468#else
[58705]2469DECLINLINE(RTCCUINTXREG) ASMGetDR3(void)
[12086]2470{
[58705]2471 RTCCUINTXREG uDR3;
[12221]2472# if RT_INLINE_ASM_USES_INTRIN
2473 uDR3 = __readdr(3);
2474# elif RT_INLINE_ASM_GNU_STYLE
[12086]2475# ifdef RT_ARCH_AMD64
[12221]2476 __asm__ __volatile__("movq %%dr3, %0\n\t" : "=r" (uDR3));
[12086]2477# else
[12221]2478 __asm__ __volatile__("movl %%dr3, %0\n\t" : "=r" (uDR3));
[12086]2479# endif
2480# else
2481 __asm
2482 {
2483# ifdef RT_ARCH_AMD64
[12221]2484 mov rax, dr3
2485 mov [uDR3], rax
[12086]2486# else
[12221]2487 mov eax, dr3
2488 mov [uDR3], eax
[12086]2489# endif
2490 }
2491# endif
[12221]2492 return uDR3;
[12086]2493}
2494#endif
[1]2495
[12086]2496
[2144]2497/**
[12221]2498 * Gets dr6.
[12086]2499 *
[12221]2500 * @returns dr6.
[12086]2501 */
[12221]2502#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2503RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR6(void);
[12086]2504#else
[58705]2505DECLINLINE(RTCCUINTXREG) ASMGetDR6(void)
[12086]2506{
[58705]2507 RTCCUINTXREG uDR6;
[12221]2508# if RT_INLINE_ASM_USES_INTRIN
2509 uDR6 = __readdr(6);
2510# elif RT_INLINE_ASM_GNU_STYLE
[12086]2511# ifdef RT_ARCH_AMD64
[12221]2512 __asm__ __volatile__("movq %%dr6, %0\n\t" : "=r" (uDR6));
[12086]2513# else
[12221]2514 __asm__ __volatile__("movl %%dr6, %0\n\t" : "=r" (uDR6));
[12086]2515# endif
2516# else
2517 __asm
2518 {
2519# ifdef RT_ARCH_AMD64
[12221]2520 mov rax, dr6
2521 mov [uDR6], rax
[12086]2522# else
[12221]2523 mov eax, dr6
2524 mov [uDR6], eax
[12086]2525# endif
2526 }
2527# endif
[12221]2528 return uDR6;
[12086]2529}
2530#endif
2531
[12221]2532
[12086]2533/**
[12221]2534 * Reads and clears DR6.
[12086]2535 *
[12221]2536 * @returns DR6.
[12086]2537 */
[12221]2538#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2539RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetAndClearDR6(void);
[12086]2540#else
[58705]2541DECLINLINE(RTCCUINTXREG) ASMGetAndClearDR6(void)
[12086]2542{
[58705]2543 RTCCUINTXREG uDR6;
[12221]2544# if RT_INLINE_ASM_USES_INTRIN
2545 uDR6 = __readdr(6);
2546 __writedr(6, 0xffff0ff0U); /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
2547# elif RT_INLINE_ASM_GNU_STYLE
[58705]2548 RTCCUINTXREG uNewValue = 0xffff0ff0U;/* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
[12086]2549# ifdef RT_ARCH_AMD64
[12221]2550 __asm__ __volatile__("movq %%dr6, %0\n\t"
2551 "movq %1, %%dr6\n\t"
2552 : "=r" (uDR6)
2553 : "r" (uNewValue));
[12086]2554# else
[12221]2555 __asm__ __volatile__("movl %%dr6, %0\n\t"
2556 "movl %1, %%dr6\n\t"
2557 : "=r" (uDR6)
2558 : "r" (uNewValue));
[12086]2559# endif
2560# else
2561 __asm
2562 {
2563# ifdef RT_ARCH_AMD64
[12221]2564 mov rax, dr6
2565 mov [uDR6], rax
2566 mov rcx, rax
2567 mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
2568 mov dr6, rcx
[12086]2569# else
[12221]2570 mov eax, dr6
2571 mov [uDR6], eax
2572 mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 is zero. */
2573 mov dr6, ecx
[12086]2574# endif
2575 }
2576# endif
[12221]2577 return uDR6;
[12086]2578}
2579#endif
2580
[12221]2581
[12086]2582/**
[12221]2583 * Gets dr7.
[12086]2584 *
[12221]2585 * @returns dr7.
[12086]2586 */
[12221]2587#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2588RT_ASM_DECL_PRAGMA_WATCOM(RTCCUINTXREG) ASMGetDR7(void);
[12086]2589#else
[58705]2590DECLINLINE(RTCCUINTXREG) ASMGetDR7(void)
[12086]2591{
[58705]2592 RTCCUINTXREG uDR7;
[12221]2593# if RT_INLINE_ASM_USES_INTRIN
2594 uDR7 = __readdr(7);
2595# elif RT_INLINE_ASM_GNU_STYLE
[12086]2596# ifdef RT_ARCH_AMD64
[12221]2597 __asm__ __volatile__("movq %%dr7, %0\n\t" : "=r" (uDR7));
[12086]2598# else
[12221]2599 __asm__ __volatile__("movl %%dr7, %0\n\t" : "=r" (uDR7));
[12086]2600# endif
2601# else
2602 __asm
2603 {
2604# ifdef RT_ARCH_AMD64
[12221]2605 mov rax, dr7
2606 mov [uDR7], rax
[12086]2607# else
[12221]2608 mov eax, dr7
2609 mov [uDR7], eax
[12086]2610# endif
2611 }
2612# endif
[12221]2613 return uDR7;
[12086]2614}
2615#endif
2616
[12221]2617
[12086]2618/**
[12087]2619 * Sets dr0.
2620 *
2621 * @param uDRVal Debug register value to write
2622 */
[12221]2623#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2624RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR0(RTCCUINTXREG uDRVal);
[12087]2625#else
[58705]2626DECLINLINE(void) ASMSetDR0(RTCCUINTXREG uDRVal)
[12087]2627{
[12221]2628# if RT_INLINE_ASM_USES_INTRIN
2629 __writedr(0, uDRVal);
2630# elif RT_INLINE_ASM_GNU_STYLE
[12087]2631# ifdef RT_ARCH_AMD64
[12223]2632 __asm__ __volatile__("movq %0, %%dr0\n\t" : : "r" (uDRVal));
[12087]2633# else
[12223]2634 __asm__ __volatile__("movl %0, %%dr0\n\t" : : "r" (uDRVal));
[12087]2635# endif
2636# else
2637 __asm
2638 {
2639# ifdef RT_ARCH_AMD64
[12221]2640 mov rax, [uDRVal]
2641 mov dr0, rax
[12087]2642# else
[12092]2643 mov eax, [uDRVal]
2644 mov dr0, eax
[12087]2645# endif
2646 }
2647# endif
2648}
2649#endif
2650
[12221]2651
[12087]2652/**
2653 * Sets dr1.
2654 *
2655 * @param uDRVal Debug register value to write
2656 */
[12221]2657#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2658RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR1(RTCCUINTXREG uDRVal);
[12087]2659#else
[58705]2660DECLINLINE(void) ASMSetDR1(RTCCUINTXREG uDRVal)
[12087]2661{
[12221]2662# if RT_INLINE_ASM_USES_INTRIN
2663 __writedr(1, uDRVal);
2664# elif RT_INLINE_ASM_GNU_STYLE
[12087]2665# ifdef RT_ARCH_AMD64
[12223]2666 __asm__ __volatile__("movq %0, %%dr1\n\t" : : "r" (uDRVal));
[12087]2667# else
[12223]2668 __asm__ __volatile__("movl %0, %%dr1\n\t" : : "r" (uDRVal));
[12087]2669# endif
2670# else
2671 __asm
2672 {
2673# ifdef RT_ARCH_AMD64
[12221]2674 mov rax, [uDRVal]
2675 mov dr1, rax
[12087]2676# else
[12092]2677 mov eax, [uDRVal]
2678 mov dr1, eax
[12087]2679# endif
2680 }
2681# endif
2682}
2683#endif
2684
[12221]2685
[12087]2686/**
2687 * Sets dr2.
2688 *
2689 * @param uDRVal Debug register value to write
2690 */
[12221]2691#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2692RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR2(RTCCUINTXREG uDRVal);
[12087]2693#else
[58705]2694DECLINLINE(void) ASMSetDR2(RTCCUINTXREG uDRVal)
[12087]2695{
[12221]2696# if RT_INLINE_ASM_USES_INTRIN
2697 __writedr(2, uDRVal);
2698# elif RT_INLINE_ASM_GNU_STYLE
[12087]2699# ifdef RT_ARCH_AMD64
[12223]2700 __asm__ __volatile__("movq %0, %%dr2\n\t" : : "r" (uDRVal));
[12087]2701# else
[12223]2702 __asm__ __volatile__("movl %0, %%dr2\n\t" : : "r" (uDRVal));
[12087]2703# endif
2704# else
2705 __asm
2706 {
2707# ifdef RT_ARCH_AMD64
[12221]2708 mov rax, [uDRVal]
2709 mov dr2, rax
[12087]2710# else
[12092]2711 mov eax, [uDRVal]
2712 mov dr2, eax
[12087]2713# endif
2714 }
2715# endif
2716}
2717#endif
2718
[12221]2719
[12087]2720/**
2721 * Sets dr3.
2722 *
2723 * @param uDRVal Debug register value to write
2724 */
[12221]2725#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2726RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR3(RTCCUINTXREG uDRVal);
[12087]2727#else
[58705]2728DECLINLINE(void) ASMSetDR3(RTCCUINTXREG uDRVal)
[12087]2729{
[12221]2730# if RT_INLINE_ASM_USES_INTRIN
2731 __writedr(3, uDRVal);
2732# elif RT_INLINE_ASM_GNU_STYLE
[12087]2733# ifdef RT_ARCH_AMD64
[12223]2734 __asm__ __volatile__("movq %0, %%dr3\n\t" : : "r" (uDRVal));
[12087]2735# else
[12223]2736 __asm__ __volatile__("movl %0, %%dr3\n\t" : : "r" (uDRVal));
[12087]2737# endif
2738# else
2739 __asm
2740 {
2741# ifdef RT_ARCH_AMD64
[12221]2742 mov rax, [uDRVal]
2743 mov dr3, rax
[12087]2744# else
[12092]2745 mov eax, [uDRVal]
2746 mov dr3, eax
[12087]2747# endif
2748 }
2749# endif
2750}
2751#endif
2752
[12221]2753
[12087]2754/**
2755 * Sets dr6.
2756 *
2757 * @param uDRVal Debug register value to write
2758 */
[12221]2759#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2760RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR6(RTCCUINTXREG uDRVal);
[12087]2761#else
[58705]2762DECLINLINE(void) ASMSetDR6(RTCCUINTXREG uDRVal)
[12087]2763{
[12221]2764# if RT_INLINE_ASM_USES_INTRIN
2765 __writedr(6, uDRVal);
2766# elif RT_INLINE_ASM_GNU_STYLE
[12087]2767# ifdef RT_ARCH_AMD64
[12223]2768 __asm__ __volatile__("movq %0, %%dr6\n\t" : : "r" (uDRVal));
[12087]2769# else
[12223]2770 __asm__ __volatile__("movl %0, %%dr6\n\t" : : "r" (uDRVal));
[12087]2771# endif
2772# else
2773 __asm
2774 {
2775# ifdef RT_ARCH_AMD64
[12221]2776 mov rax, [uDRVal]
2777 mov dr6, rax
[12087]2778# else
[12092]2779 mov eax, [uDRVal]
2780 mov dr6, eax
[12087]2781# endif
2782 }
2783# endif
2784}
2785#endif
2786
[12221]2787
[12087]2788/**
2789 * Sets dr7.
2790 *
2791 * @param uDRVal Debug register value to write
2792 */
[12221]2793#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2794RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetDR7(RTCCUINTXREG uDRVal);
[12087]2795#else
[58705]2796DECLINLINE(void) ASMSetDR7(RTCCUINTXREG uDRVal)
[12087]2797{
[12221]2798# if RT_INLINE_ASM_USES_INTRIN
2799 __writedr(7, uDRVal);
2800# elif RT_INLINE_ASM_GNU_STYLE
[12087]2801# ifdef RT_ARCH_AMD64
[12223]2802 __asm__ __volatile__("movq %0, %%dr7\n\t" : : "r" (uDRVal));
[12087]2803# else
[12223]2804 __asm__ __volatile__("movl %0, %%dr7\n\t" : : "r" (uDRVal));
[12087]2805# endif
2806# else
2807 __asm
2808 {
2809# ifdef RT_ARCH_AMD64
[12221]2810 mov rax, [uDRVal]
2811 mov dr7, rax
[12087]2812# else
[12092]2813 mov eax, [uDRVal]
2814 mov dr7, eax
[12087]2815# endif
2816 }
2817# endif
2818}
2819#endif
2820
[12221]2821
[12087]2822/**
[6782]2823 * Writes a 8-bit unsigned integer to an I/O port, ordered.
[1]2824 *
[18521]2825 * @param Port I/O port to write to.
[1]2826 * @param u8 8-bit integer to write.
2827 */
2828#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2829RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutU8(RTIOPORT Port, uint8_t u8);
[1]2830#else
2831DECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8)
2832{
2833# if RT_INLINE_ASM_GNU_STYLE
2834 __asm__ __volatile__("outb %b1, %w0\n\t"
2835 :: "Nd" (Port),
2836 "a" (u8));
2837
2838# elif RT_INLINE_ASM_USES_INTRIN
2839 __outbyte(Port, u8);
2840
2841# else
2842 __asm
2843 {
2844 mov dx, [Port]
2845 mov al, [u8]
2846 out dx, al
2847 }
2848# endif
2849}
2850#endif
2851
2852
2853/**
[18521]2854 * Reads a 8-bit unsigned integer from an I/O port, ordered.
[1]2855 *
2856 * @returns 8-bit integer.
2857 * @param Port I/O port to read from.
2858 */
2859#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2860RT_ASM_DECL_PRAGMA_WATCOM(uint8_t) ASMInU8(RTIOPORT Port);
[1]2861#else
2862DECLINLINE(uint8_t) ASMInU8(RTIOPORT Port)
2863{
2864 uint8_t u8;
2865# if RT_INLINE_ASM_GNU_STYLE
2866 __asm__ __volatile__("inb %w1, %b0\n\t"
2867 : "=a" (u8)
2868 : "Nd" (Port));
2869
2870# elif RT_INLINE_ASM_USES_INTRIN
2871 u8 = __inbyte(Port);
2872
2873# else
2874 __asm
2875 {
2876 mov dx, [Port]
2877 in al, dx
2878 mov [u8], al
2879 }
2880# endif
2881 return u8;
2882}
2883#endif
2884
2885
2886/**
[6782]2887 * Writes a 16-bit unsigned integer to an I/O port, ordered.
[1]2888 *
[18521]2889 * @param Port I/O port to write to.
[1]2890 * @param u16 16-bit integer to write.
2891 */
2892#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2893RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutU16(RTIOPORT Port, uint16_t u16);
[1]2894#else
2895DECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16)
2896{
2897# if RT_INLINE_ASM_GNU_STYLE
2898 __asm__ __volatile__("outw %w1, %w0\n\t"
2899 :: "Nd" (Port),
2900 "a" (u16));
2901
2902# elif RT_INLINE_ASM_USES_INTRIN
2903 __outword(Port, u16);
2904
2905# else
2906 __asm
2907 {
2908 mov dx, [Port]
2909 mov ax, [u16]
2910 out dx, ax
2911 }
2912# endif
2913}
2914#endif
2915
2916
2917/**
[18521]2918 * Reads a 16-bit unsigned integer from an I/O port, ordered.
[1]2919 *
2920 * @returns 16-bit integer.
2921 * @param Port I/O port to read from.
2922 */
2923#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2924RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMInU16(RTIOPORT Port);
[1]2925#else
2926DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port)
2927{
2928 uint16_t u16;
2929# if RT_INLINE_ASM_GNU_STYLE
2930 __asm__ __volatile__("inw %w1, %w0\n\t"
2931 : "=a" (u16)
2932 : "Nd" (Port));
2933
2934# elif RT_INLINE_ASM_USES_INTRIN
2935 u16 = __inword(Port);
2936
2937# else
2938 __asm
2939 {
2940 mov dx, [Port]
2941 in ax, dx
2942 mov [u16], ax
2943 }
2944# endif
2945 return u16;
2946}
2947#endif
2948
2949
2950/**
[6782]2951 * Writes a 32-bit unsigned integer to an I/O port, ordered.
[1]2952 *
[18521]2953 * @param Port I/O port to write to.
[1]2954 * @param u32 32-bit integer to write.
2955 */
2956#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2957RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutU32(RTIOPORT Port, uint32_t u32);
[1]2958#else
2959DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32)
2960{
2961# if RT_INLINE_ASM_GNU_STYLE
2962 __asm__ __volatile__("outl %1, %w0\n\t"
2963 :: "Nd" (Port),
2964 "a" (u32));
2965
2966# elif RT_INLINE_ASM_USES_INTRIN
2967 __outdword(Port, u32);
2968
2969# else
2970 __asm
2971 {
2972 mov dx, [Port]
2973 mov eax, [u32]
2974 out dx, eax
2975 }
2976# endif
2977}
2978#endif
2979
2980
2981/**
[18521]2982 * Reads a 32-bit unsigned integer from an I/O port, ordered.
[1]2983 *
2984 * @returns 32-bit integer.
2985 * @param Port I/O port to read from.
2986 */
2987#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]2988RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMInU32(RTIOPORT Port);
[1]2989#else
2990DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port)
2991{
2992 uint32_t u32;
2993# if RT_INLINE_ASM_GNU_STYLE
2994 __asm__ __volatile__("inl %w1, %0\n\t"
2995 : "=a" (u32)
2996 : "Nd" (Port));
2997
2998# elif RT_INLINE_ASM_USES_INTRIN
2999 u32 = __indword(Port);
3000
3001# else
3002 __asm
3003 {
3004 mov dx, [Port]
3005 in eax, dx
3006 mov [u32], eax
3007 }
3008# endif
3009 return u32;
3010}
3011#endif
3012
3013
[18521]3014/**
3015 * Writes a string of 8-bit unsigned integer items to an I/O port, ordered.
3016 *
3017 * @param Port I/O port to write to.
3018 * @param pau8 Pointer to the string buffer.
3019 * @param c The number of items to write.
3020 */
3021#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3022RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const RT_FAR *pau8, size_t c);
[18521]3023#else
[68606]3024DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const RT_FAR *pau8, size_t c)
[18521]3025{
3026# if RT_INLINE_ASM_GNU_STYLE
3027 __asm__ __volatile__("rep; outsb\n\t"
3028 : "+S" (pau8),
3029 "+c" (c)
3030 : "d" (Port));
[6782]3031
[18521]3032# elif RT_INLINE_ASM_USES_INTRIN
[68606]3033 __outbytestring(Port, (unsigned char RT_FAR *)pau8, (unsigned long)c);
[18521]3034
3035# else
3036 __asm
3037 {
3038 mov dx, [Port]
3039 mov ecx, [c]
3040 mov eax, [pau8]
3041 xchg esi, eax
3042 rep outsb
3043 xchg esi, eax
3044 }
3045# endif
3046}
3047#endif
3048
3049
[1]3050/**
[18521]3051 * Reads a string of 8-bit unsigned integer items from an I/O port, ordered.
3052 *
3053 * @param Port I/O port to read from.
3054 * @param pau8 Pointer to the string buffer (output).
3055 * @param c The number of items to read.
3056 */
3057#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3058RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU8(RTIOPORT Port, uint8_t RT_FAR *pau8, size_t c);
[18521]3059#else
[68606]3060DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t RT_FAR *pau8, size_t c)
[18521]3061{
3062# if RT_INLINE_ASM_GNU_STYLE
3063 __asm__ __volatile__("rep; insb\n\t"
3064 : "+D" (pau8),
3065 "+c" (c)
3066 : "d" (Port));
3067
3068# elif RT_INLINE_ASM_USES_INTRIN
3069 __inbytestring(Port, pau8, (unsigned long)c);
3070
3071# else
3072 __asm
3073 {
3074 mov dx, [Port]
3075 mov ecx, [c]
3076 mov eax, [pau8]
3077 xchg edi, eax
3078 rep insb
3079 xchg edi, eax
3080 }
3081# endif
3082}
3083#endif
3084
3085
3086/**
3087 * Writes a string of 16-bit unsigned integer items to an I/O port, ordered.
3088 *
3089 * @param Port I/O port to write to.
3090 * @param pau16 Pointer to the string buffer.
3091 * @param c The number of items to write.
3092 */
3093#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3094RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const RT_FAR *pau16, size_t c);
[18521]3095#else
[68606]3096DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const RT_FAR *pau16, size_t c)
[18521]3097{
3098# if RT_INLINE_ASM_GNU_STYLE
3099 __asm__ __volatile__("rep; outsw\n\t"
3100 : "+S" (pau16),
3101 "+c" (c)
3102 : "d" (Port));
3103
3104# elif RT_INLINE_ASM_USES_INTRIN
[68606]3105 __outwordstring(Port, (unsigned short RT_FAR *)pau16, (unsigned long)c);
[18521]3106
3107# else
3108 __asm
3109 {
3110 mov dx, [Port]
3111 mov ecx, [c]
3112 mov eax, [pau16]
3113 xchg esi, eax
3114 rep outsw
3115 xchg esi, eax
3116 }
3117# endif
3118}
3119#endif
3120
3121
3122/**
3123 * Reads a string of 16-bit unsigned integer items from an I/O port, ordered.
3124 *
3125 * @param Port I/O port to read from.
3126 * @param pau16 Pointer to the string buffer (output).
3127 * @param c The number of items to read.
3128 */
3129#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3130RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU16(RTIOPORT Port, uint16_t RT_FAR *pau16, size_t c);
[18521]3131#else
[68606]3132DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t RT_FAR *pau16, size_t c)
[18521]3133{
3134# if RT_INLINE_ASM_GNU_STYLE
3135 __asm__ __volatile__("rep; insw\n\t"
3136 : "+D" (pau16),
3137 "+c" (c)
3138 : "d" (Port));
3139
3140# elif RT_INLINE_ASM_USES_INTRIN
3141 __inwordstring(Port, pau16, (unsigned long)c);
3142
3143# else
3144 __asm
3145 {
3146 mov dx, [Port]
3147 mov ecx, [c]
3148 mov eax, [pau16]
3149 xchg edi, eax
3150 rep insw
3151 xchg edi, eax
3152 }
3153# endif
3154}
3155#endif
3156
3157
3158/**
3159 * Writes a string of 32-bit unsigned integer items to an I/O port, ordered.
3160 *
3161 * @param Port I/O port to write to.
3162 * @param pau32 Pointer to the string buffer.
3163 * @param c The number of items to write.
3164 */
3165#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3166RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const RT_FAR *pau32, size_t c);
[18521]3167#else
[68606]3168DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const RT_FAR *pau32, size_t c)
[18521]3169{
3170# if RT_INLINE_ASM_GNU_STYLE
3171 __asm__ __volatile__("rep; outsl\n\t"
3172 : "+S" (pau32),
3173 "+c" (c)
3174 : "d" (Port));
3175
3176# elif RT_INLINE_ASM_USES_INTRIN
[68606]3177 __outdwordstring(Port, (unsigned long RT_FAR *)pau32, (unsigned long)c);
[18521]3178
3179# else
3180 __asm
3181 {
3182 mov dx, [Port]
3183 mov ecx, [c]
3184 mov eax, [pau32]
3185 xchg esi, eax
3186 rep outsd
3187 xchg esi, eax
3188 }
3189# endif
3190}
3191#endif
3192
3193
3194/**
3195 * Reads a string of 32-bit unsigned integer items from an I/O port, ordered.
3196 *
3197 * @param Port I/O port to read from.
3198 * @param pau32 Pointer to the string buffer (output).
3199 * @param c The number of items to read.
3200 */
3201#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3202RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU32(RTIOPORT Port, uint32_t RT_FAR *pau32, size_t c);
[18521]3203#else
[68606]3204DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t RT_FAR *pau32, size_t c)
[18521]3205{
3206# if RT_INLINE_ASM_GNU_STYLE
3207 __asm__ __volatile__("rep; insl\n\t"
3208 : "+D" (pau32),
3209 "+c" (c)
3210 : "d" (Port));
3211
3212# elif RT_INLINE_ASM_USES_INTRIN
[68606]3213 __indwordstring(Port, (unsigned long RT_FAR *)pau32, (unsigned long)c);
[18521]3214
3215# else
3216 __asm
3217 {
3218 mov dx, [Port]
3219 mov ecx, [c]
3220 mov eax, [pau32]
3221 xchg edi, eax
3222 rep insd
3223 xchg edi, eax
3224 }
3225# endif
3226}
3227#endif
3228
3229
3230/**
[29245]3231 * Invalidate page.
[1]3232 *
[60235]3233 * @param uPtr Address of the page to invalidate.
[1]3234 */
3235#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3236RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInvalidatePage(RTCCUINTXREG uPtr);
[1]3237#else
[60228]3238DECLINLINE(void) ASMInvalidatePage(RTCCUINTXREG uPtr)
[1]3239{
3240# if RT_INLINE_ASM_USES_INTRIN
[68606]3241 __invlpg((void RT_FAR *)uPtr);
[1]3242
[7180]3243# elif RT_INLINE_ASM_GNU_STYLE
[29245]3244 __asm__ __volatile__("invlpg %0\n\t"
[68606]3245 : : "m" (*(uint8_t RT_FAR *)(uintptr_t)uPtr));
[7180]3246# else
3247 __asm
3248 {
3249# ifdef RT_ARCH_AMD64
[60228]3250 mov rax, [uPtr]
[29245]3251 invlpg [rax]
[7180]3252# else
[60228]3253 mov eax, [uPtr]
[29245]3254 invlpg [eax]
[7180]3255# endif
3256 }
3257# endif
3258}
3259#endif
3260
3261
3262/**
[29245]3263 * Write back the internal caches and invalidate them.
[7180]3264 */
[1]3265#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
[75131]3266RT_ASM_DECL_PRAGMA_WATCOM(void) ASMWriteBackAndInvalidateCaches(void);
[1]3267#else
[29245]3268DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
[1]3269{
3270# if RT_INLINE_ASM_USES_INTRIN
[29245]3271 __wbinvd();
[1]3272
3273# elif RT_INLINE_ASM_GNU_STYLE
[29245]3274 __asm__ __volatile__("wbinvd");
[1]3275# else
3276 __asm
3277 {
[29245]3278 wbinvd
[1]3279 }
3280# endif
3281}
3282#endif
3283
3284
3285/**
[29245]3286 * Invalidate internal and (perhaps) external caches without first
3287 * flushing dirty cache lines. Use with extreme care.
[1]3288 */
[29245]3289#if RT_INLINE_ASM_EXTERNAL
[75131]3290RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInvalidateInternalCaches(void);
[1]3291#else
[29245]3292DECLINLINE(void) ASMInvalidateInternalCaches(void)
[1]3293{
[20624]3294# if RT_INLINE_ASM_GNU_STYLE
[29245]3295 __asm__ __volatile__("invd");
[20624]3296# else
3297 __asm
3298 {
[29245]3299 invd
[20624]3300 }
3301# endif
3302}
3303#endif
3304
3305
[1]3306/**
[21234]3307 * Memory load/store fence, waits for any pending writes and reads to complete.
3308 * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
3309 */
3310DECLINLINE(void) ASMMemoryFenceSSE2(void)
3311{
[21235]3312#if RT_INLINE_ASM_GNU_STYLE
[21234]3313 __asm__ __volatile__ (".byte 0x0f,0xae,0xf0\n\t");
[21236]3314#elif RT_INLINE_ASM_USES_INTRIN
3315 _mm_mfence();
[21234]3316#else
3317 __asm
3318 {
[21236]3319 _emit 0x0f
3320 _emit 0xae
3321 _emit 0xf0
[21234]3322 }
3323#endif
3324}
3325
3326
3327/**
3328 * Memory store fence, waits for any writes to complete.
3329 * Requires the X86_CPUID_FEATURE_EDX_SSE CPUID bit set.
3330 */
3331DECLINLINE(void) ASMWriteFenceSSE(void)
3332{
[21235]3333#if RT_INLINE_ASM_GNU_STYLE
[21234]3334 __asm__ __volatile__ (".byte 0x0f,0xae,0xf8\n\t");
[21236]3335#elif RT_INLINE_ASM_USES_INTRIN
3336 _mm_sfence();
[21234]3337#else
3338 __asm
3339 {
[21236]3340 _emit 0x0f
3341 _emit 0xae
3342 _emit 0xf8
[21234]3343 }
3344#endif
3345}
3346
3347
3348/**
3349 * Memory load fence, waits for any pending reads to complete.
3350 * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
3351 */
3352DECLINLINE(void) ASMReadFenceSSE2(void)
3353{
[21235]3354#if RT_INLINE_ASM_GNU_STYLE
[21234]3355 __asm__ __volatile__ (".byte 0x0f,0xae,0xe8\n\t");
[21236]3356#elif RT_INLINE_ASM_USES_INTRIN
3357 _mm_lfence();
[21234]3358#else
3359 __asm
3360 {
[21236]3361 _emit 0x0f
3362 _emit 0xae
3363 _emit 0xe8
[21234]3364 }
3365#endif
3366}
3367
[55319]3368#if !defined(_MSC_VER) || !defined(RT_ARCH_AMD64)
[55318]3369
3370/*
3371 * Clear the AC bit in the EFLAGS register.
3372 * Requires the X86_CPUID_STEXT_FEATURE_EBX_SMAP CPUID bit set.
3373 * Requires to be executed in R0.
3374 */
3375DECLINLINE(void) ASMClearAC(void)
3376{
3377#if RT_INLINE_ASM_GNU_STYLE
3378 __asm__ __volatile__ (".byte 0x0f,0x01,0xca\n\t");
3379#else
3380 __asm
3381 {
3382 _emit 0x0f
3383 _emit 0x01
3384 _emit 0xca
3385 }
3386#endif
3387}
3388
3389
3390/*
3391 * Set the AC bit in the EFLAGS register.
3392 * Requires the X86_CPUID_STEXT_FEATURE_EBX_SMAP CPUID bit set.
3393 * Requires to be executed in R0.
3394 */
3395DECLINLINE(void) ASMSetAC(void)
3396{
3397#if RT_INLINE_ASM_GNU_STYLE
3398 __asm__ __volatile__ (".byte 0x0f,0x01,0xcb\n\t");
3399#else
3400 __asm
3401 {
3402 _emit 0x0f
3403 _emit 0x01
3404 _emit 0xcb
3405 }
3406#endif
3407}
3408
[75131]3409#endif /* !_MSC_VER || !RT_ARCH_AMD64 */
[55319]3410
[75131]3411
3412/*
3413 * Include #pragma aux definitions for Watcom C/C++.
3414 */
3415#if defined(__WATCOMC__) && ARCH_BITS == 16
3416# define IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
[76557]3417# undef IPRT_INCLUDED_asm_amd64_x86_watcom_16_h
[75131]3418# include "asm-amd64-x86-watcom-16.h"
3419#elif defined(__WATCOMC__) && ARCH_BITS == 32
3420# define IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
[76557]3421# undef IPRT_INCLUDED_asm_amd64_x86_watcom_32_h
[75131]3422# include "asm-amd64-x86-watcom-32.h"
3423#endif
3424
3425
[1]3426/** @} */
[76585]3427#endif /* !IPRT_INCLUDED_asm_amd64_x86_h */
[1]3428
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette