asm.h revision ec1eca74badc326cb04c0d139286e5a2ce99da63
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @file
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * innotek Portable Runtime - Assembly Functions.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/*
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Copyright (C) 2006-2007 innotek GmbH
c58f1213e628a545081c70e26c6b67a841cff880vboxsync *
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * available from http://www.virtualbox.org. This file is free software;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * you can redistribute it and/or modify it under the terms of the GNU
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * General Public License as published by the Free Software Foundation,
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#ifndef ___iprt_asm_h
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#define ___iprt_asm_h
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#include <iprt/cdefs.h>
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#include <iprt/types.h>
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @todo #include <iprt/param.h> for PAGE_SIZE. */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @def RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Defined as 1 if we're using a _MSC_VER 1400.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Otherwise defined as 0.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#ifdef _MSC_VER
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if _MSC_VER >= 1400
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# define RT_INLINE_ASM_USES_INTRIN 1
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# include <intrin.h>
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync /* Emit the intrinsics at all optimization levels. */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_ReadWriteBarrier)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__cpuid)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_enable)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_disable)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__rdtsc)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__readmsr)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__writemsr)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__outbyte)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__outword)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__outdword)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__inbyte)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__inword)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__indword)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# pragma intrinsic(__invlpg)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# pragma intrinsic(__stosd)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# pragma intrinsic(__stosw)
d1c36fd86d36726777e3d6f9d040573e0aaf30devboxsync# pragma intrinsic(__stosb)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# pragma intrinsic(__readcr0)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__readcr2)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__readcr3)
76cb9831bbeaff3bb30068363e35660a776736c4vboxsync# pragma intrinsic(__readcr4)
d68336e34409fd767807d5ef641a305de4d9ee59vboxsync# pragma intrinsic(__writecr0)
d68336e34409fd767807d5ef641a305de4d9ee59vboxsync# pragma intrinsic(__writecr3)
76cb9831bbeaff3bb30068363e35660a776736c4vboxsync# pragma intrinsic(__writecr4)
76cb9831bbeaff3bb30068363e35660a776736c4vboxsync# pragma intrinsic(_BitScanForward)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_BitScanReverse)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_bittest)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_bittestandset)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_bittestandreset)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_bittestandcomplement)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_byteswap_ushort)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_byteswap_ulong)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_interlockedbittestandset)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_interlockedbittestandreset)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedAnd)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedOr)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedIncrement)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedDecrement)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedExchange)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedCompareExchange)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_InterlockedCompareExchange64)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__stosq)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__readcr8)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(__writecr8)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# pragma intrinsic(_byteswap_uint64)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# pragma intrinsic(_InterlockedExchange64)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#ifndef RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# define RT_INLINE_ASM_USES_INTRIN 0
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @defgroup grp_asm ASM - Assembly Routines
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @ingroup grp_rt
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @def RT_INLINE_ASM_EXTERNAL
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Defined as 1 if the compiler does not support inline assembly.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * The ASM* functions will then be implemented in an external .asm file.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync *
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @remark At the present time it's unconfirmed whether or not Microsoft skipped
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * inline assmebly in their AMD64 compiler.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# define RT_INLINE_ASM_EXTERNAL 1
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# define RT_INLINE_ASM_EXTERNAL 0
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync/** @def RT_INLINE_ASM_GNU_STYLE
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * Defined as 1 if the compiler understand GNU style inline assembly.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync */
619824b60d668e6e43f385ef78cf06e13d43aab6vboxsync#if defined(_MSC_VER)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# define RT_INLINE_ASM_GNU_STYLE 0
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# define RT_INLINE_ASM_GNU_STYLE 1
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync/** @todo find a more proper place for this structure? */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#pragma pack(1)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync/** IDTR */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsynctypedef struct RTIDTR
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync{
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync /** Size of the IDT. */
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync uint16_t cbIdt;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync /** Address of the IDT. */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync uintptr_t pIdt;
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync} RTIDTR, *PRTIDTR;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#pragma pack()
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#pragma pack(1)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/** GDTR */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsynctypedef struct RTGDTR
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync /** Size of the GDT. */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync uint16_t cbGdt;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync /** Address of the GDT. */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync uintptr_t pGdt;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync} RTGDTR, *PRTGDTR;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#pragma pack()
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/** @def ASMReturnAddress
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Gets the return address of the current (or calling if you like) function or method.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#ifdef _MSC_VER
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef __cplusplus
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncextern "C"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncvoid * _ReturnAddress(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# pragma intrinsic(_ReturnAddress)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# define ASMReturnAddress() _ReturnAddress()
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#elif defined(__GNUC__) || defined(__DOXYGEN__)
b3109af8dcc2a3da7f424aa05a4e84a64bf1c43fvboxsync# define ASMReturnAddress() __builtin_return_address(0)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# error "Unsupported compiler."
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Gets the content of the IDTR CPU register.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @param pIdtr Where to store the IDTR contents.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#if RT_INLINE_ASM_EXTERNAL
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(void) ASMGetIDTR(PRTIDTR pIdtr);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("sidt %0" : "=m" (*pIdtr));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync {
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov rax, [pIdtr]
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync sidt [rax]
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov eax, [pIdtr]
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync sidt [eax]
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Sets the content of the IDTR CPU register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @param pIdtr Where to load the IDTR contents from
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(void) ASMSetIDTR(const RTIDTR *pIdtr);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsyncDECLINLINE(void) ASMSetIDTR(const RTIDTR *pIdtr)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("lidt %0" : : "m" (*pIdtr));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, [pIdtr]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync lidt [rax]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, [pIdtr]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync lidt [eax]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync}
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync#endif
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync/**
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync * Gets the content of the GDTR CPU register.
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync * @param pGdtr Where to store the GDTR contents.
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync */
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync#if RT_INLINE_ASM_EXTERNAL
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsyncDECLASM(void) ASMGetGDTR(PRTGDTR pGdtr);
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync#else
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsyncDECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync{
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync# if RT_INLINE_ASM_GNU_STYLE
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync __asm__ __volatile__ ("sgdt %0" : "=m" (*pGdtr));
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync# else
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync __asm
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync {
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync# ifdef RT_ARCH_AMD64
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync mov rax, [pGdtr]
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync sgdt [rax]
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync# else
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync mov eax, [pGdtr]
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync sgdt [eax]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync/**
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync * Get the cs register.
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync * @returns cs.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(RTSEL) ASMGetCS(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(RTSEL) ASMGetCS(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
0780b79e94db3b60fb4a3057df7c64ba8b1cb75dvboxsync RTSEL SelCS;
0780b79e94db3b60fb4a3057df7c64ba8b1cb75dvboxsync# if RT_INLINE_ASM_GNU_STYLE
0780b79e94db3b60fb4a3057df7c64ba8b1cb75dvboxsync __asm__ __volatile__("movw %%cs, %0\n\t" : "=r" (SelCS));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync __asm
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync {
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync mov ax, cs
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync mov [SelCS], ax
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync }
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync# endif
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync return SelCS;
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync}
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync#endif
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync/**
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync * Get the DS register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns DS.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsyncDECLASM(RTSEL) ASMGetDS(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(RTSEL) ASMGetDS(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTSEL SelDS;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__("movw %%ds, %0\n\t" : "=r" (SelDS));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov ax, ds
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync mov [SelDS], ax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync return SelDS;
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync}
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync#endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync/**
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync * Get the ES register.
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync * @returns ES.
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync */
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync#if RT_INLINE_ASM_EXTERNAL
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsyncDECLASM(RTSEL) ASMGetES(void);
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync#else
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsyncDECLINLINE(RTSEL) ASMGetES(void)
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync{
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync RTSEL SelES;
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# if RT_INLINE_ASM_GNU_STYLE
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm__ __volatile__("movw %%es, %0\n\t" : "=r" (SelES));
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# else
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync __asm
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync {
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync mov ax, es
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync mov [SelES], ax
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync }
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync return SelES;
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync}
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync/**
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync * Get the FS register.
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync * @returns FS.
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync */
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync#if RT_INLINE_ASM_EXTERNAL
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsyncDECLASM(RTSEL) ASMGetFS(void);
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync#else
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsyncDECLINLINE(RTSEL) ASMGetFS(void)
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync{
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync RTSEL SelFS;
619824b60d668e6e43f385ef78cf06e13d43aab6vboxsync# if RT_INLINE_ASM_GNU_STYLE
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync __asm__ __volatile__("movw %%fs, %0\n\t" : "=r" (SelFS));
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync# else
619824b60d668e6e43f385ef78cf06e13d43aab6vboxsync __asm
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync {
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync mov ax, fs
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync mov [SelFS], ax
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync return SelFS;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
76cb9831bbeaff3bb30068363e35660a776736c4vboxsync/**
76cb9831bbeaff3bb30068363e35660a776736c4vboxsync * Get the GS register.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @returns GS.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLASM(RTSEL) ASMGetGS(void);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(RTSEL) ASMGetGS(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTSEL SelGS;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__("movw %%gs, %0\n\t" : "=r" (SelGS));
5422fa26c16d9d065b5879feb3852da231be5c55vboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync {
619824b60d668e6e43f385ef78cf06e13d43aab6vboxsync mov ax, gs
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync mov [SelGS], ax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync return SelGS;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync}
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync * Get the SS register.
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync * @returns SS.
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL
76cb9831bbeaff3bb30068363e35660a776736c4vboxsyncDECLASM(RTSEL) ASMGetSS(void);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
76cb9831bbeaff3bb30068363e35660a776736c4vboxsyncDECLINLINE(RTSEL) ASMGetSS(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync RTSEL SelSS;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__("movw %%ss, %0\n\t" : "=r" (SelSS));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov ax, ss
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov [SelSS], ax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync return SelSS;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Get the TR register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns TR.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsyncDECLASM(RTSEL) ASMGetTR(void);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(RTSEL) ASMGetTR(void)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync RTSEL SelTR;
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# if RT_INLINE_ASM_GNU_STYLE
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# else
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync __asm
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync {
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync str ax
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync mov [SelTR], ax
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync }
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync return SelTR;
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync}
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync#endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Get the [RE]FLAGS register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns [RE]FLAGS.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMGetFlags(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(RTCCUINTREG) ASMGetFlags(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uFlags;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# ifdef RT_ARCH_AMD64
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync __asm__ __volatile__("pushfq\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "popq %0\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync : "=m" (uFlags));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__("pushfl\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "popl %0\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=m" (uFlags));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pushfq
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop [uFlags]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pushfd
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop [uFlags]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return uFlags;
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync}
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync#endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync/**
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync * Set the [RE]FLAGS register.
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync * @param uFlags The new [RE]FLAGS value.
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync */
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync#if RT_INLINE_ASM_EXTERNAL
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsyncDECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync#else
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsyncDECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync{
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# if RT_INLINE_ASM_GNU_STYLE
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# ifdef RT_ARCH_AMD64
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync __asm__ __volatile__("pushq %0\n\t"
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync "popfq\n\t"
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync : : "m" (uFlags));
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# else
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync __asm__ __volatile__("pushl %0\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "popfl\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : : "m" (uFlags));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync {
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# ifdef RT_ARCH_AMD64
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync push [uFlags]
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync popfq
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# else
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync push [uFlags]
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync popfd
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync }
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync# endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync}
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync#endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Gets the content of the CPU timestamp counter register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns TSC.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(uint64_t) ASMReadTSC(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(uint64_t) ASMReadTSC(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTUINT64U u;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__ ("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync u.u = __rdtsc();
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync rdtsc
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [u.s.Lo], eax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [u.s.Hi], edx
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return u.u;
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync/**
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync * Performs the cpuid instruction returning all registers.
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync *
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync * @param uOperator CPUID operation (eax).
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync * @param pvEAX Where to store eax.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param pvEBX Where to store ebx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param pvECX Where to store ecx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param pvEDX Where to store edx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @remark We're using void pointers to ease the use of special bitfield structures and such.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("cpuid\n\t"
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync : "=a" (uRAX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=b" (uRBX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=c" (uRCX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=d" (uRDX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEAX = (uint32_t)uRAX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEBX = (uint32_t)uRBX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvECX = (uint32_t)uRCX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEDX = (uint32_t)uRDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("xchgl %%ebx, %1\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "cpuid\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "xchgl %%ebx, %1\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (*(uint32_t *)pvEAX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=r" (*(uint32_t *)pvEBX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=c" (*(uint32_t *)pvECX),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=d" (*(uint32_t *)pvEDX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync int aInfo[4];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __cpuid(aInfo, uOperator);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEAX = aInfo[0];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEBX = aInfo[1];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvECX = aInfo[2];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEDX = aInfo[3];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t uEAX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t uEBX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t uECX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t uEDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync push ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, [uOperator]
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync cpuid
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uEAX], eax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uEBX], ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uECX], ecx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uEDX], edx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEAX = uEAX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEBX = uEBX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvECX = uECX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *(uint32_t *)pvEDX = uEDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Performs the cpuid instruction returning ecx and edx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uOperator CPUID operation (eax).
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param pvECX Where to store ecx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param pvEDX Where to store edx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @remark We're using void pointers to ease the use of special bitfield structures and such.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t uEBX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Performs the cpuid instruction returning edx.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uOperator CPUID operation (eax).
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns EDX after cpuid operation.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(uint32_t) ASMCpuId_EDX(uint32_t uOperator);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG xDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uSpill;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("cpuid"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uSpill),
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "=d" (xDX)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "0" (uOperator)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync : "rbx", "rcx");
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# elif (defined(PIC) || defined(RT_OS_DARWIN)) && defined(__i386__) /* darwin: PIC by default. */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm__ ("push %%ebx\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "cpuid\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync "pop %%ebx\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "=a" (uOperator),
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "=d" (xDX)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "0" (uOperator)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync : "ecx");
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("cpuid"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uOperator),
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "=d" (xDX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "ebx", "ecx");
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync int aInfo[4];
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __cpuid(aInfo, uOperator);
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync xDX = aInfo[3];
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync# else
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync __asm
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync {
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync push ebx
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync mov eax, [uOperator]
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync cpuid
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync mov [xDX], edx
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync pop ebx
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return (uint32_t)xDX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Performs the cpuid instruction returning ecx.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync *
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync * @param uOperator CPUID operation (eax).
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns ECX after cpuid operation.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(uint32_t) ASMCpuId_ECX(uint32_t uOperator);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG xCX;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync RTCCUINTREG uSpill;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("cpuid"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uSpill),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=c" (xCX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "rbx", "rdx");
619824b60d668e6e43f385ef78cf06e13d43aab6vboxsync# elif (defined(PIC) || defined(RT_OS_DARWIN)) && defined(__i386__) /* darwin: 4.0.1 compiler option / bug? */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("push %%ebx\n\t"
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync "cpuid\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "pop %%ebx\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uOperator),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=c" (xCX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "edx");
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("cpuid"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uOperator),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=c" (xCX)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "0" (uOperator)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "ebx", "edx");
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync int aInfo[4];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __cpuid(aInfo, uOperator);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync xCX = aInfo[2];
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync push ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, [uOperator]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync cpuid
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [xCX], ecx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop ebx
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync return (uint32_t)xCX;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync/**
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * Checks if the current CPU supports CPUID.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync *
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @returns true if CPUID is supported.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLINLINE(bool) ASMHasCpuId(void)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#ifdef RT_ARCH_AMD64
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync return true; /* ASSUME that all amd64 compatible CPUs have cpuid. */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else /* !RT_ARCH_AMD64 */
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync bool fRet = false;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t u1;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t u2;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("pushf\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "pop %1\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "mov %1, %2\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "xorl $0x200000, %1\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "push %1\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "popf\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "pushf\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "pop %1\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "cmpl %1, %2\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "setne %0\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "push %2\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync "popf\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync : "=m" (fRet), "=r" (u1), "=r" (u2));
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync# else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pushfd
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop eax
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync mov ebx, eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync xor eax, 0200000h
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync push eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync popfd
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync pushfd
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync pop eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync cmp eax, ebx
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync setne fRet
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync push ebx
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync popfd
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync }
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync return fRet;
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync#endif /* !RT_ARCH_AMD64 */
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync}
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync/**
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync * Gets the APIC ID of the current CPU.
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync *
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync * @returns the APIC ID.
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync */
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLASM(uint8_t) ASMGetApicId(void);
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(uint8_t) ASMGetApicId(void)
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync{
3a2aedd9e337c0cc515ce501a066359ba2f9505cvboxsync RTCCUINTREG xBX;
3a2aedd9e337c0cc515ce501a066359ba2f9505cvboxsync# if RT_INLINE_ASM_GNU_STYLE
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# ifdef RT_ARCH_AMD64
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync RTCCUINTREG uSpill;
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm__ ("cpuid"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (uSpill),
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync "=b" (xBX)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "0" (1)
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync : "rcx", "rdx");
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif (defined(PIC) || defined(RT_OS_DARWIN)) && defined(__i386__)
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync RTCCUINTREG uSpill;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm__ ("mov %%ebx,%1\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "cpuid\n\t"
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync "xchgl %%ebx,%1\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "=a" (uSpill),
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync "=r" (xBX)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "0" (1)
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync : "ecx", "edx");
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync RTCCUINTREG uSpill;
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm__ ("cpuid"
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync : "=a" (uSpill),
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync "=b" (xBX)
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync : "0" (1)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "ecx", "edx");
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# elif RT_INLINE_ASM_USES_INTRIN
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync int aInfo[4];
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __cpuid(aInfo, 1);
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync xBX = aInfo[1];
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync push ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, 1
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync cpuid
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [xBX], ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop ebx
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return (uint8_t)(xBX >> 24);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Get cr0.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns cr0.
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMGetCR0(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(RTCCUINTREG) ASMGetCR0(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uCR0;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uCR0 = __readcr0();
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("movq %%cr0, %0\t\n" : "=r" (uCR0));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("movl %%cr0, %0\t\n" : "=r" (uCR0));
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# ifdef RT_ARCH_AMD64
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov rax, cr0
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov [uCR0], rax
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov eax, cr0
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov [uCR0], eax
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync }
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync return uCR0;
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync}
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync#endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Sets the CR0 register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uCR0 The new CR0 value.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMSetCR0(RTCCUINTREG uCR0);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(void) ASMSetCR0(RTCCUINTREG uCR0)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __writecr0(uCR0);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, [uCR0]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr0, rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov eax, [uCR0]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr0, eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Get cr2.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns cr2.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
2b6e5e029d7448f21b9f8b6fb2c87b13c22b4997vboxsyncDECLASM(RTCCUINTREG) ASMGetCR2(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(RTCCUINTREG) ASMGetCR2(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTCCUINTREG uCR2;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uCR2 = __readcr2();
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movq %%cr2, %0\t\n" : "=r" (uCR2));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movl %%cr2, %0\t\n" : "=r" (uCR2));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, cr2
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync mov [uCR2], rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, cr2
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uCR2], eax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return uCR2;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
affcf9ad9ceb4b20938f02dd7cd284b4aaf6b5bbvboxsync * Sets the CR2 register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @param uCR2 The new CR0 value.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(void) ASMSetCR2(RTCCUINTREG uCR2);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(void) ASMSetCR2(RTCCUINTREG uCR2)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
67c73271505adae0686ddbc74eaeef778ef16792vboxsync# if RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov rax, [uCR2]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr2, rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov eax, [uCR2]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr2, eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
affcf9ad9ceb4b20938f02dd7cd284b4aaf6b5bbvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Get cr3.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns cr3.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(RTCCUINTREG) ASMGetCR3(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsyncDECLINLINE(RTCCUINTREG) ASMGetCR3(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTCCUINTREG uCR3;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync uCR3 = __readcr3();
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movq %%cr3, %0\t\n" : "=r" (uCR3));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movl %%cr3, %0\t\n" : "=r" (uCR3));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, cr3
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync mov [uCR3], rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov eax, cr3
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov [uCR3], eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync return uCR3;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Sets the CR3 register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync *
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @param uCR3 New CR3 value.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMSetCR3(RTCCUINTREG uCR3);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(void) ASMSetCR3(RTCCUINTREG uCR3)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __writecr3(uCR3);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__ ("movq %0, %%cr3\n\t" : : "r" (uCR3));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__ ("movl %0, %%cr3\n\t" : : "r" (uCR3));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov rax, [uCR3]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov cr3, rax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, [uCR3]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr3, eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Reloads the CR3 register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMReloadCR3(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(void) ASMReloadCR3(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __writecr3(__readcr3());
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTCCUINTREG u;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("movq %%cr3, %0\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync "movq %0, %%cr3\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "=r" (u));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("movl %%cr3, %0\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync "movl %0, %%cr3\n\t"
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync : "=r" (u));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync {
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, cr3
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr3, rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov eax, cr3
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr3, eax
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * Get cr4.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @returns cr4.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(RTCCUINTREG) ASMGetCR4(void);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLINLINE(RTCCUINTREG) ASMGetCR4(void)
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync RTCCUINTREG uCR4;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync uCR4 = __readcr4();
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movq %%cr4, %0\t\n" : "=r" (uCR4));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movl %%cr4, %0\t\n" : "=r" (uCR4));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
8e2e6c9f8f2157e3ec6599f87343bdc453734c4cvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, cr4
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov [uCR4], rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync push eax /* just in case */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync /*mov eax, cr4*/
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0x0f
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0x20
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0xe0
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov [uCR4], eax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync pop eax
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync return uCR4;
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync}
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync/**
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * Sets the CR4 register.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync *
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync * @param uCR4 New CR4 value.
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsyncDECLASM(void) ASMSetCR4(RTCCUINTREG uCR4);
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync#else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsyncDECLINLINE(void) ASMSetCR4(RTCCUINTREG uCR4)
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync{
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __writecr4(uCR4);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("movq %0, %%cr4\n\t" : : "r" (uCR4));
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ __volatile__ ("movl %0, %%cr4\n\t" : : "r" (uCR4));
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# ifdef RT_ARCH_AMD64
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, [uCR4]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov cr4, rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov eax, [uCR4]
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0x0F
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0x22
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync _emit 0xE0 /* mov cr4, eax */
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Get cr8.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns cr8.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @remark The lock prefix hack for access from non-64-bit modes is NOT used and 0 is returned.
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMGetCR8(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(RTCCUINTREG) ASMGetCR8(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uCR8;
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# if RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uCR8 = __readcr8();
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# elif RT_INLINE_ASM_GNU_STYLE
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm__ ("movq %%cr8, %0\t\n" : "=r" (uCR8));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync __asm
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync {
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync mov rax, cr8
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync mov [uCR8], rax
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync }
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync# endif
ae41886ba231ade1b868dd32ff24ee49813ebbabvboxsync return uCR8;
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else /* !RT_ARCH_AMD64 */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync return 0;
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif /* !RT_ARCH_AMD64 */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Enables interrupts (EFLAGS.IF).
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(void) ASMIntEnable(void);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(void) ASMIntEnable(void)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# if RT_INLINE_ASM_GNU_STYLE
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm("sti\n");
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# elif RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync _enable();
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm sti
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync}
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
b377a71756cce9f39d25b561f72bfa33ce8a39devboxsync * Disables interrupts (!EFLAGS.IF).
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync */
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(void) ASMIntDisable(void);
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(void) ASMIntDisable(void)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync{
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# if RT_INLINE_ASM_GNU_STYLE
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync __asm("cli\n");
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync _disable();
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm cli
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync}
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Disables interrupts and returns previous xFLAGS.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG xFlags;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__("pushfq\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "cli\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "popq %0\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=m" (xFlags));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ __volatile__("pushfl\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "cli\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "popl %0\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=m" (xFlags));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync xFlags = ASMGetFlags();
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync _disable();
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pushfd
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync cli
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync pop [xFlags]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
9edbe160de7266b3b5d54ccf2f07ed95f9f40c6bvboxsync return xFlags;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Reads a machine specific register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns Register content.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uRegister Register to read.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(uint64_t) ASMRdMsr(uint32_t uRegister);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#else
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncDECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync{
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync RTUINT64U u;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("rdmsr\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=a" (u.s.Lo),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "=d" (u.s.Hi)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "c" (uRegister));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync u.u = __readmsr(uRegister);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync {
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync mov ecx, [uRegister]
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync rdmsr
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov [u.s.Lo], eax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [u.s.Hi], edx
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync }
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync return u.u;
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync}
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Writes a machine specific register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns Register content.
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync * @param uRegister Register to write to.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param u64Val Value to write.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTUINT64U u;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync u.u = u64Val;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm__ __volatile__("wrmsr\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync ::"a" (u.s.Lo),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "d" (u.s.Hi),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "c" (uRegister));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __writemsr(uRegister, u.u);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov ecx, [uRegister]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov edx, [u.s.Hi]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov eax, [u.s.Lo]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync wrmsr
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Reads low part of a machine specific register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns Register content.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uRegister Register to read.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(uint32_t) ASMRdMsr_Low(uint32_t uRegister);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t u32;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync __asm__ ("rdmsr\n\t"
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "=a" (u32)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "c" (uRegister)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "edx");
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync u32 = (uint32_t)__readmsr(uRegister);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync {
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync mov ecx, [uRegister]
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync rdmsr
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov [u32], eax
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync }
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync return u32;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync}
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync/**
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * Reads high part of a machine specific register.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @returns Register content.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @param uRegister Register to read.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLASM(uint32_t) ASMRdMsr_High(uint32_t uRegister);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync uint32_t u32;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# if RT_INLINE_ASM_GNU_STYLE
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm__ ("rdmsr\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "=d" (u32)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "c" (uRegister)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync : "eax");
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync u32 = (uint32_t)(__readmsr(uRegister) >> 32);
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# else
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync __asm
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync {
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov ecx, [uRegister]
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync rdmsr
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync mov [u32], edx
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync }
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync# endif
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync return u32;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync}
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Gets dr7.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @returns dr7.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMGetDR7(void);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(RTCCUINTREG) ASMGetDR7(void)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync{
b377a71756cce9f39d25b561f72bfa33ce8a39devboxsync RTCCUINTREG uDR7;
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync# if RT_INLINE_ASM_GNU_STYLE
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync# ifdef RT_ARCH_AMD64
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm__ ("movq %%dr7, %0\n\t" : "=r" (uDR7));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("movl %%dr7, %0\n\t" : "=r" (uDR7));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov rax, dr7
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uDR7], rax
f0ed7ab5e7f8d2f73b5aa08e46eb3a04cbb31cb2vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov eax, dr7
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uDR7], eax
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync return uDR7;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync/**
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Gets dr6.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * @returns dr6.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_EXTERNAL
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(RTCCUINTREG) ASMGetDR6(void);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLINLINE(RTCCUINTREG) ASMGetDR6(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync RTCCUINTREG uDR6;
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("movq %%dr6, %0\n\t" : "=r" (uDR6));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm__ ("movl %%dr6, %0\n\t" : "=r" (uDR6));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
c0b6af690ad705bddfa87c643b89770a7a0aaf5avboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# ifdef RT_ARCH_AMD64
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov rax, dr6
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov [uDR6], rax
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync# else
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync mov eax, dr6
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync mov [uDR6], eax
e9e12792a48d30217ce62abc9051b4fdd55e7fa1vboxsync# endif
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync }
e9e12792a48d30217ce62abc9051b4fdd55e7fa1vboxsync# endif
e9e12792a48d30217ce62abc9051b4fdd55e7fa1vboxsync return uDR6;
e9e12792a48d30217ce62abc9051b4fdd55e7fa1vboxsync}
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync#endif
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync
7202d537edf6d2c5fc2c26bade6855541c675fa0vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Reads and clears DR6.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync *
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @returns DR6.
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#if RT_INLINE_ASM_EXTERNAL
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(RTCCUINTREG) ASMGetAndClearDR6(void);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(RTCCUINTREG) ASMGetAndClearDR6(void)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync RTCCUINTREG uDR6;
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# if RT_INLINE_ASM_GNU_STYLE
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync RTCCUINTREG uNewValue = 0xffff0ff0; /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# ifdef RT_ARCH_AMD64
10f0e3bfdb61e7bae30a1a1d9c17659a908c3d37vboxsync __asm__ ("movq %%dr6, %0\n\t"
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync "movq %1, %%dr6\n\t"
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "=r" (uDR6)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "r" (uNewValue));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm__ ("movl %%dr6, %0\n\t"
0f77dc54d7ec617480988ccdfcd080f480e79698vboxsync "movl %1, %%dr6\n\t"
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "=r" (uDR6)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "r" (uNewValue));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync {
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# ifdef RT_ARCH_AMD64
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov rax, dr6
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov [uDR6], rax
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov rcx, rax
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov dr6, rcx
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov eax, dr6
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov [uDR6], eax
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 is zero. */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov dr6, ecx
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync }
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync# endif
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync return uDR6;
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync}
25c97a3e3ce2710f95faa6d181486df26b518e74vboxsync#endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Compiler memory barrier.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * Ensure that the compiler does not use any cached (register/tmp stack) memory
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * values or any outstanding writes when returning from this function.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync *
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * This function must be used if non-volatile data is modified by a
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * device or the VMM. Typical cases are port access, MMIO access,
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync * trapping instruction, etc.
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync */
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#if RT_INLINE_ASM_GNU_STYLE
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# define ASMCompilerBarrier() do { __asm__ __volatile__ ("" : : : "memory"); } while (0)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#elif RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# define ASMCompilerBarrier() do { _ReadWriteBarrier(); } while (0)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync#else /* 2003 should have _ReadWriteBarrier() but I guess we're at 2002 level then... */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(void) ASMCompilerBarrier(void)
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync{
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync {
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync }
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync}
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync#endif
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
852e87ceabd0234ac0f9e71537c11d08e35f736cvboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Writes a 8-bit unsigned integer to an I/O port.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync *
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @param Port I/O port to read from.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync * @param u8 8-bit integer to write.
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync */
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsyncDECLASM(void) ASMOutU8(RTIOPORT Port, uint8_t u8);
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync#else
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsyncDECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8)
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync{
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync# if RT_INLINE_ASM_GNU_STYLE
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __asm__ __volatile__("outb %b1, %w0\n\t"
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync :: "Nd" (Port),
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync "a" (u8));
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# elif RT_INLINE_ASM_USES_INTRIN
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync __outbyte(Port, u8);
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync# else
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync __asm
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync {
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov dx, [Port]
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync mov al, [u8]
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync out dx, al
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync }
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# endif
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync}
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#endif
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync/**
4b65b0b7127fe2f685bb5c3319f803a16b84ee6cvboxsync * Gets a 8-bit unsigned integer from an I/O port.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync *
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @returns 8-bit integer.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @param Port I/O port to read from.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(uint8_t) ASMInU8(RTIOPORT Port);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLINLINE(uint8_t) ASMInU8(RTIOPORT Port)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync{
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync uint8_t u8;
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# if RT_INLINE_ASM_GNU_STYLE
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm__ __volatile__("inb %w1, %b0\n\t"
951d1da36c2120dd8bf59a3b57800f8429dcd387vboxsync : "=a" (u8)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync : "Nd" (Port));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# elif RT_INLINE_ASM_USES_INTRIN
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync u8 = __inbyte(Port);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# else
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync {
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync mov dx, [Port]
7e3ff7c4e45ee1f8eb46a1aba9d2d8816d337c4avboxsync in al, dx
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync mov [u8], al
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync }
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync# endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync return u8;
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync}
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync#endif
4aafb1203580a5c145a7bdae57ebf69a36fa4f01vboxsync
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
ffbd405f3093b70e19fe9f173cf7d783a304e3e3vboxsync/**
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * Writes a 16-bit unsigned integer to an I/O port.
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync *
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @param Port I/O port to read from.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync * @param u16 16-bit integer to write.
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync */
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsyncDECLASM(void) ASMOutU16(RTIOPORT Port, uint16_t u16);
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync#else
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncDECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16)
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync{
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync# if RT_INLINE_ASM_GNU_STYLE
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __asm__ __volatile__("outw %w1, %w0\n\t"
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync :: "Nd" (Port),
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync "a" (u16));
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync# elif RT_INLINE_ASM_USES_INTRIN
bc0c1e33e433d1276ea1606ace81f61594ee3838vboxsync __outword(Port, u16);
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync# else
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync __asm
0cde281779e97ead3181bbd3b628451fa2b1efe1vboxsync {
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync mov dx, [Port]
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync mov ax, [u16]
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync out dx, ax
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync }
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync# endif
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync}
0dfc79e0666da4c8853deda18a14ebf5819d0d78vboxsync#endif
/**
* Gets a 16-bit unsigned integer from an I/O port.
*
* @returns 16-bit integer.
* @param Port I/O port to read from.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint16_t) ASMInU16(RTIOPORT Port);
#else
DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port)
{
uint16_t u16;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("inw %w1, %w0\n\t"
: "=a" (u16)
: "Nd" (Port));
# elif RT_INLINE_ASM_USES_INTRIN
u16 = __inword(Port);
# else
__asm
{
mov dx, [Port]
in ax, dx
mov [u16], ax
}
# endif
return u16;
}
#endif
/**
* Writes a 32-bit unsigned integer to an I/O port.
*
* @param Port I/O port to read from.
* @param u32 32-bit integer to write.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMOutU32(RTIOPORT Port, uint32_t u32);
#else
DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("outl %1, %w0\n\t"
:: "Nd" (Port),
"a" (u32));
# elif RT_INLINE_ASM_USES_INTRIN
__outdword(Port, u32);
# else
__asm
{
mov dx, [Port]
mov eax, [u32]
out dx, eax
}
# endif
}
#endif
/**
* Gets a 32-bit unsigned integer from an I/O port.
*
* @returns 32-bit integer.
* @param Port I/O port to read from.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint32_t) ASMInU32(RTIOPORT Port);
#else
DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port)
{
uint32_t u32;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("inl %w1, %0\n\t"
: "=a" (u32)
: "Nd" (Port));
# elif RT_INLINE_ASM_USES_INTRIN
u32 = __indword(Port);
# else
__asm
{
mov dx, [Port]
in eax, dx
mov [u32], eax
}
# endif
return u32;
}
#endif
/**
* Atomically Exchange an unsigned 8-bit value.
*
* @returns Current *pu8 value
* @param pu8 Pointer to the 8-bit variable to update.
* @param u8 The 8-bit value to assign to *pu8.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8);
#else
DECLINLINE(uint8_t) ASMAtomicXchgU8(volatile uint8_t *pu8, uint8_t u8)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("xchgb %0, %1\n\t"
: "=m" (*pu8),
"=r" (u8)
: "1" (u8));
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rdx, [pu8]
mov al, [u8]
xchg [rdx], al
mov [u8], al
# else
mov edx, [pu8]
mov al, [u8]
xchg [edx], al
mov [u8], al
# endif
}
# endif
return u8;
}
#endif
/**
* Atomically Exchange a signed 8-bit value.
*
* @returns Current *pu8 value
* @param pi8 Pointer to the 8-bit variable to update.
* @param i8 The 8-bit value to assign to *pi8.
*/
DECLINLINE(int8_t) ASMAtomicXchgS8(volatile int8_t *pi8, int8_t i8)
{
return (int8_t)ASMAtomicXchgU8((volatile uint8_t *)pi8, (uint8_t)i8);
}
/**
* Atomically Exchange a bool value.
*
* @returns Current *pf value
* @param pf Pointer to the 8-bit variable to update.
* @param f The 8-bit value to assign to *pi8.
*/
DECLINLINE(bool) ASMAtomicXchgBool(volatile bool *pf, bool f)
{
#ifdef _MSC_VER
return !!ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f);
#else
return (bool)ASMAtomicXchgU8((volatile uint8_t *)pf, (uint8_t)f);
#endif
}
/**
* Atomically Exchange an unsigned 16-bit value.
*
* @returns Current *pu16 value
* @param pu16 Pointer to the 16-bit variable to update.
* @param u16 The 16-bit value to assign to *pu16.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16);
#else
DECLINLINE(uint16_t) ASMAtomicXchgU16(volatile uint16_t *pu16, uint16_t u16)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("xchgw %0, %1\n\t"
: "=m" (*pu16),
"=r" (u16)
: "1" (u16));
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rdx, [pu16]
mov ax, [u16]
xchg [rdx], ax
mov [u16], ax
# else
mov edx, [pu16]
mov ax, [u16]
xchg [edx], ax
mov [u16], ax
# endif
}
# endif
return u16;
}
#endif
/**
* Atomically Exchange a signed 16-bit value.
*
* @returns Current *pu16 value
* @param pi16 Pointer to the 16-bit variable to update.
* @param i16 The 16-bit value to assign to *pi16.
*/
DECLINLINE(int16_t) ASMAtomicXchgS16(volatile int16_t *pi16, int16_t i16)
{
return (int16_t)ASMAtomicXchgU16((volatile uint16_t *)pi16, (uint16_t)i16);
}
/**
* Atomically Exchange an unsigned 32-bit value.
*
* @returns Current *pu32 value
* @param pu32 Pointer to the 32-bit variable to update.
* @param u32 The 32-bit value to assign to *pu32.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32);
#else
DECLINLINE(uint32_t) ASMAtomicXchgU32(volatile uint32_t *pu32, uint32_t u32)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("xchgl %0, %1\n\t"
: "=m" (*pu32),
"=r" (u32)
: "1" (u32));
# elif RT_INLINE_ASM_USES_INTRIN
u32 = _InterlockedExchange((long *)pu32, u32);
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
mov eax, u32
xchg [rdx], eax
mov [u32], eax
# else
mov edx, [pu32]
mov eax, u32
xchg [edx], eax
mov [u32], eax
# endif
}
# endif
return u32;
}
#endif
/**
* Atomically Exchange a signed 32-bit value.
*
* @returns Current *pu32 value
* @param pi32 Pointer to the 32-bit variable to update.
* @param i32 The 32-bit value to assign to *pi32.
*/
DECLINLINE(int32_t) ASMAtomicXchgS32(volatile int32_t *pi32, int32_t i32)
{
return (int32_t)ASMAtomicXchgU32((volatile uint32_t *)pi32, (uint32_t)i32);
}
/**
* Atomically Exchange an unsigned 64-bit value.
*
* @returns Current *pu64 value
* @param pu64 Pointer to the 64-bit variable to update.
* @param u64 The 64-bit value to assign to *pu64.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64);
#else
DECLINLINE(uint64_t) ASMAtomicXchgU64(volatile uint64_t *pu64, uint64_t u64)
{
# if defined(RT_ARCH_AMD64)
# if RT_INLINE_ASM_USES_INTRIN
u64 = _InterlockedExchange64((__int64 *)pu64, u64);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("xchgq %0, %1\n\t"
: "=m" (*pu64),
"=r" (u64)
: "1" (u64));
# else
__asm
{
mov rdx, [pu64]
mov rax, [u64]
xchg [rdx], rax
mov [u64], rax
}
# endif
# else /* !RT_ARCH_AMD64 */
# if RT_INLINE_ASM_GNU_STYLE
# if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
uint32_t u32 = (uint32_t)u64;
__asm__ __volatile__(/*"xchgl %%esi, %5\n\t"*/
"xchgl %%ebx, %3\n\t"
"1:\n\t"
"lock; cmpxchg8b (%5)\n\t"
"jnz 1b\n\t"
"xchgl %%ebx, %3\n\t"
/*"xchgl %%esi, %5\n\t"*/
: "=A" (u64),
"=m" (*pu64)
: "0" (*pu64),
"m" ( u32 ),
"c" ( (uint32_t)(u64 >> 32) ),
"S" (pu64) );
# else /* !PIC */
__asm__ __volatile__("1:\n\t"
"lock; cmpxchg8b %1\n\t"
"jnz 1b\n\t"
: "=A" (u64),
"=m" (*pu64)
: "0" (*pu64),
"b" ( (uint32_t)u64 ),
"c" ( (uint32_t)(u64 >> 32) ));
# endif
# else
__asm
{
mov ebx, dword ptr [u64]
mov ecx, dword ptr [u64 + 4]
mov edi, pu64
mov eax, dword ptr [edi]
mov edx, dword ptr [edi + 4]
retry:
lock cmpxchg8b [edi]
jnz retry
mov dword ptr [u64], eax
mov dword ptr [u64 + 4], edx
}
# endif
# endif /* !RT_ARCH_AMD64 */
return u64;
}
#endif
/**
* Atomically Exchange an signed 64-bit value.
*
* @returns Current *pi64 value
* @param pi64 Pointer to the 64-bit variable to update.
* @param i64 The 64-bit value to assign to *pi64.
*/
DECLINLINE(int64_t) ASMAtomicXchgS64(volatile int64_t *pi64, int64_t i64)
{
return (int64_t)ASMAtomicXchgU64((volatile uint64_t *)pi64, (uint64_t)i64);
}
#ifdef RT_ARCH_AMD64
/**
* Atomically Exchange an unsigned 128-bit value.
*
* @returns Current *pu128.
* @param pu128 Pointer to the 128-bit variable to update.
* @param u128 The 128-bit value to assign to *pu128.
*
* @remark We cannot really assume that any hardware supports this. Nor do I have
* GAS support for it. So, for the time being we'll BREAK the atomic
* bit of this function and use two 64-bit exchanges instead.
*/
# if 0 /* see remark RT_INLINE_ASM_EXTERNAL */
DECLASM(uint128_t) ASMAtomicXchgU128(volatile uint128_t *pu128, uint128_t u128);
# else
DECLINLINE(uint128_t) ASMAtomicXchgU128(volatile uint128_t *pu128, uint128_t u128)
{
if (true)/*ASMCpuId_ECX(1) & BIT(13))*/
{
/** @todo this is clumsy code */
RTUINT128U u128Ret;
u128Ret.u = u128;
u128Ret.s.Lo = ASMAtomicXchgU64(&((PRTUINT128U)(uintptr_t)pu128)->s.Lo, u128Ret.s.Lo);
u128Ret.s.Hi = ASMAtomicXchgU64(&((PRTUINT128U)(uintptr_t)pu128)->s.Hi, u128Ret.s.Hi);
return u128Ret.u;
}
#if 0 /* later? */
else
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("1:\n\t"
"lock; cmpxchg8b %1\n\t"
"jnz 1b\n\t"
: "=A" (u128),
"=m" (*pu128)
: "0" (*pu128),
"b" ( (uint64_t)u128 ),
"c" ( (uint64_t)(u128 >> 64) ));
# else
__asm
{
mov rbx, dword ptr [u128]
mov rcx, dword ptr [u128 + 4]
mov rdi, pu128
mov rax, dword ptr [rdi]
mov rdx, dword ptr [rdi + 4]
retry:
lock cmpxchg16b [rdi]
jnz retry
mov dword ptr [u128], rax
mov dword ptr [u128 + 4], rdx
}
# endif
}
return u128;
#endif
}
# endif
#endif /* RT_ARCH_AMD64 */
/**
* Atomically Reads a unsigned 64-bit value.
*
* @returns Current *pu64 value
* @param pu64 Pointer to the 64-bit variable to read.
* The memory pointed to must be writable.
* @remark This will fault if the memory is read-only!
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64);
#else
DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t *pu64)
{
uint64_t u64;
# ifdef RT_ARCH_AMD64
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("movq %1, %0\n\t"
: "=r" (u64)
: "m" (*pu64));
# else
__asm
{
mov rdx, [pu64]
mov rax, [rdx]
mov [u64], rax
}
# endif
# else /* !RT_ARCH_AMD64 */
# if RT_INLINE_ASM_GNU_STYLE
# if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
uint32_t u32EBX = 0;
__asm__ __volatile__("xchgl %%ebx, %3\n\t"
"lock; cmpxchg8b (%5)\n\t"
"xchgl %%ebx, %3\n\t"
: "=A" (u64),
"=m" (*pu64)
: "0" (0),
"m" (u32EBX),
"c" (0),
"S" (pu64));
# else /* !PIC */
__asm__ __volatile__("lock; cmpxchg8b %1\n\t"
: "=A" (u64),
"=m" (*pu64)
: "0" (0),
"b" (0),
"c" (0));
# endif
# else
__asm
{
xor eax, eax
xor edx, edx
mov edi, pu64
xor ecx, ecx
xor ebx, ebx
lock cmpxchg8b [edi]
mov dword ptr [u64], eax
mov dword ptr [u64 + 4], edx
}
# endif
# endif /* !RT_ARCH_AMD64 */
return u64;
}
#endif
/**
* Atomically Reads a signed 64-bit value.
*
* @returns Current *pi64 value
* @param pi64 Pointer to the 64-bit variable to read.
* The memory pointed to must be writable.
* @remark This will fault if the memory is read-only!
*/
DECLINLINE(int64_t) ASMAtomicReadS64(volatile int64_t *pi64)
{
return (int64_t)ASMAtomicReadU64((volatile uint64_t *)pi64);
}
/**
* Atomically Exchange a value which size might differ
* between platforms or compilers.
*
* @param pu Pointer to the variable to update.
* @param uNew The value to assign to *pu.
*/
#define ASMAtomicXchgSize(pu, uNew) \
do { \
switch (sizeof(*(pu))) { \
case 1: ASMAtomicXchgU8((volatile uint8_t *)(void *)(pu), (uint8_t)(uNew)); break; \
case 2: ASMAtomicXchgU16((volatile uint16_t *)(void *)(pu), (uint16_t)(uNew)); break; \
case 4: ASMAtomicXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew)); break; \
case 8: ASMAtomicXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew)); break; \
default: AssertMsgFailed(("ASMAtomicXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
} \
} while (0)
/**
* Atomically Exchange a pointer value.
*
* @returns Current *ppv value
* @param ppv Pointer to the pointer variable to update.
* @param pv The pointer value to assign to *ppv.
*/
DECLINLINE(void *) ASMAtomicXchgPtr(void * volatile *ppv, void *pv)
{
#if ARCH_BITS == 32
return (void *)ASMAtomicXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pv);
#elif ARCH_BITS == 64
return (void *)ASMAtomicXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pv);
#else
# error "ARCH_BITS is bogus"
#endif
}
/**
* Atomically Compare and Exchange an unsigned 32-bit value.
*
* @returns true if xchg was done.
* @returns false if xchg wasn't done.
*
* @param pu32 Pointer to the value to update.
* @param u32New The new value to assigned to *pu32.
* @param u32Old The old value to *pu32 compare with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old);
#else
DECLINLINE(bool) ASMAtomicCmpXchgU32(volatile uint32_t *pu32, const uint32_t u32New, const uint32_t u32Old)
{
# if RT_INLINE_ASM_GNU_STYLE
uint32_t u32Ret;
__asm__ __volatile__("lock; cmpxchgl %2, %0\n\t"
"setz %%al\n\t"
"movzbl %%al, %%eax\n\t"
: "=m" (*pu32),
"=a" (u32Ret)
: "r" (u32New),
"1" (u32Old));
return (bool)u32Ret;
# elif RT_INLINE_ASM_USES_INTRIN
return _InterlockedCompareExchange((long *)pu32, u32New, u32Old) == u32Old;
# else
uint32_t u32Ret;
__asm
{
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
# else
mov edx, [pu32]
# endif
mov eax, [u32Old]
mov ecx, [u32New]
# ifdef RT_ARCH_AMD64
lock cmpxchg [rdx], ecx
# else
lock cmpxchg [edx], ecx
# endif
setz al
movzx eax, al
mov [u32Ret], eax
}
return !!u32Ret;
# endif
}
#endif
/**
* Atomically Compare and Exchange a signed 32-bit value.
*
* @returns true if xchg was done.
* @returns false if xchg wasn't done.
*
* @param pi32 Pointer to the value to update.
* @param i32New The new value to assigned to *pi32.
* @param i32Old The old value to *pi32 compare with.
*/
DECLINLINE(bool) ASMAtomicCmpXchgS32(volatile int32_t *pi32, const int32_t i32New, const int32_t i32Old)
{
return ASMAtomicCmpXchgU32((volatile uint32_t *)pi32, (uint32_t)i32New, (uint32_t)i32Old);
}
/**
* Atomically Compare and exchange an unsigned 64-bit value.
*
* @returns true if xchg was done.
* @returns false if xchg wasn't done.
*
* @param pu64 Pointer to the 64-bit variable to update.
* @param u64New The 64-bit value to assign to *pu64.
* @param u64Old The value to compare with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old);
#else
DECLINLINE(bool) ASMAtomicCmpXchgU64(volatile uint64_t *pu64, const uint64_t u64New, const uint64_t u64Old)
{
# if RT_INLINE_ASM_USES_INTRIN
return _InterlockedCompareExchange64((__int64 *)pu64, u64New, u64Old) == u64Old;
# elif defined(RT_ARCH_AMD64)
# if RT_INLINE_ASM_GNU_STYLE
uint64_t u64Ret;
__asm__ __volatile__("lock; cmpxchgq %2, %0\n\t"
"setz %%al\n\t"
"movzbl %%al, %%eax\n\t"
: "=m" (*pu64),
"=a" (u64Ret)
: "r" (u64New),
"1" (u64Old));
return (bool)u64Ret;
# else
bool fRet;
__asm
{
mov rdx, [pu32]
mov rax, [u64Old]
mov rcx, [u64New]
lock cmpxchg [rdx], rcx
setz al
mov [fRet], al
}
return fRet;
# endif
# else /* !RT_ARCH_AMD64 */
uint32_t u32Ret;
# if RT_INLINE_ASM_GNU_STYLE
# if defined(PIC) || defined(RT_OS_DARWIN) /* darwin: 4.0.1 compiler option / bug? */
uint32_t u32 = (uint32_t)u64New;
uint32_t u32Spill;
__asm__ __volatile__("xchgl %%ebx, %4\n\t"
"lock; cmpxchg8b (%6)\n\t"
"setz %%al\n\t"
"xchgl %%ebx, %4\n\t"
"movzbl %%al, %%eax\n\t"
: "=a" (u32Ret),
"=d" (u32Spill),
"=m" (*pu64)
: "A" (u64Old),
"m" ( u32 ),
"c" ( (uint32_t)(u64New >> 32) ),
"S" (pu64) );
# else /* !PIC */
uint32_t u32Spill;
__asm__ __volatile__("lock; cmpxchg8b %2\n\t"
"setz %%al\n\t"
"movzbl %%al, %%eax\n\t"
: "=a" (u32Ret),
"=d" (u32Spill),
"=m" (*pu64)
: "A" (u64Old),
"b" ( (uint32_t)u64New ),
"c" ( (uint32_t)(u64New >> 32) ));
# endif
return (bool)u32Ret;
# else
__asm
{
mov ebx, dword ptr [u64New]
mov ecx, dword ptr [u64New + 4]
mov edi, [pu64]
mov eax, dword ptr [u64Old]
mov edx, dword ptr [u64Old + 4]
lock cmpxchg8b [edi]
setz al
movzx eax, al
mov dword ptr [u32Ret], eax
}
return !!u32Ret;
# endif
# endif /* !RT_ARCH_AMD64 */
}
#endif
/**
* Atomically Compare and exchange a signed 64-bit value.
*
* @returns true if xchg was done.
* @returns false if xchg wasn't done.
*
* @param pi64 Pointer to the 64-bit variable to update.
* @param i64 The 64-bit value to assign to *pu64.
* @param i64Old The value to compare with.
*/
DECLINLINE(bool) ASMAtomicCmpXchgS64(volatile int64_t *pi64, const int64_t i64, const int64_t i64Old)
{
return ASMAtomicCmpXchgU64((volatile uint64_t *)pi64, (uint64_t)i64, (uint64_t)i64Old);
}
/** @def ASMAtomicCmpXchgSize
* Atomically Compare and Exchange a value which size might differ
* between platforms or compilers.
*
* @param pu Pointer to the value to update.
* @param uNew The new value to assigned to *pu.
* @param uOld The old value to *pu compare with.
* @param fRc Where to store the result.
*/
#define ASMAtomicCmpXchgSize(pu, uNew, uOld, fRc) \
do { \
switch (sizeof(*(pu))) { \
case 4: (fRc) = ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)(pu), (uint32_t)(uNew), (uint32_t)(uOld)); \
break; \
case 8: (fRc) = ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)(pu), (uint64_t)(uNew), (uint64_t)(uOld)); \
break; \
default: AssertMsgFailed(("ASMAtomicCmpXchgSize: size %d is not supported\n", sizeof(*(pu)))); \
(fRc) = false; \
break; \
} \
} while (0)
/**
* Atomically Compare and Exchange a pointer value.
*
* @returns true if xchg was done.
* @returns false if xchg wasn't done.
*
* @param ppv Pointer to the value to update.
* @param pvNew The new value to assigned to *ppv.
* @param pvOld The old value to *ppv compare with.
*/
DECLINLINE(bool) ASMAtomicCmpXchgPtr(void * volatile *ppv, void *pvNew, void *pvOld)
{
#if ARCH_BITS == 32
return ASMAtomicCmpXchgU32((volatile uint32_t *)(void *)ppv, (uint32_t)pvNew, (uint32_t)pvOld);
#elif ARCH_BITS == 64
return ASMAtomicCmpXchgU64((volatile uint64_t *)(void *)ppv, (uint64_t)pvNew, (uint64_t)pvOld);
#else
# error "ARCH_BITS is bogus"
#endif
}
/**
* Atomically increment a 32-bit value.
*
* @returns The new value.
* @param pu32 Pointer to the value to increment.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32);
#else
DECLINLINE(uint32_t) ASMAtomicIncU32(uint32_t volatile *pu32)
{
uint32_t u32;
# if RT_INLINE_ASM_USES_INTRIN
u32 = _InterlockedIncrement((long *)pu32);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("lock; xaddl %0, %1\n\t"
"incl %0\n\t"
: "=r" (u32),
"=m" (*pu32)
: "0" (1)
: "memory");
# else
__asm
{
mov eax, 1
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
lock xadd [rdx], eax
# else
mov edx, [pu32]
lock xadd [edx], eax
# endif
inc eax
mov u32, eax
}
# endif
return u32;
}
#endif
/**
* Atomically increment a signed 32-bit value.
*
* @returns The new value.
* @param pi32 Pointer to the value to increment.
*/
DECLINLINE(int32_t) ASMAtomicIncS32(int32_t volatile *pi32)
{
return (int32_t)ASMAtomicIncU32((uint32_t volatile *)pi32);
}
/**
* Atomically decrement an unsigned 32-bit value.
*
* @returns The new value.
* @param pu32 Pointer to the value to decrement.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32);
#else
DECLINLINE(uint32_t) ASMAtomicDecU32(uint32_t volatile *pu32)
{
uint32_t u32;
# if RT_INLINE_ASM_USES_INTRIN
u32 = _InterlockedDecrement((long *)pu32);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("lock; xaddl %0, %1\n\t"
"decl %0\n\t"
: "=r" (u32),
"=m" (*pu32)
: "0" (-1)
: "memory");
# else
__asm
{
mov eax, -1
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
lock xadd [rdx], eax
# else
mov edx, [pu32]
lock xadd [edx], eax
# endif
dec eax
mov u32, eax
}
# endif
return u32;
}
#endif
/**
* Atomically decrement a signed 32-bit value.
*
* @returns The new value.
* @param pi32 Pointer to the value to decrement.
*/
DECLINLINE(int32_t) ASMAtomicDecS32(int32_t volatile *pi32)
{
return (int32_t)ASMAtomicDecU32((uint32_t volatile *)pi32);
}
/**
* Atomically Or an unsigned 32-bit value.
*
* @param pu32 Pointer to the pointer variable to OR u32 with.
* @param u32 The value to OR *pu32 with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32);
#else
DECLINLINE(void) ASMAtomicOrU32(uint32_t volatile *pu32, uint32_t u32)
{
# if RT_INLINE_ASM_USES_INTRIN
_InterlockedOr((long volatile *)pu32, (long)u32);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("lock; orl %1, %0\n\t"
: "=m" (*pu32)
: "r" (u32));
# else
__asm
{
mov eax, [u32]
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
lock or [rdx], eax
# else
mov edx, [pu32]
lock or [edx], eax
# endif
}
# endif
}
#endif
/**
* Atomically Or a signed 32-bit value.
*
* @param pi32 Pointer to the pointer variable to OR u32 with.
* @param i32 The value to OR *pu32 with.
*/
DECLINLINE(void) ASMAtomicOrS32(int32_t volatile *pi32, int32_t i32)
{
ASMAtomicOrU32((uint32_t volatile *)pi32, i32);
}
/**
* Atomically And an unsigned 32-bit value.
*
* @param pu32 Pointer to the pointer variable to AND u32 with.
* @param u32 The value to AND *pu32 with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32);
#else
DECLINLINE(void) ASMAtomicAndU32(uint32_t volatile *pu32, uint32_t u32)
{
# if RT_INLINE_ASM_USES_INTRIN
_InterlockedAnd((long volatile *)pu32, u32);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("lock; andl %1, %0\n\t"
: "=m" (*pu32)
: "r" (u32));
# else
__asm
{
mov eax, [u32]
# ifdef RT_ARCH_AMD64
mov rdx, [pu32]
lock and [rdx], eax
# else
mov edx, [pu32]
lock and [edx], eax
# endif
}
# endif
}
#endif
/**
* Atomically And a signed 32-bit value.
*
* @param pi32 Pointer to the pointer variable to AND i32 with.
* @param i32 The value to AND *pi32 with.
*/
DECLINLINE(void) ASMAtomicAndS32(int32_t volatile *pi32, int32_t i32)
{
ASMAtomicAndU32((uint32_t volatile *)pi32, (uint32_t)i32);
}
/**
* Invalidate page.
*
* @param pv Address of the page to invalidate.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMInvalidatePage(void *pv);
#else
DECLINLINE(void) ASMInvalidatePage(void *pv)
{
# if RT_INLINE_ASM_USES_INTRIN
__invlpg(pv);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("invlpg %0\n\t"
: : "m" (*(uint8_t *)pv));
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pv]
invlpg [rax]
# else
mov eax, [pv]
invlpg [eax]
# endif
}
# endif
}
#endif
#if defined(PAGE_SIZE) && !defined(NT_INCLUDED)
# if PAGE_SIZE != 0x1000
# error "PAGE_SIZE is not 0x1000!"
# endif
#endif
/**
* Zeros a 4K memory page.
*
* @param pv Pointer to the memory block. This must be page aligned.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMMemZeroPage(volatile void *pv);
# else
DECLINLINE(void) ASMMemZeroPage(volatile void *pv)
{
# if RT_INLINE_ASM_USES_INTRIN
# ifdef RT_ARCH_AMD64
__stosq((unsigned __int64 *)pv, 0, /*PAGE_SIZE*/0x1000 / 8);
# else
__stosd((unsigned long *)pv, 0, /*PAGE_SIZE*/0x1000 / 4);
# endif
# elif RT_INLINE_ASM_GNU_STYLE
RTUINTREG uDummy;
# ifdef RT_ARCH_AMD64
__asm__ __volatile__ ("rep stosq"
: "=D" (pv),
"=c" (uDummy)
: "0" (pv),
"c" (0x1000 >> 3),
"a" (0)
: "memory");
# else
__asm__ __volatile__ ("rep stosl"
: "=D" (pv),
"=c" (uDummy)
: "0" (pv),
"c" (0x1000 >> 2),
"a" (0)
: "memory");
# endif
# else
__asm
{
# ifdef RT_ARCH_AMD64
xor rax, rax
mov ecx, 0200h
mov rdi, [pv]
rep stosq
# else
xor eax, eax
mov ecx, 0400h
mov edi, [pv]
rep stosd
# endif
}
# endif
}
# endif
/**
* Zeros a memory block with a 32-bit aligned size.
*
* @param pv Pointer to the memory block.
* @param cb Number of bytes in the block. This MUST be aligned on 32-bit!
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMMemZero32(volatile void *pv, size_t cb);
#else
DECLINLINE(void) ASMMemZero32(volatile void *pv, size_t cb)
{
# if RT_INLINE_ASM_USES_INTRIN
__stosd((unsigned long *)pv, 0, cb >> 2);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("rep stosl"
: "=D" (pv),
"=c" (cb)
: "0" (pv),
"1" (cb >> 2),
"a" (0)
: "memory");
# else
__asm
{
xor eax, eax
# ifdef RT_ARCH_AMD64
mov rcx, [cb]
shr rcx, 2
mov rdi, [pv]
# else
mov ecx, [cb]
shr ecx, 2
mov edi, [pv]
# endif
rep stosd
}
# endif
}
#endif
/**
* Fills a memory block with a 32-bit aligned size.
*
* @param pv Pointer to the memory block.
* @param cb Number of bytes in the block. This MUST be aligned on 32-bit!
* @param u32 The value to fill with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32);
#else
DECLINLINE(void) ASMMemFill32(volatile void *pv, size_t cb, uint32_t u32)
{
# if RT_INLINE_ASM_USES_INTRIN
__stosd((unsigned long *)pv, 0, cb >> 2);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("rep stosl"
: "=D" (pv),
"=c" (cb)
: "0" (pv),
"1" (cb >> 2),
"a" (u32)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rcx, [cb]
shr rcx, 2
mov rdi, [pv]
# else
mov ecx, [cb]
shr ecx, 2
mov edi, [pv]
# endif
mov eax, [u32]
rep stosd
}
# endif
}
#endif
/**
* Checks if a memory block is filled with the specified byte.
*
* This is a sort of inverted memchr.
*
* @returns Pointer to the byte which doesn't equal u8.
* @returns NULL if all equal to u8.
*
* @param pv Pointer to the memory block.
* @param cb Number of bytes in the block. This MUST be aligned on 32-bit!
* @param u8 The value it's supposed to be filled with.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void *) ASMMemIsAll8(void const *pv, size_t cb, uint8_t u8);
#else
DECLINLINE(void *) ASMMemIsAll8(void const *pv, size_t cb, uint8_t u8)
{
/** @todo rewrite this in inline assembly. */
uint8_t const *pb = (uint8_t const *)pv;
for (; cb; cb--, pb++)
if (RT_UNLIKELY(*pb != u8))
return (void *)pb;
return NULL;
}
#endif
/**
* Multiplies two unsigned 32-bit values returning an unsigned 64-bit result.
*
* @returns u32F1 * u32F2.
*/
#if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
DECLASM(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2);
#else
DECLINLINE(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2)
{
# ifdef RT_ARCH_AMD64
return (uint64_t)u32F1 * u32F2;
# else /* !RT_ARCH_AMD64 */
uint64_t u64;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("mull %%edx"
: "=A" (u64)
: "a" (u32F2), "d" (u32F1));
# else
__asm
{
mov edx, [u32F1]
mov eax, [u32F2]
mul edx
mov dword ptr [u64], eax
mov dword ptr [u64 + 4], edx
}
# endif
return u64;
# endif /* !RT_ARCH_AMD64 */
}
#endif
/**
* Multiplies two signed 32-bit values returning a signed 64-bit result.
*
* @returns u32F1 * u32F2.
*/
#if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
DECLASM(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2);
#else
DECLINLINE(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2)
{
# ifdef RT_ARCH_AMD64
return (int64_t)i32F1 * i32F2;
# else /* !RT_ARCH_AMD64 */
int64_t i64;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("imull %%edx"
: "=A" (i64)
: "a" (i32F2), "d" (i32F1));
# else
__asm
{
mov edx, [i32F1]
mov eax, [i32F2]
imul edx
mov dword ptr [i64], eax
mov dword ptr [i64 + 4], edx
}
# endif
return i64;
# endif /* !RT_ARCH_AMD64 */
}
#endif
/**
* Devides a 64-bit unsigned by a 32-bit unsigned returning an unsigned 32-bit result.
*
* @returns u64 / u32.
*/
#if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
DECLASM(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32);
#else
DECLINLINE(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32)
{
# ifdef RT_ARCH_AMD64
return (uint32_t)(u64 / u32);
# else /* !RT_ARCH_AMD64 */
# if RT_INLINE_ASM_GNU_STYLE
RTUINTREG uDummy;
__asm__ __volatile__("divl %3"
: "=a" (u32), "=d"(uDummy)
: "A" (u64), "r" (u32));
# else
__asm
{
mov eax, dword ptr [u64]
mov edx, dword ptr [u64 + 4]
mov ecx, [u32]
div ecx
mov [u32], eax
}
# endif
return u32;
# endif /* !RT_ARCH_AMD64 */
}
#endif
/**
* Devides a 64-bit signed by a 32-bit signed returning a signed 32-bit result.
*
* @returns u64 / u32.
*/
#if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
DECLASM(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32);
#else
DECLINLINE(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32)
{
# ifdef RT_ARCH_AMD64
return (int32_t)(i64 / i32);
# else /* !RT_ARCH_AMD64 */
# if RT_INLINE_ASM_GNU_STYLE
RTUINTREG iDummy;
__asm__ __volatile__("idivl %3"
: "=a" (i32), "=d"(iDummy)
: "A" (i64), "r" (i32));
# else
__asm
{
mov eax, dword ptr [i64]
mov edx, dword ptr [i64 + 4]
mov ecx, [i32]
idiv ecx
mov [i32], eax
}
# endif
return i32;
# endif /* !RT_ARCH_AMD64 */
}
#endif
/**
* Multiple a 64-bit by a 32-bit integer and divide the result by a 32-bit integer
* using a 96 bit intermediate result.
* @note Don't use 64-bit C arithmetic here since some gcc compilers generate references to
* __udivdi3 and __umoddi3 even if this inline function is not used.
*
* @returns (u64A * u32B) / u32C.
* @param u64A The 64-bit value.
* @param u32B The 32-bit value to multiple by A.
* @param u32C The 32-bit value to divide A*B by.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C);
#else
DECLINLINE(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C)
{
# if RT_INLINE_ASM_GNU_STYLE
# ifdef RT_ARCH_AMD64
uint64_t u64Result, u64Spill;
__asm__ __volatile__("mulq %2\n\t"
"divq %3\n\t"
: "=a" (u64Result),
"=d" (u64Spill)
: "r" ((uint64_t)u32B),
"r" ((uint64_t)u32C),
"0" (u64A),
"1" (0));
return u64Result;
# else
uint32_t u32Dummy;
uint64_t u64Result;
__asm__ __volatile__("mull %%ecx \n\t" /* eax = u64Lo.lo = (u64A.lo * u32B).lo
edx = u64Lo.hi = (u64A.lo * u32B).hi */
"xchg %%eax,%%esi \n\t" /* esi = u64Lo.lo
eax = u64A.hi */
"xchg %%edx,%%edi \n\t" /* edi = u64Low.hi
edx = u32C */
"xchg %%edx,%%ecx \n\t" /* ecx = u32C
edx = u32B */
"mull %%edx \n\t" /* eax = u64Hi.lo = (u64A.hi * u32B).lo
edx = u64Hi.hi = (u64A.hi * u32B).hi */
"addl %%edi,%%eax \n\t" /* u64Hi.lo += u64Lo.hi */
"adcl $0,%%edx \n\t" /* u64Hi.hi += carry */
"divl %%ecx \n\t" /* eax = u64Hi / u32C
edx = u64Hi % u32C */
"movl %%eax,%%edi \n\t" /* edi = u64Result.hi = u64Hi / u32C */
"movl %%esi,%%eax \n\t" /* eax = u64Lo.lo */
"divl %%ecx \n\t" /* u64Result.lo */
"movl %%edi,%%edx \n\t" /* u64Result.hi */
: "=A"(u64Result), "=c"(u32Dummy),
"=S"(u32Dummy), "=D"(u32Dummy)
: "a"((uint32_t)u64A),
"S"((uint32_t)(u64A >> 32)),
"c"(u32B),
"D"(u32C));
return u64Result;
# endif
# else
RTUINT64U u;
uint64_t u64Lo = (uint64_t)(u64A & 0xffffffff) * u32B;
uint64_t u64Hi = (uint64_t)(u64A >> 32) * u32B;
u64Hi += (u64Lo >> 32);
u.s.Hi = (uint32_t)(u64Hi / u32C);
u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo & 0xffffffff)) / u32C);
return u.u;
# endif
}
#endif
/**
* Probes a byte pointer for read access.
*
* While the function will not fault if the byte is not read accessible,
* the idea is to do this in a safe place like before acquiring locks
* and such like.
*
* Also, this functions guarantees that an eager compiler is not going
* to optimize the probing away.
*
* @param pvByte Pointer to the byte.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(uint8_t) ASMProbeReadByte(const void *pvByte);
#else
DECLINLINE(uint8_t) ASMProbeReadByte(const void *pvByte)
{
/** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */
uint8_t u8;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("movb (%1), %0\n\t"
: "=r" (u8)
: "r" (pvByte));
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvByte]
mov al, [rax]
# else
mov eax, [pvByte]
mov al, [eax]
# endif
mov [u8], al
}
# endif
return u8;
}
#endif
/**
* Probes a buffer for read access page by page.
*
* While the function will fault if the buffer is not fully read
* accessible, the idea is to do this in a safe place like before
* acquiring locks and such like.
*
* Also, this functions guarantees that an eager compiler is not going
* to optimize the probing away.
*
* @param pvBuf Pointer to the buffer.
* @param cbBuf The size of the buffer in bytes. Must be >= 1.
*/
DECLINLINE(void) ASMProbeReadBuffer(const void *pvBuf, size_t cbBuf)
{
/** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */
/* the first byte */
const uint8_t *pu8 = (const uint8_t *)pvBuf;
ASMProbeReadByte(pu8);
/* the pages in between pages. */
while (cbBuf > /*PAGE_SIZE*/0x1000)
{
ASMProbeReadByte(pu8);
cbBuf -= /*PAGE_SIZE*/0x1000;
pu8 += /*PAGE_SIZE*/0x1000;
}
/* the last byte */
ASMProbeReadByte(pu8 + cbBuf - 1);
}
/** @def ASMBreakpoint
* Debugger Breakpoint.
* @remark In the gnu world we add a nop instruction after the int3 to
* force gdb to remain at the int3 source line.
* @remark The L4 kernel will try make sense of the breakpoint, thus the jmp.
* @internal
*/
#if RT_INLINE_ASM_GNU_STYLE
# ifndef __L4ENV__
# define ASMBreakpoint() do { __asm__ __volatile__ ("int3\n\tnop"); } while (0)
# else
# define ASMBreakpoint() do { __asm__ __volatile__ ("int3; jmp 1f; 1:"); } while (0)
# endif
#else
# define ASMBreakpoint() __debugbreak()
#endif
/** @defgroup grp_inline_bits Bit Operations
* @{
*/
/**
* Sets a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to set.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMBitSet(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_USES_INTRIN
_bittestandset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btsl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
bts [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
bts [eax], edx
# endif
}
# endif
}
#endif
/**
* Atomically sets a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to set.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMAtomicBitSet(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_USES_INTRIN
_interlockedbittestandset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btsl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
lock bts [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
lock bts [eax], edx
# endif
}
# endif
}
#endif
/**
* Clears a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to clear.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMBitClear(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_USES_INTRIN
_bittestandreset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btrl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
btr [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
btr [eax], edx
# endif
}
# endif
}
#endif
/**
* Atomically clears a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to toggle set.
* @remark No memory barrier, take care on smp.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMAtomicBitClear(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btrl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
lock btr [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
lock btr [eax], edx
# endif
}
# endif
}
#endif
/**
* Toggles a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to toggle.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMBitToggle(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_USES_INTRIN
_bittestandcomplement((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btcl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
btc [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
btc [eax], edx
# endif
}
# endif
}
#endif
/**
* Atomically toggles a bit in a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and set.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(void) ASMAtomicBitToggle(volatile void *pvBitmap, int32_t iBit)
{
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btcl %1, %0"
: "=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
mov edx, [iBit]
lock btc [rax], edx
# else
mov eax, [pvBitmap]
mov edx, [iBit]
lock btc [eax], edx
# endif
}
# endif
}
#endif
/**
* Tests and sets a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and set.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMBitTestAndSet(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u8 = _bittestandset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btsl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
bts [rax], edx
# else
mov eax, [pvBitmap]
bts [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Atomically tests and sets a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to set.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMAtomicBitTestAndSet(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u8 = _interlockedbittestandset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btsl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
lock bts [rax], edx
# else
mov eax, [pvBitmap]
lock bts [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Tests and clears a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and clear.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMBitTestAndClear(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u8 = _bittestandreset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btrl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
btr [rax], edx
# else
mov eax, [pvBitmap]
btr [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Atomically tests and clears a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and clear.
* @remark No memory barrier, take care on smp.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMAtomicBitTestAndClear(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u8 = _interlockedbittestandreset((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btrl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
lock btr [rax], edx
# else
mov eax, [pvBitmap]
lock btr [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Tests and toggles a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and toggle.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLINLINE(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMBitTestAndToggle(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u8 = _bittestandcomplement((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btcl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
btc [rax], edx
# else
mov eax, [pvBitmap]
btc [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Atomically tests and toggles a bit in a bitmap.
*
* @returns true if the bit was set.
* @returns false if the bit was clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test and toggle.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMAtomicBitTestAndToggle(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("lock; btcl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
lock btc [rax], edx
# else
mov eax, [pvBitmap]
lock btc [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Tests if a bit in a bitmap is set.
*
* @returns true if the bit is set.
* @returns false if the bit is clear.
* @param pvBitmap Pointer to the bitmap.
* @param iBit The bit to test.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(bool) ASMBitTest(volatile void *pvBitmap, int32_t iBit);
#else
DECLINLINE(bool) ASMBitTest(volatile void *pvBitmap, int32_t iBit)
{
union { bool f; uint32_t u32; uint8_t u8; } rc;
# if RT_INLINE_ASM_USES_INTRIN
rc.u32 = _bittest((long *)pvBitmap, iBit);
# elif RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__ ("btl %2, %1\n\t"
"setc %b0\n\t"
"andl $1, %0\n\t"
: "=q" (rc.u32),
"=m" (*(volatile long *)pvBitmap)
: "Ir" (iBit)
: "memory");
# else
__asm
{
mov edx, [iBit]
# ifdef RT_ARCH_AMD64
mov rax, [pvBitmap]
bt [rax], edx
# else
mov eax, [pvBitmap]
bt [eax], edx
# endif
setc al
and eax, 1
mov [rc.u32], eax
}
# endif
return rc.f;
}
#endif
/**
* Clears a bit range within a bitmap.
*
* @param pvBitmap Pointer to the bitmap.
* @param iBitStart The First bit to clear.
* @param iBitEnd The first bit not to clear.
*/
DECLINLINE(void) ASMBitClearRange(volatile void *pvBitmap, int32_t iBitStart, int32_t iBitEnd)
{
if (iBitStart < iBitEnd)
{
volatile uint32_t *pu32 = (volatile uint32_t *)pvBitmap + (iBitStart >> 5);
int iStart = iBitStart & ~31;
int iEnd = iBitEnd & ~31;
if (iStart == iEnd)
*pu32 &= ((1 << (iBitStart & 31)) - 1) | ~((1 << (iBitEnd & 31)) - 1);
else
{
/* bits in first dword. */
if (iBitStart & 31)
{
*pu32 &= (1 << (iBitStart & 31)) - 1;
pu32++;
iBitStart = iStart + 32;
}
/* whole dword. */
if (iBitStart != iEnd)
ASMMemZero32(pu32, (iEnd - iBitStart) >> 3);
/* bits in last dword. */
if (iBitEnd & 31)
{
pu32 = (volatile uint32_t *)pvBitmap + (iBitEnd >> 5);
*pu32 &= ~((1 << (iBitEnd & 31)) - 1);
}
}
}
}
/**
* Finds the first clear bit in a bitmap.
*
* @returns Index of the first zero bit.
* @returns -1 if no clear bit was found.
* @param pvBitmap Pointer to the bitmap.
* @param cBits The number of bits in the bitmap. Multiple of 32.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(int) ASMBitFirstClear(volatile void *pvBitmap, uint32_t cBits);
#else
DECLINLINE(int) ASMBitFirstClear(volatile void *pvBitmap, uint32_t cBits)
{
if (cBits)
{
int32_t iBit;
# if RT_INLINE_ASM_GNU_STYLE
RTCCUINTREG uEAX, uECX, uEDI;
cBits = RT_ALIGN_32(cBits, 32);
__asm__ __volatile__("repe; scasl\n\t"
"je 1f\n\t"
# ifdef RT_ARCH_AMD64
"lea -4(%%rdi), %%rdi\n\t"
"xorl (%%rdi), %%eax\n\t"
"subq %5, %%rdi\n\t"
# else
"lea -4(%%edi), %%edi\n\t"
"xorl (%%edi), %%eax\n\t"
"subl %5, %%edi\n\t"
# endif
"shll $3, %%edi\n\t"
"bsfl %%eax, %%edx\n\t"
"addl %%edi, %%edx\n\t"
"1:\t\n"
: "=d" (iBit),
"=&c" (uECX),
"=&D" (uEDI),
"=&a" (uEAX)
: "0" (0xffffffff),
"mr" (pvBitmap),
"1" (cBits >> 5),
"2" (pvBitmap),
"3" (0xffffffff));
# else
cBits = RT_ALIGN_32(cBits, 32);
__asm
{
# ifdef RT_ARCH_AMD64
mov rdi, [pvBitmap]
mov rbx, rdi
# else
mov edi, [pvBitmap]
mov ebx, edi
# endif
mov edx, 0ffffffffh
mov eax, edx
mov ecx, [cBits]
shr ecx, 5
repe scasd
je done
# ifdef RT_ARCH_AMD64
lea rdi, [rdi - 4]
xor eax, [rdi]
sub rdi, rbx
# else
lea edi, [edi - 4]
xor eax, [edi]
sub edi, ebx
# endif
shl edi, 3
bsf edx, eax
add edx, edi
done:
mov [iBit], edx
}
# endif
return iBit;
}
return -1;
}
#endif
/**
* Finds the next clear bit in a bitmap.
*
* @returns Index of the first zero bit.
* @returns -1 if no clear bit was found.
* @param pvBitmap Pointer to the bitmap.
* @param cBits The number of bits in the bitmap. Multiple of 32.
* @param iBitPrev The bit returned from the last search.
* The search will start at iBitPrev + 1.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(int) ASMBitNextClear(volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev);
#else
DECLINLINE(int) ASMBitNextClear(volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
{
int iBit = ++iBitPrev & 31;
pvBitmap = (volatile char *)pvBitmap + ((iBitPrev >> 5) << 2);
cBits -= iBitPrev & ~31;
if (iBit)
{
/* inspect the first dword. */
uint32_t u32 = (~*(volatile uint32_t *)pvBitmap) >> iBit;
# if RT_INLINE_ASM_USES_INTRIN
unsigned long ulBit = 0;
if (_BitScanForward(&ulBit, u32))
return ulBit + iBitPrev;
iBit = -1;
# else
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("bsf %1, %0\n\t"
"jnz 1f\n\t"
"movl $-1, %0\n\t"
"1:\n\t"
: "=r" (iBit)
: "r" (u32));
# else
__asm
{
mov edx, [u32]
bsf eax, edx
jnz done
mov eax, 0ffffffffh
done:
mov [iBit], eax
}
# endif
if (iBit >= 0)
return iBit + iBitPrev;
# endif
/* Search the rest of the bitmap, if there is anything. */
if (cBits > 32)
{
iBit = ASMBitFirstClear((volatile char *)pvBitmap + sizeof(uint32_t), cBits - 32);
if (iBit >= 0)
return iBit + (iBitPrev & ~31) + 32;
}
}
else
{
/* Search the rest of the bitmap. */
iBit = ASMBitFirstClear(pvBitmap, cBits);
if (iBit >= 0)
return iBit + (iBitPrev & ~31);
}
return iBit;
}
#endif
/**
* Finds the first set bit in a bitmap.
*
* @returns Index of the first set bit.
* @returns -1 if no clear bit was found.
* @param pvBitmap Pointer to the bitmap.
* @param cBits The number of bits in the bitmap. Multiple of 32.
*/
#if RT_INLINE_ASM_EXTERNAL
DECLASM(int) ASMBitFirstSet(volatile void *pvBitmap, uint32_t cBits);
#else
DECLINLINE(int) ASMBitFirstSet(volatile void *pvBitmap, uint32_t cBits)
{
if (cBits)
{
int32_t iBit;
# if RT_INLINE_ASM_GNU_STYLE
RTCCUINTREG uEAX, uECX, uEDI;
cBits = RT_ALIGN_32(cBits, 32);
__asm__ __volatile__("repe; scasl\n\t"
"je 1f\n\t"
# ifdef RT_ARCH_AMD64
"lea -4(%%rdi), %%rdi\n\t"
"movl (%%rdi), %%eax\n\t"
"subq %5, %%rdi\n\t"
# else
"lea -4(%%edi), %%edi\n\t"
"movl (%%edi), %%eax\n\t"
"subl %5, %%edi\n\t"
# endif
"shll $3, %%edi\n\t"
"bsfl %%eax, %%edx\n\t"
"addl %%edi, %%edx\n\t"
"1:\t\n"
: "=d" (iBit),
"=&c" (uECX),
"=&D" (uEDI),
"=&a" (uEAX)
: "0" (0xffffffff),
"mr" (pvBitmap),
"1" (cBits >> 5),
"2" (pvBitmap),
"3" (0));
# else
cBits = RT_ALIGN_32(cBits, 32);
__asm
{
# ifdef RT_ARCH_AMD64
mov rdi, [pvBitmap]
mov rbx, rdi
# else
mov edi, [pvBitmap]
mov ebx, edi
# endif
mov edx, 0ffffffffh
xor eax, eax
mov ecx, [cBits]
shr ecx, 5
repe scasd
je done
# ifdef RT_ARCH_AMD64
lea rdi, [rdi - 4]
mov eax, [rdi]
sub rdi, rbx
# else
lea edi, [edi - 4]
mov eax, [edi]
sub edi, ebx
# endif
shl edi, 3
bsf edx, eax
add edx, edi
done:
mov [iBit], edx
}
# endif
return iBit;
}
return -1;
}
#endif
/**
* Finds the next set bit in a bitmap.
*
* @returns Index of the next set bit.
* @returns -1 if no set bit was found.
* @param pvBitmap Pointer to the bitmap.
* @param cBits The number of bits in the bitmap. Multiple of 32.
* @param iBitPrev The bit returned from the last search.
* The search will start at iBitPrev + 1.
*/
#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
DECLASM(int) ASMBitNextSet(volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev);
#else
DECLINLINE(int) ASMBitNextSet(volatile void *pvBitmap, uint32_t cBits, uint32_t iBitPrev)
{
int iBit = ++iBitPrev & 31;
pvBitmap = (volatile char *)pvBitmap + ((iBitPrev >> 5) << 2);
cBits -= iBitPrev & ~31;
if (iBit)
{
/* inspect the first dword. */
uint32_t u32 = *(volatile uint32_t *)pvBitmap >> iBit;
# if RT_INLINE_ASM_USES_INTRIN
unsigned long ulBit = 0;
if (_BitScanForward(&ulBit, u32))
return ulBit + iBitPrev;
iBit = -1;
# else
# if RT_INLINE_ASM_GNU_STYLE
__asm__ __volatile__("bsf %1, %0\n\t"
"jnz 1f\n\t"
"movl $-1, %0\n\t"
"1:\n\t"
: "=r" (iBit)
: "r" (u32));
# else
__asm
{
mov edx, u32
bsf eax, edx
jnz done
mov eax, 0ffffffffh
done:
mov [iBit], eax
}
# endif
if (iBit >= 0)
return iBit + iBitPrev;
# endif
/* Search the rest of the bitmap, if there is anything. */
if (cBits > 32)
{
iBit = ASMBitFirstSet((volatile char *)pvBitmap + sizeof(uint32_t), cBits - 32);
if (iBit >= 0)
return iBit + (iBitPrev & ~31) + 32;
}
}
else
{
/* Search the rest of the bitmap. */
iBit = ASMBitFirstSet(pvBitmap, cBits);
if (iBit >= 0)
return iBit + (iBitPrev & ~31);
}
return iBit;
}
#endif
/**
* Finds the first bit which is set in the given 32-bit integer.
* Bits are numbered from 1 (least significant) to 32.
*
* @returns index [1..32] of the first set bit.
* @returns 0 if all bits are cleared.
* @param u32 Integer to search for set bits.
* @remark Similar to ffs() in BSD.
*/
DECLINLINE(unsigned) ASMBitFirstSetU32(uint32_t u32)
{
# if RT_INLINE_ASM_USES_INTRIN
unsigned long iBit;
if (_BitScanForward(&iBit, u32))
iBit++;
else
iBit = 0;
# elif RT_INLINE_ASM_GNU_STYLE
uint32_t iBit;
__asm__ __volatile__("bsf %1, %0\n\t"
"jnz 1f\n\t"
"xorl %0, %0\n\t"
"jmp 2f\n"
"1:\n\t"
"incl %0\n"
"2:\n\t"
: "=r" (iBit)
: "rm" (u32));
# else
uint32_t iBit;
_asm
{
bsf eax, [u32]
jnz found
xor eax, eax
jmp done
found:
inc eax
done:
mov [iBit], eax
}
# endif
return iBit;
}
/**
* Finds the first bit which is set in the given 32-bit integer.
* Bits are numbered from 1 (least significant) to 32.
*
* @returns index [1..32] of the first set bit.
* @returns 0 if all bits are cleared.
* @param i32 Integer to search for set bits.
* @remark Similar to ffs() in BSD.
*/
DECLINLINE(unsigned) ASMBitFirstSetS32(int32_t i32)
{
return ASMBitFirstSetU32((uint32_t)i32);
}
/**
* Finds the last bit which is set in the given 32-bit integer.
* Bits are numbered from 1 (least significant) to 32.
*
* @returns index [1..32] of the last set bit.
* @returns 0 if all bits are cleared.
* @param u32 Integer to search for set bits.
* @remark Similar to fls() in BSD.
*/
DECLINLINE(unsigned) ASMBitLastSetU32(uint32_t u32)
{
# if RT_INLINE_ASM_USES_INTRIN
unsigned long iBit;
if (_BitScanReverse(&iBit, u32))
iBit++;
else
iBit = 0;
# elif RT_INLINE_ASM_GNU_STYLE
uint32_t iBit;
__asm__ __volatile__("bsrl %1, %0\n\t"
"jnz 1f\n\t"
"xorl %0, %0\n\t"
"jmp 2f\n"
"1:\n\t"
"incl %0\n"
"2:\n\t"
: "=r" (iBit)
: "rm" (u32));
# else
uint32_t iBit;
_asm
{
bsr eax, [u32]
jnz found
xor eax, eax
jmp done
found:
inc eax
done:
mov [iBit], eax
}
# endif
return iBit;
}
/**
* Finds the last bit which is set in the given 32-bit integer.
* Bits are numbered from 1 (least significant) to 32.
*
* @returns index [1..32] of the last set bit.
* @returns 0 if all bits are cleared.
* @param i32 Integer to search for set bits.
* @remark Similar to fls() in BSD.
*/
DECLINLINE(unsigned) ASMBitLastSetS32(int32_t i32)
{
return ASMBitLastSetS32((uint32_t)i32);
}
/**
* Reverse the byte order of the given 32-bit integer.
* @param u32 Integer
*/
DECLINLINE(uint32_t) ASMByteSwapU32(uint32_t u32)
{
#if RT_INLINE_ASM_USES_INTRIN
u32 = _byteswap_ulong(u32);
#elif RT_INLINE_ASM_GNU_STYLE
__asm__ ("bswapl %0" : "=r" (u32) : "0" (u32));
#else
_asm
{
mov eax, [u32]
bswap eax
mov [u32], eax
}
#endif
return u32;
}
/** @} */
/** @} */
#endif