asm-amd64-x86.h revision 9c5875d62215e6a088a86658e5553af6b8401f1c
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * IPRT - AMD64 and x86 Specific Assembly Functions.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Copyright (C) 2006-2013 Oracle Corporation
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * available from http://www.virtualbox.org. This file is free software;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * General Public License (GPL) as published by the Free Software
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The contents of this file may alternatively be used under the terms
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * of the Common Development and Distribution License Version 1.0
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution, in which case the provisions of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * CDDL are applicable instead of those of the GPL.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * You may elect to license modified versions of this file under the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * terms and conditions of either the GPL or the CDDL or both.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* Emit the intrinsics at all optimization levels. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @defgroup grp_rt_asm_amd64_x86 AMD64 and x86 Specific ASM Routines
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @ingroup grp_rt_asm
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @todo find a more proper place for this structure? */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct RTIDTR
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Size of the IDT. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Address of the IDT. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsynctypedef struct RTGDTR
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Size of the GDT. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** Address of the GDT. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Gets the content of the IDTR CPU register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pIdtr Where to store the IDTR contents.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Sets the content of the IDTR CPU register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pIdtr Where to load the IDTR contents from
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Gets the content of the GDTR CPU register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pGdtr Where to store the GDTR contents.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the cs register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns cs.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%cs, %0\n\t" : "=r" (SelCS));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the DS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns DS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%ds, %0\n\t" : "=r" (SelDS));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the ES register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns ES.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%es, %0\n\t" : "=r" (SelES));
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync * Get the FS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns FS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%fs, %0\n\t" : "=r" (SelFS));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the GS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns GS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%gs, %0\n\t" : "=r" (SelGS));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the SS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns SS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("movw %%ss, %0\n\t" : "=r" (SelSS));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the TR register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns TR.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the LDTR register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns LDTR.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("sldt %w0\n\t" : "=r" (SelLDTR));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the access rights for the segment selector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns The access rights on success or ~0U on failure.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uSel The selector value.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @remarks Using ~0U for failure is chosen because valid access rights always
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * have bits 0:7 as 0 (on both Intel & AMD).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* LAR only accesses 16-bit of the source operand, but eax for the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync destination operand is required for getting the full 32-bit access rights. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "jz done%=\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "movl $0xffffffff, %%eax\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "done%=:\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "movl %%eax, %0\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Get the [RE]FLAGS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns [RE]FLAGS.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "popq %0\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "popl %0\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Set the [RE]FLAGS register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uFlags The new [RE]FLAGS value.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < 15
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "popfq\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "popfl\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Gets the content of the CPU timestamp counter register.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns TSC.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return u.u;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning all registers.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEAX Where to store eax.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEBX Where to store ebx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvECX Where to store ecx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEDX Where to store edx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @remark We're using void pointers to ease the use of special bitfield structures and such.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "xchgl %%ebx, %1\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the CPUID instruction with EAX and ECX input returning ALL output
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * registers.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uIdxECX ecx index
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEAX Where to store eax.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEBX Where to store ebx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvECX Where to store ecx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEDX Where to store edx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @remark We're using void pointers to ease the use of special bitfield structures and such.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL || RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "xchgl %%ebx, %1\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * CPUID variant that initializes all 4 registers before the CPUID instruction.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns The EAX result value.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uInitEBX The value to assign EBX prior to the CPUID instruction.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uInitECX The value to assign ECX prior to the CPUID instruction.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uInitEDX The value to assign EDX prior to the CPUID instruction.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEAX Where to store eax. Optional.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEBX Where to store ebx. Optional.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvECX Where to store ecx. Optional.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEDX Where to store edx. Optional.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLASM(uint32_t) ASMCpuIdExSlow(uint32_t uOperator, uint32_t uInitEBX, uint32_t uInitECX, uint32_t uInitEDX,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning ecx and edx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvECX Where to store ecx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvEDX Where to store edx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @remark We're using void pointers to ease the use of special bitfield structures and such.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning eax.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns EAX after cpuid operation.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(uint32_t) ASMCpuId_EAX(uint32_t uOperator)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "pop %%ebx\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning ebx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns EBX after cpuid operation.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(uint32_t) ASMCpuId_EBX(uint32_t uOperator)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "mov %%ebx, %%edx\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "pop %%ebx\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning ecx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns ECX after cpuid operation.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "pop %%ebx\n\t"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Performs the cpuid instruction returning edx.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param uOperator CPUID operation (eax).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns EDX after cpuid operation.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncDECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "cpuid\n\t"
#ifdef RT_ARCH_AMD64
bool fRet = false;
return fRet;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uCR0;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uCR2;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uCR3;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
RTCCUINTREG u;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uCR4;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uCR8;
_enable();
_disable();
# ifdef RT_ARCH_AMD64
_disable();
__asm {
return xFlags;
__asm {
RTUINT64U u;
RTUINT64U u;
u.u = u64Val;
RTUINT64U u;
RTUINT64U u;
u.u = u64Val;
return u32;
return u32;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR0;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR1;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR2;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR3;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR6;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR6;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return uDR7;
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
# ifdef RT_ARCH_AMD64
return u8;
return u16;
return u32;
# ifdef RT_ARCH_AMD64
__wbinvd();
_mm_mfence();
_mm_sfence();
_mm_lfence();