VirtualBox

Changeset 29250 in vbox for trunk/include/iprt/asm-math.h


Ignore:
Timestamp:
May 9, 2010 5:53:58 PM (15 years ago)
Author:
vboxsync
Message:

iprt/asm*.h: split out asm-math.h, don't include asm-*.h from asm.h, don't include asm.h from sup.h. Fixed a couple file headers.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/asm-math.h

    r29245 r29250  
    11/** @file
    2  * IPRT - AMD64 and x86 Specific Assembly Functions.
     2 * IPRT - Assembly Routines for Optimizing some Integers Math Operations.
    33 */
    44
     
    2424 */
    2525
    26 #ifndef ___iprt_asm_amd64_x86_h
    27 #define ___iprt_asm_amd64_x86_h
    28 
    29 /* We depend on several defines and pragmas that live in iprt/asm.h. */
    30 #include <iprt/asm.h>
    31 
    32 #ifdef _MSC_VER
    33 # if _MSC_VER >= 1400 && RT_INLINE_ASM_USES_INTRIN
    34    /* Emit the intrinsics at all optimization levels. */
    35 #  pragma intrinsic(_ReadWriteBarrier)
    36 #  pragma intrinsic(__cpuid)
    37 #  pragma intrinsic(_enable)
    38 #  pragma intrinsic(_disable)
    39 #  pragma intrinsic(__rdtsc)
    40 #  pragma intrinsic(__readmsr)
    41 #  pragma intrinsic(__writemsr)
    42 #  pragma intrinsic(__outbyte)
    43 #  pragma intrinsic(__outbytestring)
    44 #  pragma intrinsic(__outword)
    45 #  pragma intrinsic(__outwordstring)
    46 #  pragma intrinsic(__outdword)
    47 #  pragma intrinsic(__outdwordstring)
    48 #  pragma intrinsic(__inbyte)
    49 #  pragma intrinsic(__inbytestring)
    50 #  pragma intrinsic(__inword)
    51 #  pragma intrinsic(__inwordstring)
    52 #  pragma intrinsic(__indword)
    53 #  pragma intrinsic(__indwordstring)
    54 #  pragma intrinsic(__invlpg)
    55 #  pragma intrinsic(__wbinvd)
    56 #  pragma intrinsic(__readcr0)
    57 #  pragma intrinsic(__readcr2)
    58 #  pragma intrinsic(__readcr3)
    59 #  pragma intrinsic(__readcr4)
    60 #  pragma intrinsic(__writecr0)
    61 #  pragma intrinsic(__writecr3)
    62 #  pragma intrinsic(__writecr4)
    63 #  pragma intrinsic(__readdr)
    64 #  pragma intrinsic(__writedr)
    65 #  ifdef RT_ARCH_AMD64
    66 #   pragma intrinsic(__readcr8)
    67 #   pragma intrinsic(__writecr8)
    68 #  endif
    69 # endif
    70 #endif
    71 
    72 
    73 
    74 /** @defgroup grp_rt_asm_amd64_x86  AMD64 and x86 Specific ASM Routines
     26#ifndef ___iprt_asm_math_h
     27#define ___iprt_asm_math_h
     28
     29#include <iprt/types.h>
     30
     31
     32/** @defgroup grp_rt_asm_math   Interger Math Optimizations
    7533 * @ingroup grp_rt_asm
    76  * @{
    77  */
    78 
    79 /** @todo find a more proper place for this structure? */
    80 #pragma pack(1)
    81 /** IDTR */
    82 typedef struct RTIDTR
    83 {
    84     /** Size of the IDT. */
    85     uint16_t    cbIdt;
    86     /** Address of the IDT. */
    87     uintptr_t   pIdt;
    88 } RTIDTR, *PRTIDTR;
    89 #pragma pack()
    90 
    91 #pragma pack(1)
    92 /** GDTR */
    93 typedef struct RTGDTR
    94 {
    95     /** Size of the GDT. */
    96     uint16_t    cbGdt;
    97     /** Address of the GDT. */
    98     uintptr_t   pGdt;
    99 } RTGDTR, *PRTGDTR;
    100 #pragma pack()
    101 
    102 
    103 /**
    104  * Gets the content of the IDTR CPU register.
    105  * @param   pIdtr   Where to store the IDTR contents.
    106  */
    107 #if RT_INLINE_ASM_EXTERNAL
    108 DECLASM(void) ASMGetIDTR(PRTIDTR pIdtr);
    109 #else
    110 DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)
    111 {
    112 # if RT_INLINE_ASM_GNU_STYLE
    113     __asm__ __volatile__("sidt %0" : "=m" (*pIdtr));
    114 # else
    115     __asm
    116     {
    117 #  ifdef RT_ARCH_AMD64
    118         mov     rax, [pIdtr]
    119         sidt    [rax]
    120 #  else
    121         mov     eax, [pIdtr]
    122         sidt    [eax]
    123 #  endif
    124     }
    125 # endif
    126 }
    127 #endif
    128 
    129 
    130 /**
    131  * Sets the content of the IDTR CPU register.
    132  * @param   pIdtr   Where to load the IDTR contents from
    133  */
    134 #if RT_INLINE_ASM_EXTERNAL
    135 DECLASM(void) ASMSetIDTR(const RTIDTR *pIdtr);
    136 #else
    137 DECLINLINE(void) ASMSetIDTR(const RTIDTR *pIdtr)
    138 {
    139 # if RT_INLINE_ASM_GNU_STYLE
    140     __asm__ __volatile__("lidt %0" : : "m" (*pIdtr));
    141 # else
    142     __asm
    143     {
    144 #  ifdef RT_ARCH_AMD64
    145         mov     rax, [pIdtr]
    146         lidt    [rax]
    147 #  else
    148         mov     eax, [pIdtr]
    149         lidt    [eax]
    150 #  endif
    151     }
    152 # endif
    153 }
    154 #endif
    155 
    156 
    157 /**
    158  * Gets the content of the GDTR CPU register.
    159  * @param   pGdtr   Where to store the GDTR contents.
    160  */
    161 #if RT_INLINE_ASM_EXTERNAL
    162 DECLASM(void) ASMGetGDTR(PRTGDTR pGdtr);
    163 #else
    164 DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)
    165 {
    166 # if RT_INLINE_ASM_GNU_STYLE
    167     __asm__ __volatile__("sgdt %0" : "=m" (*pGdtr));
    168 # else
    169     __asm
    170     {
    171 #  ifdef RT_ARCH_AMD64
    172         mov     rax, [pGdtr]
    173         sgdt    [rax]
    174 #  else
    175         mov     eax, [pGdtr]
    176         sgdt    [eax]
    177 #  endif
    178     }
    179 # endif
    180 }
    181 #endif
    182 
    183 /**
    184  * Get the cs register.
    185  * @returns cs.
    186  */
    187 #if RT_INLINE_ASM_EXTERNAL
    188 DECLASM(RTSEL) ASMGetCS(void);
    189 #else
    190 DECLINLINE(RTSEL) ASMGetCS(void)
    191 {
    192     RTSEL SelCS;
    193 # if RT_INLINE_ASM_GNU_STYLE
    194     __asm__ __volatile__("movw  %%cs, %0\n\t" : "=r" (SelCS));
    195 # else
    196     __asm
    197     {
    198         mov     ax, cs
    199         mov     [SelCS], ax
    200     }
    201 # endif
    202     return SelCS;
    203 }
    204 #endif
    205 
    206 
    207 /**
    208  * Get the DS register.
    209  * @returns DS.
    210  */
    211 #if RT_INLINE_ASM_EXTERNAL
    212 DECLASM(RTSEL) ASMGetDS(void);
    213 #else
    214 DECLINLINE(RTSEL) ASMGetDS(void)
    215 {
    216     RTSEL SelDS;
    217 # if RT_INLINE_ASM_GNU_STYLE
    218     __asm__ __volatile__("movw  %%ds, %0\n\t" : "=r" (SelDS));
    219 # else
    220     __asm
    221     {
    222         mov     ax, ds
    223         mov     [SelDS], ax
    224     }
    225 # endif
    226     return SelDS;
    227 }
    228 #endif
    229 
    230 
    231 /**
    232  * Get the ES register.
    233  * @returns ES.
    234  */
    235 #if RT_INLINE_ASM_EXTERNAL
    236 DECLASM(RTSEL) ASMGetES(void);
    237 #else
    238 DECLINLINE(RTSEL) ASMGetES(void)
    239 {
    240     RTSEL SelES;
    241 # if RT_INLINE_ASM_GNU_STYLE
    242     __asm__ __volatile__("movw  %%es, %0\n\t" : "=r" (SelES));
    243 # else
    244     __asm
    245     {
    246         mov     ax, es
    247         mov     [SelES], ax
    248     }
    249 # endif
    250     return SelES;
    251 }
    252 #endif
    253 
    254 
    255 /**
    256  * Get the FS register.
    257  * @returns FS.
    258  */
    259 #if RT_INLINE_ASM_EXTERNAL
    260 DECLASM(RTSEL) ASMGetFS(void);
    261 #else
    262 DECLINLINE(RTSEL) ASMGetFS(void)
    263 {
    264     RTSEL SelFS;
    265 # if RT_INLINE_ASM_GNU_STYLE
    266     __asm__ __volatile__("movw  %%fs, %0\n\t" : "=r" (SelFS));
    267 # else
    268     __asm
    269     {
    270         mov     ax, fs
    271         mov     [SelFS], ax
    272     }
    273 # endif
    274     return SelFS;
    275 }
    276 # endif
    277 
    278 
    279 /**
    280  * Get the GS register.
    281  * @returns GS.
    282  */
    283 #if RT_INLINE_ASM_EXTERNAL
    284 DECLASM(RTSEL) ASMGetGS(void);
    285 #else
    286 DECLINLINE(RTSEL) ASMGetGS(void)
    287 {
    288     RTSEL SelGS;
    289 # if RT_INLINE_ASM_GNU_STYLE
    290     __asm__ __volatile__("movw  %%gs, %0\n\t" : "=r" (SelGS));
    291 # else
    292     __asm
    293     {
    294         mov     ax, gs
    295         mov     [SelGS], ax
    296     }
    297 # endif
    298     return SelGS;
    299 }
    300 #endif
    301 
    302 
    303 /**
    304  * Get the SS register.
    305  * @returns SS.
    306  */
    307 #if RT_INLINE_ASM_EXTERNAL
    308 DECLASM(RTSEL) ASMGetSS(void);
    309 #else
    310 DECLINLINE(RTSEL) ASMGetSS(void)
    311 {
    312     RTSEL SelSS;
    313 # if RT_INLINE_ASM_GNU_STYLE
    314     __asm__ __volatile__("movw  %%ss, %0\n\t" : "=r" (SelSS));
    315 # else
    316     __asm
    317     {
    318         mov     ax, ss
    319         mov     [SelSS], ax
    320     }
    321 # endif
    322     return SelSS;
    323 }
    324 #endif
    325 
    326 
    327 /**
    328  * Get the TR register.
    329  * @returns TR.
    330  */
    331 #if RT_INLINE_ASM_EXTERNAL
    332 DECLASM(RTSEL) ASMGetTR(void);
    333 #else
    334 DECLINLINE(RTSEL) ASMGetTR(void)
    335 {
    336     RTSEL SelTR;
    337 # if RT_INLINE_ASM_GNU_STYLE
    338     __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));
    339 # else
    340     __asm
    341     {
    342         str     ax
    343         mov     [SelTR], ax
    344     }
    345 # endif
    346     return SelTR;
    347 }
    348 #endif
    349 
    350 
    351 /**
    352  * Get the [RE]FLAGS register.
    353  * @returns [RE]FLAGS.
    354  */
    355 #if RT_INLINE_ASM_EXTERNAL
    356 DECLASM(RTCCUINTREG) ASMGetFlags(void);
    357 #else
    358 DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
    359 {
    360     RTCCUINTREG uFlags;
    361 # if RT_INLINE_ASM_GNU_STYLE
    362 #  ifdef RT_ARCH_AMD64
    363     __asm__ __volatile__("pushfq\n\t"
    364                          "popq  %0\n\t"
    365                          : "=r" (uFlags));
    366 #  else
    367     __asm__ __volatile__("pushfl\n\t"
    368                          "popl  %0\n\t"
    369                          : "=r" (uFlags));
    370 #  endif
    371 # else
    372     __asm
    373     {
    374 #  ifdef RT_ARCH_AMD64
    375         pushfq
    376         pop  [uFlags]
    377 #  else
    378         pushfd
    379         pop  [uFlags]
    380 #  endif
    381     }
    382 # endif
    383     return uFlags;
    384 }
    385 #endif
    386 
    387 
    388 /**
    389  * Set the [RE]FLAGS register.
    390  * @param   uFlags      The new [RE]FLAGS value.
    391  */
    392 #if RT_INLINE_ASM_EXTERNAL
    393 DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
    394 #else
    395 DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
    396 {
    397 # if RT_INLINE_ASM_GNU_STYLE
    398 #  ifdef RT_ARCH_AMD64
    399     __asm__ __volatile__("pushq %0\n\t"
    400                          "popfq\n\t"
    401                          : : "g" (uFlags));
    402 #  else
    403     __asm__ __volatile__("pushl %0\n\t"
    404                          "popfl\n\t"
    405                          : : "g" (uFlags));
    406 #  endif
    407 # else
    408     __asm
    409     {
    410 #  ifdef RT_ARCH_AMD64
    411         push    [uFlags]
    412         popfq
    413 #  else
    414         push    [uFlags]
    415         popfd
    416 #  endif
    417     }
    418 # endif
    419 }
    420 #endif
    421 
    422 
    423 /**
    424  * Gets the content of the CPU timestamp counter register.
    425  *
    426  * @returns TSC.
    427  */
    428 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    429 DECLASM(uint64_t) ASMReadTSC(void);
    430 #else
    431 DECLINLINE(uint64_t) ASMReadTSC(void)
    432 {
    433     RTUINT64U u;
    434 # if RT_INLINE_ASM_GNU_STYLE
    435     __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));
    436 # else
    437 #  if RT_INLINE_ASM_USES_INTRIN
    438     u.u = __rdtsc();
    439 #  else
    440     __asm
    441     {
    442         rdtsc
    443         mov     [u.s.Lo], eax
    444         mov     [u.s.Hi], edx
    445     }
    446 #  endif
    447 # endif
    448     return u.u;
    449 }
    450 #endif
    451 
    452 
    453 /**
    454  * Performs the cpuid instruction returning all registers.
    455  *
    456  * @param   uOperator   CPUID operation (eax).
    457  * @param   pvEAX       Where to store eax.
    458  * @param   pvEBX       Where to store ebx.
    459  * @param   pvECX       Where to store ecx.
    460  * @param   pvEDX       Where to store edx.
    461  * @remark  We're using void pointers to ease the use of special bitfield structures and such.
    462  */
    463 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    464 DECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
    465 #else
    466 DECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
    467 {
    468 # if RT_INLINE_ASM_GNU_STYLE
    469 #  ifdef RT_ARCH_AMD64
    470     RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
    471     __asm__ ("cpuid\n\t"
    472              : "=a" (uRAX),
    473                "=b" (uRBX),
    474                "=c" (uRCX),
    475                "=d" (uRDX)
    476              : "0" (uOperator));
    477     *(uint32_t *)pvEAX = (uint32_t)uRAX;
    478     *(uint32_t *)pvEBX = (uint32_t)uRBX;
    479     *(uint32_t *)pvECX = (uint32_t)uRCX;
    480     *(uint32_t *)pvEDX = (uint32_t)uRDX;
    481 #  else
    482     __asm__ ("xchgl %%ebx, %1\n\t"
    483              "cpuid\n\t"
    484              "xchgl %%ebx, %1\n\t"
    485              : "=a" (*(uint32_t *)pvEAX),
    486                "=r" (*(uint32_t *)pvEBX),
    487                "=c" (*(uint32_t *)pvECX),
    488                "=d" (*(uint32_t *)pvEDX)
    489              : "0" (uOperator));
    490 #  endif
    491 
    492 # elif RT_INLINE_ASM_USES_INTRIN
    493     int aInfo[4];
    494     __cpuid(aInfo, uOperator);
    495     *(uint32_t *)pvEAX = aInfo[0];
    496     *(uint32_t *)pvEBX = aInfo[1];
    497     *(uint32_t *)pvECX = aInfo[2];
    498     *(uint32_t *)pvEDX = aInfo[3];
    499 
    500 # else
    501     uint32_t    uEAX;
    502     uint32_t    uEBX;
    503     uint32_t    uECX;
    504     uint32_t    uEDX;
    505     __asm
    506     {
    507         push    ebx
    508         mov     eax, [uOperator]
    509         cpuid
    510         mov     [uEAX], eax
    511         mov     [uEBX], ebx
    512         mov     [uECX], ecx
    513         mov     [uEDX], edx
    514         pop     ebx
    515     }
    516     *(uint32_t *)pvEAX = uEAX;
    517     *(uint32_t *)pvEBX = uEBX;
    518     *(uint32_t *)pvECX = uECX;
    519     *(uint32_t *)pvEDX = uEDX;
    520 # endif
    521 }
    522 #endif
    523 
    524 
    525 /**
    526  * Performs the cpuid instruction returning all registers.
    527  * Some subfunctions of cpuid take ECX as additional parameter (currently known for EAX=4)
    528  *
    529  * @param   uOperator   CPUID operation (eax).
    530  * @param   uIdxECX     ecx index
    531  * @param   pvEAX       Where to store eax.
    532  * @param   pvEBX       Where to store ebx.
    533  * @param   pvECX       Where to store ecx.
    534  * @param   pvEDX       Where to store edx.
    535  * @remark  We're using void pointers to ease the use of special bitfield structures and such.
    536  */
    537 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    538 DECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);
    539 #else
    540 DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)
    541 {
    542 # if RT_INLINE_ASM_GNU_STYLE
    543 #  ifdef RT_ARCH_AMD64
    544     RTCCUINTREG uRAX, uRBX, uRCX, uRDX;
    545     __asm__ ("cpuid\n\t"
    546              : "=a" (uRAX),
    547                "=b" (uRBX),
    548                "=c" (uRCX),
    549                "=d" (uRDX)
    550              : "0" (uOperator),
    551                "2" (uIdxECX));
    552     *(uint32_t *)pvEAX = (uint32_t)uRAX;
    553     *(uint32_t *)pvEBX = (uint32_t)uRBX;
    554     *(uint32_t *)pvECX = (uint32_t)uRCX;
    555     *(uint32_t *)pvEDX = (uint32_t)uRDX;
    556 #  else
    557     __asm__ ("xchgl %%ebx, %1\n\t"
    558              "cpuid\n\t"
    559              "xchgl %%ebx, %1\n\t"
    560              : "=a" (*(uint32_t *)pvEAX),
    561                "=r" (*(uint32_t *)pvEBX),
    562                "=c" (*(uint32_t *)pvECX),
    563                "=d" (*(uint32_t *)pvEDX)
    564              : "0" (uOperator),
    565                "2" (uIdxECX));
    566 #  endif
    567 
    568 # elif RT_INLINE_ASM_USES_INTRIN
    569     int aInfo[4];
    570     /* ??? another intrinsic ??? */
    571     __cpuid(aInfo, uOperator);
    572     *(uint32_t *)pvEAX = aInfo[0];
    573     *(uint32_t *)pvEBX = aInfo[1];
    574     *(uint32_t *)pvECX = aInfo[2];
    575     *(uint32_t *)pvEDX = aInfo[3];
    576 
    577 # else
    578     uint32_t    uEAX;
    579     uint32_t    uEBX;
    580     uint32_t    uECX;
    581     uint32_t    uEDX;
    582     __asm
    583     {
    584         push    ebx
    585         mov     eax, [uOperator]
    586         mov     ecx, [uIdxECX]
    587         cpuid
    588         mov     [uEAX], eax
    589         mov     [uEBX], ebx
    590         mov     [uECX], ecx
    591         mov     [uEDX], edx
    592         pop     ebx
    593     }
    594     *(uint32_t *)pvEAX = uEAX;
    595     *(uint32_t *)pvEBX = uEBX;
    596     *(uint32_t *)pvECX = uECX;
    597     *(uint32_t *)pvEDX = uEDX;
    598 # endif
    599 }
    600 #endif
    601 
    602 
    603 /**
    604  * Performs the cpuid instruction returning ecx and edx.
    605  *
    606  * @param   uOperator   CPUID operation (eax).
    607  * @param   pvECX       Where to store ecx.
    608  * @param   pvEDX       Where to store edx.
    609  * @remark  We're using void pointers to ease the use of special bitfield structures and such.
    610  */
    611 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    612 DECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX);
    613 #else
    614 DECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX)
    615 {
    616     uint32_t uEBX;
    617     ASMCpuId(uOperator, &uOperator, &uEBX, pvECX, pvEDX);
    618 }
    619 #endif
    620 
    621 
    622 /**
    623  * Performs the cpuid instruction returning edx.
    624  *
    625  * @param   uOperator   CPUID operation (eax).
    626  * @returns EDX after cpuid operation.
    627  */
    628 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    629 DECLASM(uint32_t) ASMCpuId_EDX(uint32_t uOperator);
    630 #else
    631 DECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)
    632 {
    633     RTCCUINTREG xDX;
    634 # if RT_INLINE_ASM_GNU_STYLE
    635 #  ifdef RT_ARCH_AMD64
    636     RTCCUINTREG uSpill;
    637     __asm__ ("cpuid"
    638              : "=a" (uSpill),
    639                "=d" (xDX)
    640              : "0" (uOperator)
    641              : "rbx", "rcx");
    642 #  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
    643     __asm__ ("push  %%ebx\n\t"
    644              "cpuid\n\t"
    645              "pop   %%ebx\n\t"
    646              : "=a" (uOperator),
    647                "=d" (xDX)
    648              : "0" (uOperator)
    649              : "ecx");
    650 #  else
    651     __asm__ ("cpuid"
    652              : "=a" (uOperator),
    653                "=d" (xDX)
    654              : "0" (uOperator)
    655              : "ebx", "ecx");
    656 #  endif
    657 
    658 # elif RT_INLINE_ASM_USES_INTRIN
    659     int aInfo[4];
    660     __cpuid(aInfo, uOperator);
    661     xDX = aInfo[3];
    662 
    663 # else
    664     __asm
    665     {
    666         push    ebx
    667         mov     eax, [uOperator]
    668         cpuid
    669         mov     [xDX], edx
    670         pop     ebx
    671     }
    672 # endif
    673     return (uint32_t)xDX;
    674 }
    675 #endif
    676 
    677 
    678 /**
    679  * Performs the cpuid instruction returning ecx.
    680  *
    681  * @param   uOperator   CPUID operation (eax).
    682  * @returns ECX after cpuid operation.
    683  */
    684 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    685 DECLASM(uint32_t) ASMCpuId_ECX(uint32_t uOperator);
    686 #else
    687 DECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)
    688 {
    689     RTCCUINTREG xCX;
    690 # if RT_INLINE_ASM_GNU_STYLE
    691 #  ifdef RT_ARCH_AMD64
    692     RTCCUINTREG uSpill;
    693     __asm__ ("cpuid"
    694              : "=a" (uSpill),
    695                "=c" (xCX)
    696              : "0" (uOperator)
    697              : "rbx", "rdx");
    698 #  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
    699     __asm__ ("push  %%ebx\n\t"
    700              "cpuid\n\t"
    701              "pop   %%ebx\n\t"
    702              : "=a" (uOperator),
    703                "=c" (xCX)
    704              : "0" (uOperator)
    705              : "edx");
    706 #  else
    707     __asm__ ("cpuid"
    708              : "=a" (uOperator),
    709                "=c" (xCX)
    710              : "0" (uOperator)
    711              : "ebx", "edx");
    712 
    713 #  endif
    714 
    715 # elif RT_INLINE_ASM_USES_INTRIN
    716     int aInfo[4];
    717     __cpuid(aInfo, uOperator);
    718     xCX = aInfo[2];
    719 
    720 # else
    721     __asm
    722     {
    723         push    ebx
    724         mov     eax, [uOperator]
    725         cpuid
    726         mov     [xCX], ecx
    727         pop     ebx
    728     }
    729 # endif
    730     return (uint32_t)xCX;
    731 }
    732 #endif
    733 
    734 
    735 /**
    736  * Checks if the current CPU supports CPUID.
    737  *
    738  * @returns true if CPUID is supported.
    739  */
    740 DECLINLINE(bool) ASMHasCpuId(void)
    741 {
    742 #ifdef RT_ARCH_AMD64
    743     return true; /* ASSUME that all amd64 compatible CPUs have cpuid. */
    744 #else /* !RT_ARCH_AMD64 */
    745     bool        fRet = false;
    746 # if RT_INLINE_ASM_GNU_STYLE
    747     uint32_t    u1;
    748     uint32_t    u2;
    749     __asm__ ("pushf\n\t"
    750              "pop   %1\n\t"
    751              "mov   %1, %2\n\t"
    752              "xorl  $0x200000, %1\n\t"
    753              "push  %1\n\t"
    754              "popf\n\t"
    755              "pushf\n\t"
    756              "pop   %1\n\t"
    757              "cmpl  %1, %2\n\t"
    758              "setne %0\n\t"
    759              "push  %2\n\t"
    760              "popf\n\t"
    761              : "=m" (fRet), "=r" (u1), "=r" (u2));
    762 # else
    763     __asm
    764     {
    765         pushfd
    766         pop     eax
    767         mov     ebx, eax
    768         xor     eax, 0200000h
    769         push    eax
    770         popfd
    771         pushfd
    772         pop     eax
    773         cmp     eax, ebx
    774         setne   fRet
    775         push    ebx
    776         popfd
    777     }
    778 # endif
    779     return fRet;
    780 #endif /* !RT_ARCH_AMD64 */
    781 }
    782 
    783 
    784 /**
    785  * Gets the APIC ID of the current CPU.
    786  *
    787  * @returns the APIC ID.
    788  */
    789 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    790 DECLASM(uint8_t) ASMGetApicId(void);
    791 #else
    792 DECLINLINE(uint8_t) ASMGetApicId(void)
    793 {
    794     RTCCUINTREG xBX;
    795 # if RT_INLINE_ASM_GNU_STYLE
    796 #  ifdef RT_ARCH_AMD64
    797     RTCCUINTREG uSpill;
    798     __asm__ ("cpuid"
    799              : "=a" (uSpill),
    800                "=b" (xBX)
    801              : "0" (1)
    802              : "rcx", "rdx");
    803 #  elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
    804     RTCCUINTREG uSpill;
    805     __asm__ ("mov   %%ebx,%1\n\t"
    806              "cpuid\n\t"
    807              "xchgl %%ebx,%1\n\t"
    808              : "=a" (uSpill),
    809                "=r" (xBX)
    810              : "0" (1)
    811              : "ecx", "edx");
    812 #  else
    813     RTCCUINTREG uSpill;
    814     __asm__ ("cpuid"
    815              : "=a" (uSpill),
    816                "=b" (xBX)
    817              : "0" (1)
    818              : "ecx", "edx");
    819 #  endif
    820 
    821 # elif RT_INLINE_ASM_USES_INTRIN
    822     int aInfo[4];
    823     __cpuid(aInfo, 1);
    824     xBX = aInfo[1];
    825 
    826 # else
    827     __asm
    828     {
    829         push    ebx
    830         mov     eax, 1
    831         cpuid
    832         mov     [xBX], ebx
    833         pop     ebx
    834     }
    835 # endif
    836     return (uint8_t)(xBX >> 24);
    837 }
    838 #endif
    839 
    840 
    841 /**
    842  * Tests if it a genuine Intel CPU based on the ASMCpuId(0) output.
    843  *
    844  * @returns true/false.
    845  * @param   uEBX    EBX return from ASMCpuId(0)
    846  * @param   uECX    ECX return from ASMCpuId(0)
    847  * @param   uEDX    EDX return from ASMCpuId(0)
    848  */
    849 DECLINLINE(bool) ASMIsIntelCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
    850 {
    851     return uEBX == UINT32_C(0x756e6547)
    852         && uECX == UINT32_C(0x6c65746e)
    853         && uEDX == UINT32_C(0x49656e69);
    854 }
    855 
    856 
    857 /**
    858  * Tests if this is a genuine Intel CPU.
    859  *
    860  * @returns true/false.
    861  * @remarks ASSUMES that cpuid is supported by the CPU.
    862  */
    863 DECLINLINE(bool) ASMIsIntelCpu(void)
    864 {
    865     uint32_t uEAX, uEBX, uECX, uEDX;
    866     ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
    867     return ASMIsIntelCpuEx(uEBX, uECX, uEDX);
    868 }
    869 
    870 
    871 /**
    872  * Tests if it a authentic AMD CPU based on the ASMCpuId(0) output.
    873  *
    874  * @returns true/false.
    875  * @param   uEBX    EBX return from ASMCpuId(0)
    876  * @param   uECX    ECX return from ASMCpuId(0)
    877  * @param   uEDX    EDX return from ASMCpuId(0)
    878  */
    879 DECLINLINE(bool) ASMIsAmdCpuEx(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
    880 {
    881     return uEBX == UINT32_C(0x68747541)
    882         && uECX == UINT32_C(0x444d4163)
    883         && uEDX == UINT32_C(0x69746e65);
    884 }
    885 
    886 
    887 /**
    888  * Tests if this is an authentic AMD CPU.
    889  *
    890  * @returns true/false.
    891  * @remarks ASSUMES that cpuid is supported by the CPU.
    892  */
    893 DECLINLINE(bool) ASMIsAmdCpu(void)
    894 {
    895     uint32_t uEAX, uEBX, uECX, uEDX;
    896     ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
    897     return ASMIsAmdCpuEx(uEBX, uECX, uEDX);
    898 }
    899 
    900 
    901 /**
    902  * Extracts the CPU family from ASMCpuId(1) or ASMCpuId(0x80000001)
    903  *
    904  * @returns Family.
    905  * @param   uEAX    EAX return from ASMCpuId(1) or ASMCpuId(0x80000001).
    906  */
    907 DECLINLINE(uint32_t) ASMGetCpuFamily(uint32_t uEAX)
    908 {
    909     return ((uEAX >> 8) & 0xf) == 0xf
    910          ? ((uEAX >> 20) & 0x7f) + 0xf
    911          : ((uEAX >> 8) & 0xf);
    912 }
    913 
    914 
    915 /**
    916  * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), Intel variant.
    917  *
    918  * @returns Model.
    919  * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
    920  */
    921 DECLINLINE(uint32_t) ASMGetCpuModelIntel(uint32_t uEAX)
    922 {
    923     return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6) /* family! */
    924          ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
    925          : ((uEAX >> 4) & 0xf);
    926 }
    927 
    928 
    929 /**
    930  * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001), AMD variant.
    931  *
    932  * @returns Model.
    933  * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
    934  */
    935 DECLINLINE(uint32_t) ASMGetCpuModelAMD(uint32_t uEAX)
    936 {
    937     return ((uEAX >> 8) & 0xf) == 0xf
    938          ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
    939          : ((uEAX >> 4) & 0xf);
    940 }
    941 
    942 
    943 /**
    944  * Extracts the CPU model from ASMCpuId(1) or ASMCpuId(0x80000001)
    945  *
    946  * @returns Model.
    947  * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
    948  * @param   fIntel  Whether it's an intel CPU. Use ASMIsIntelCpuEx() or ASMIsIntelCpu().
    949  */
    950 DECLINLINE(uint32_t) ASMGetCpuModel(uint32_t uEAX, bool fIntel)
    951 {
    952     return ((uEAX >> 8) & 0xf) == 0xf || (((uEAX >> 8) & 0xf) == 0x6 && fIntel) /* family! */
    953          ? ((uEAX >> 4) & 0xf) | ((uEAX >> 12) & 0xf0)
    954          : ((uEAX >> 4) & 0xf);
    955 }
    956 
    957 
    958 /**
    959  * Extracts the CPU stepping from ASMCpuId(1) or ASMCpuId(0x80000001)
    960  *
    961  * @returns Model.
    962  * @param   uEAX    EAX from ASMCpuId(1) or ASMCpuId(0x80000001).
    963  */
    964 DECLINLINE(uint32_t) ASMGetCpuStepping(uint32_t uEAX)
    965 {
    966     return uEAX & 0xf;
    967 }
    968 
    969 
    970 /**
    971  * Get cr0.
    972  * @returns cr0.
    973  */
    974 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    975 DECLASM(RTCCUINTREG) ASMGetCR0(void);
    976 #else
    977 DECLINLINE(RTCCUINTREG) ASMGetCR0(void)
    978 {
    979     RTCCUINTREG uCR0;
    980 # if RT_INLINE_ASM_USES_INTRIN
    981     uCR0 = __readcr0();
    982 
    983 # elif RT_INLINE_ASM_GNU_STYLE
    984 #  ifdef RT_ARCH_AMD64
    985     __asm__ __volatile__("movq  %%cr0, %0\t\n" : "=r" (uCR0));
    986 #  else
    987     __asm__ __volatile__("movl  %%cr0, %0\t\n" : "=r" (uCR0));
    988 #  endif
    989 # else
    990     __asm
    991     {
    992 #  ifdef RT_ARCH_AMD64
    993         mov     rax, cr0
    994         mov     [uCR0], rax
    995 #  else
    996         mov     eax, cr0
    997         mov     [uCR0], eax
    998 #  endif
    999     }
    1000 # endif
    1001     return uCR0;
    1002 }
    1003 #endif
    1004 
    1005 
    1006 /**
    1007  * Sets the CR0 register.
    1008  * @param   uCR0 The new CR0 value.
    1009  */
    1010 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1011 DECLASM(void) ASMSetCR0(RTCCUINTREG uCR0);
    1012 #else
    1013 DECLINLINE(void) ASMSetCR0(RTCCUINTREG uCR0)
    1014 {
    1015 # if RT_INLINE_ASM_USES_INTRIN
    1016     __writecr0(uCR0);
    1017 
    1018 # elif RT_INLINE_ASM_GNU_STYLE
    1019 #  ifdef RT_ARCH_AMD64
    1020     __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0));
    1021 #  else
    1022     __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0));
    1023 #  endif
    1024 # else
    1025     __asm
    1026     {
    1027 #  ifdef RT_ARCH_AMD64
    1028         mov     rax, [uCR0]
    1029         mov     cr0, rax
    1030 #  else
    1031         mov     eax, [uCR0]
    1032         mov     cr0, eax
    1033 #  endif
    1034     }
    1035 # endif
    1036 }
    1037 #endif
    1038 
    1039 
    1040 /**
    1041  * Get cr2.
    1042  * @returns cr2.
    1043  */
    1044 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1045 DECLASM(RTCCUINTREG) ASMGetCR2(void);
    1046 #else
    1047 DECLINLINE(RTCCUINTREG) ASMGetCR2(void)
    1048 {
    1049     RTCCUINTREG uCR2;
    1050 # if RT_INLINE_ASM_USES_INTRIN
    1051     uCR2 = __readcr2();
    1052 
    1053 # elif RT_INLINE_ASM_GNU_STYLE
    1054 #  ifdef RT_ARCH_AMD64
    1055     __asm__ __volatile__("movq  %%cr2, %0\t\n" : "=r" (uCR2));
    1056 #  else
    1057     __asm__ __volatile__("movl  %%cr2, %0\t\n" : "=r" (uCR2));
    1058 #  endif
    1059 # else
    1060     __asm
    1061     {
    1062 #  ifdef RT_ARCH_AMD64
    1063         mov     rax, cr2
    1064         mov     [uCR2], rax
    1065 #  else
    1066         mov     eax, cr2
    1067         mov     [uCR2], eax
    1068 #  endif
    1069     }
    1070 # endif
    1071     return uCR2;
    1072 }
    1073 #endif
    1074 
    1075 
    1076 /**
    1077  * Sets the CR2 register.
    1078  * @param   uCR2 The new CR0 value.
    1079  */
    1080 #if RT_INLINE_ASM_EXTERNAL
    1081 DECLASM(void) ASMSetCR2(RTCCUINTREG uCR2);
    1082 #else
    1083 DECLINLINE(void) ASMSetCR2(RTCCUINTREG uCR2)
    1084 {
    1085 # if RT_INLINE_ASM_GNU_STYLE
    1086 #  ifdef RT_ARCH_AMD64
    1087     __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2));
    1088 #  else
    1089     __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2));
    1090 #  endif
    1091 # else
    1092     __asm
    1093     {
    1094 #  ifdef RT_ARCH_AMD64
    1095         mov     rax, [uCR2]
    1096         mov     cr2, rax
    1097 #  else
    1098         mov     eax, [uCR2]
    1099         mov     cr2, eax
    1100 #  endif
    1101     }
    1102 # endif
    1103 }
    1104 #endif
    1105 
    1106 
    1107 /**
    1108  * Get cr3.
    1109  * @returns cr3.
    1110  */
    1111 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1112 DECLASM(RTCCUINTREG) ASMGetCR3(void);
    1113 #else
    1114 DECLINLINE(RTCCUINTREG) ASMGetCR3(void)
    1115 {
    1116     RTCCUINTREG uCR3;
    1117 # if RT_INLINE_ASM_USES_INTRIN
    1118     uCR3 = __readcr3();
    1119 
    1120 # elif RT_INLINE_ASM_GNU_STYLE
    1121 #  ifdef RT_ARCH_AMD64
    1122     __asm__ __volatile__("movq  %%cr3, %0\t\n" : "=r" (uCR3));
    1123 #  else
    1124     __asm__ __volatile__("movl  %%cr3, %0\t\n" : "=r" (uCR3));
    1125 #  endif
    1126 # else
    1127     __asm
    1128     {
    1129 #  ifdef RT_ARCH_AMD64
    1130         mov     rax, cr3
    1131         mov     [uCR3], rax
    1132 #  else
    1133         mov     eax, cr3
    1134         mov     [uCR3], eax
    1135 #  endif
    1136     }
    1137 # endif
    1138     return uCR3;
    1139 }
    1140 #endif
    1141 
    1142 
    1143 /**
    1144  * Sets the CR3 register.
    1145  *
    1146  * @param   uCR3    New CR3 value.
    1147  */
    1148 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1149 DECLASM(void) ASMSetCR3(RTCCUINTREG uCR3);
    1150 #else
    1151 DECLINLINE(void) ASMSetCR3(RTCCUINTREG uCR3)
    1152 {
    1153 # if RT_INLINE_ASM_USES_INTRIN
    1154     __writecr3(uCR3);
    1155 
    1156 # elif RT_INLINE_ASM_GNU_STYLE
    1157 #  ifdef RT_ARCH_AMD64
    1158     __asm__ __volatile__("movq %0, %%cr3\n\t" : : "r" (uCR3));
    1159 #  else
    1160     __asm__ __volatile__("movl %0, %%cr3\n\t" : : "r" (uCR3));
    1161 #  endif
    1162 # else
    1163     __asm
    1164     {
    1165 #  ifdef RT_ARCH_AMD64
    1166         mov     rax, [uCR3]
    1167         mov     cr3, rax
    1168 #  else
    1169         mov     eax, [uCR3]
    1170         mov     cr3, eax
    1171 #  endif
    1172     }
    1173 # endif
    1174 }
    1175 #endif
    1176 
    1177 
    1178 /**
    1179  * Reloads the CR3 register.
    1180  */
    1181 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1182 DECLASM(void) ASMReloadCR3(void);
    1183 #else
    1184 DECLINLINE(void) ASMReloadCR3(void)
    1185 {
    1186 # if RT_INLINE_ASM_USES_INTRIN
    1187     __writecr3(__readcr3());
    1188 
    1189 # elif RT_INLINE_ASM_GNU_STYLE
    1190     RTCCUINTREG u;
    1191 #  ifdef RT_ARCH_AMD64
    1192     __asm__ __volatile__("movq %%cr3, %0\n\t"
    1193                          "movq %0, %%cr3\n\t"
    1194                          : "=r" (u));
    1195 #  else
    1196     __asm__ __volatile__("movl %%cr3, %0\n\t"
    1197                          "movl %0, %%cr3\n\t"
    1198                          : "=r" (u));
    1199 #  endif
    1200 # else
    1201     __asm
    1202     {
    1203 #  ifdef RT_ARCH_AMD64
    1204         mov     rax, cr3
    1205         mov     cr3, rax
    1206 #  else
    1207         mov     eax, cr3
    1208         mov     cr3, eax
    1209 #  endif
    1210     }
    1211 # endif
    1212 }
    1213 #endif
    1214 
    1215 
    1216 /**
    1217  * Get cr4.
    1218  * @returns cr4.
    1219  */
    1220 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1221 DECLASM(RTCCUINTREG) ASMGetCR4(void);
    1222 #else
    1223 DECLINLINE(RTCCUINTREG) ASMGetCR4(void)
    1224 {
    1225     RTCCUINTREG uCR4;
    1226 # if RT_INLINE_ASM_USES_INTRIN
    1227     uCR4 = __readcr4();
    1228 
    1229 # elif RT_INLINE_ASM_GNU_STYLE
    1230 #  ifdef RT_ARCH_AMD64
    1231     __asm__ __volatile__("movq  %%cr4, %0\t\n" : "=r" (uCR4));
    1232 #  else
    1233     __asm__ __volatile__("movl  %%cr4, %0\t\n" : "=r" (uCR4));
    1234 #  endif
    1235 # else
    1236     __asm
    1237     {
    1238 #  ifdef RT_ARCH_AMD64
    1239         mov     rax, cr4
    1240         mov     [uCR4], rax
    1241 #  else
    1242         push    eax /* just in case */
    1243         /*mov     eax, cr4*/
    1244         _emit   0x0f
    1245         _emit   0x20
    1246         _emit   0xe0
    1247         mov     [uCR4], eax
    1248         pop     eax
    1249 #  endif
    1250     }
    1251 # endif
    1252     return uCR4;
    1253 }
    1254 #endif
    1255 
    1256 
    1257 /**
    1258  * Sets the CR4 register.
    1259  *
    1260  * @param   uCR4    New CR4 value.
    1261  */
    1262 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1263 DECLASM(void) ASMSetCR4(RTCCUINTREG uCR4);
    1264 #else
    1265 DECLINLINE(void) ASMSetCR4(RTCCUINTREG uCR4)
    1266 {
    1267 # if RT_INLINE_ASM_USES_INTRIN
    1268     __writecr4(uCR4);
    1269 
    1270 # elif RT_INLINE_ASM_GNU_STYLE
    1271 #  ifdef RT_ARCH_AMD64
    1272     __asm__ __volatile__("movq %0, %%cr4\n\t" : : "r" (uCR4));
    1273 #  else
    1274     __asm__ __volatile__("movl %0, %%cr4\n\t" : : "r" (uCR4));
    1275 #  endif
    1276 # else
    1277     __asm
    1278     {
    1279 #  ifdef RT_ARCH_AMD64
    1280         mov     rax, [uCR4]
    1281         mov     cr4, rax
    1282 #  else
    1283         mov     eax, [uCR4]
    1284         _emit   0x0F
    1285         _emit   0x22
    1286         _emit   0xE0        /* mov     cr4, eax */
    1287 #  endif
    1288     }
    1289 # endif
    1290 }
    1291 #endif
    1292 
    1293 
    1294 /**
    1295  * Get cr8.
    1296  * @returns cr8.
    1297  * @remark  The lock prefix hack for access from non-64-bit modes is NOT used and 0 is returned.
    1298  */
    1299 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1300 DECLASM(RTCCUINTREG) ASMGetCR8(void);
    1301 #else
    1302 DECLINLINE(RTCCUINTREG) ASMGetCR8(void)
    1303 {
    1304 # ifdef RT_ARCH_AMD64
    1305     RTCCUINTREG uCR8;
    1306 #  if RT_INLINE_ASM_USES_INTRIN
    1307     uCR8 = __readcr8();
    1308 
    1309 #  elif RT_INLINE_ASM_GNU_STYLE
    1310     __asm__ __volatile__("movq  %%cr8, %0\t\n" : "=r" (uCR8));
    1311 #  else
    1312     __asm
    1313     {
    1314         mov     rax, cr8
    1315         mov     [uCR8], rax
    1316     }
    1317 #  endif
    1318     return uCR8;
    1319 # else /* !RT_ARCH_AMD64 */
    1320     return 0;
    1321 # endif /* !RT_ARCH_AMD64 */
    1322 }
    1323 #endif
    1324 
    1325 
    1326 /**
    1327  * Enables interrupts (EFLAGS.IF).
    1328  */
    1329 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1330 DECLASM(void) ASMIntEnable(void);
    1331 #else
    1332 DECLINLINE(void) ASMIntEnable(void)
    1333 {
    1334 # if RT_INLINE_ASM_GNU_STYLE
    1335     __asm("sti\n");
    1336 # elif RT_INLINE_ASM_USES_INTRIN
    1337     _enable();
    1338 # else
    1339     __asm sti
    1340 # endif
    1341 }
    1342 #endif
    1343 
    1344 
    1345 /**
    1346  * Disables interrupts (!EFLAGS.IF).
    1347  */
    1348 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1349 DECLASM(void) ASMIntDisable(void);
    1350 #else
    1351 DECLINLINE(void) ASMIntDisable(void)
    1352 {
    1353 # if RT_INLINE_ASM_GNU_STYLE
    1354     __asm("cli\n");
    1355 # elif RT_INLINE_ASM_USES_INTRIN
    1356     _disable();
    1357 # else
    1358     __asm cli
    1359 # endif
    1360 }
    1361 #endif
    1362 
    1363 
    1364 /**
    1365  * Disables interrupts and returns previous xFLAGS.
    1366  */
    1367 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1368 DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
    1369 #else
    1370 DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
    1371 {
    1372     RTCCUINTREG xFlags;
    1373 # if RT_INLINE_ASM_GNU_STYLE
    1374 #  ifdef RT_ARCH_AMD64
    1375     __asm__ __volatile__("pushfq\n\t"
    1376                          "cli\n\t"
    1377                          "popq  %0\n\t"
    1378                          : "=r" (xFlags));
    1379 #  else
    1380     __asm__ __volatile__("pushfl\n\t"
    1381                          "cli\n\t"
    1382                          "popl  %0\n\t"
    1383                          : "=r" (xFlags));
    1384 #  endif
    1385 # elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86)
    1386     xFlags = ASMGetFlags();
    1387     _disable();
    1388 # else
    1389     __asm {
    1390         pushfd
    1391         cli
    1392         pop  [xFlags]
    1393     }
    1394 # endif
    1395     return xFlags;
    1396 }
    1397 #endif
    1398 
    1399 
    1400 /**
    1401  * Are interrupts enabled?
    1402  *
    1403  * @returns true / false.
    1404  */
    1405 DECLINLINE(RTCCUINTREG) ASMIntAreEnabled(void)
    1406 {
    1407     RTCCUINTREG uFlags = ASMGetFlags();
    1408     return uFlags & 0x200 /* X86_EFL_IF */ ? true : false;
    1409 }
    1410 
    1411 
    1412 /**
    1413  * Halts the CPU until interrupted.
    1414  */
    1415 #if RT_INLINE_ASM_EXTERNAL
    1416 DECLASM(void) ASMHalt(void);
    1417 #else
    1418 DECLINLINE(void) ASMHalt(void)
    1419 {
    1420 # if RT_INLINE_ASM_GNU_STYLE
    1421     __asm__ __volatile__("hlt\n\t");
    1422 # else
    1423     __asm {
    1424         hlt
    1425     }
    1426 # endif
    1427 }
    1428 #endif
    1429 
    1430 
    1431 /**
    1432  * The PAUSE variant of NOP for helping hyperthreaded CPUs detecing spin locks.
    1433  */
    1434 #if RT_INLINE_ASM_EXTERNAL
    1435 DECLASM(void) ASMNopPause(void);
    1436 #else
    1437 DECLINLINE(void) ASMNopPause(void)
    1438 {
    1439 # if RT_INLINE_ASM_GNU_STYLE
    1440     __asm__ __volatile__(".byte 0xf3,0x90\n\t");
    1441 # else
    1442     __asm {
    1443         _emit 0f3h
    1444         _emit 090h
    1445     }
    1446 # endif
    1447 }
    1448 #endif
    1449 
    1450 
    1451 /**
    1452  * Reads a machine specific register.
    1453  *
    1454  * @returns Register content.
    1455  * @param   uRegister   Register to read.
    1456  */
    1457 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1458 DECLASM(uint64_t) ASMRdMsr(uint32_t uRegister);
    1459 #else
    1460 DECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister)
    1461 {
    1462     RTUINT64U u;
    1463 # if RT_INLINE_ASM_GNU_STYLE
    1464     __asm__ __volatile__("rdmsr\n\t"
    1465                          : "=a" (u.s.Lo),
    1466                            "=d" (u.s.Hi)
    1467                          : "c" (uRegister));
    1468 
    1469 # elif RT_INLINE_ASM_USES_INTRIN
    1470     u.u = __readmsr(uRegister);
    1471 
    1472 # else
    1473     __asm
    1474     {
    1475         mov     ecx, [uRegister]
    1476         rdmsr
    1477         mov     [u.s.Lo], eax
    1478         mov     [u.s.Hi], edx
    1479     }
    1480 # endif
    1481 
    1482     return u.u;
    1483 }
    1484 #endif
    1485 
    1486 
    1487 /**
    1488  * Writes a machine specific register.
    1489  *
    1490  * @returns Register content.
    1491  * @param   uRegister   Register to write to.
    1492  * @param   u64Val      Value to write.
    1493  */
    1494 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1495 DECLASM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val);
    1496 #else
    1497 DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)
    1498 {
    1499     RTUINT64U u;
    1500 
    1501     u.u = u64Val;
    1502 # if RT_INLINE_ASM_GNU_STYLE
    1503     __asm__ __volatile__("wrmsr\n\t"
    1504                          ::"a" (u.s.Lo),
    1505                            "d" (u.s.Hi),
    1506                            "c" (uRegister));
    1507 
    1508 # elif RT_INLINE_ASM_USES_INTRIN
    1509     __writemsr(uRegister, u.u);
    1510 
    1511 # else
    1512     __asm
    1513     {
    1514         mov     ecx, [uRegister]
    1515         mov     edx, [u.s.Hi]
    1516         mov     eax, [u.s.Lo]
    1517         wrmsr
    1518     }
    1519 # endif
    1520 }
    1521 #endif
    1522 
    1523 
    1524 /**
    1525  * Reads low part of a machine specific register.
    1526  *
    1527  * @returns Register content.
    1528  * @param   uRegister   Register to read.
    1529  */
    1530 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1531 DECLASM(uint32_t) ASMRdMsr_Low(uint32_t uRegister);
    1532 #else
    1533 DECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister)
    1534 {
    1535     uint32_t u32;
    1536 # if RT_INLINE_ASM_GNU_STYLE
    1537     __asm__ __volatile__("rdmsr\n\t"
    1538                          : "=a" (u32)
    1539                          : "c" (uRegister)
    1540                          : "edx");
    1541 
    1542 # elif RT_INLINE_ASM_USES_INTRIN
    1543     u32 = (uint32_t)__readmsr(uRegister);
    1544 
    1545 #else
    1546     __asm
    1547     {
    1548         mov     ecx, [uRegister]
    1549         rdmsr
    1550         mov     [u32], eax
    1551     }
    1552 # endif
    1553 
    1554     return u32;
    1555 }
    1556 #endif
    1557 
    1558 
    1559 /**
    1560  * Reads high part of a machine specific register.
    1561  *
    1562  * @returns Register content.
    1563  * @param   uRegister   Register to read.
    1564  */
    1565 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1566 DECLASM(uint32_t) ASMRdMsr_High(uint32_t uRegister);
    1567 #else
    1568 DECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister)
    1569 {
    1570     uint32_t    u32;
    1571 # if RT_INLINE_ASM_GNU_STYLE
    1572     __asm__ __volatile__("rdmsr\n\t"
    1573                          : "=d" (u32)
    1574                          : "c" (uRegister)
    1575                          : "eax");
    1576 
    1577 # elif RT_INLINE_ASM_USES_INTRIN
    1578     u32 = (uint32_t)(__readmsr(uRegister) >> 32);
    1579 
    1580 # else
    1581     __asm
    1582     {
    1583         mov     ecx, [uRegister]
    1584         rdmsr
    1585         mov     [u32], edx
    1586     }
    1587 # endif
    1588 
    1589     return u32;
    1590 }
    1591 #endif
    1592 
    1593 
    1594 /**
    1595  * Gets dr0.
    1596  *
    1597  * @returns dr0.
    1598  */
    1599 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1600 DECLASM(RTCCUINTREG) ASMGetDR0(void);
    1601 #else
    1602 DECLINLINE(RTCCUINTREG) ASMGetDR0(void)
    1603 {
    1604     RTCCUINTREG uDR0;
    1605 # if RT_INLINE_ASM_USES_INTRIN
    1606     uDR0 = __readdr(0);
    1607 # elif RT_INLINE_ASM_GNU_STYLE
    1608 #  ifdef RT_ARCH_AMD64
    1609     __asm__ __volatile__("movq   %%dr0, %0\n\t" : "=r" (uDR0));
    1610 #  else
    1611     __asm__ __volatile__("movl   %%dr0, %0\n\t" : "=r" (uDR0));
    1612 #  endif
    1613 # else
    1614     __asm
    1615     {
    1616 #  ifdef RT_ARCH_AMD64
    1617         mov     rax, dr0
    1618         mov     [uDR0], rax
    1619 #  else
    1620         mov     eax, dr0
    1621         mov     [uDR0], eax
    1622 #  endif
    1623     }
    1624 # endif
    1625     return uDR0;
    1626 }
    1627 #endif
    1628 
    1629 
    1630 /**
    1631  * Gets dr1.
    1632  *
    1633  * @returns dr1.
    1634  */
    1635 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1636 DECLASM(RTCCUINTREG) ASMGetDR1(void);
    1637 #else
    1638 DECLINLINE(RTCCUINTREG) ASMGetDR1(void)
    1639 {
    1640     RTCCUINTREG uDR1;
    1641 # if RT_INLINE_ASM_USES_INTRIN
    1642     uDR1 = __readdr(1);
    1643 # elif RT_INLINE_ASM_GNU_STYLE
    1644 #  ifdef RT_ARCH_AMD64
    1645     __asm__ __volatile__("movq   %%dr1, %0\n\t" : "=r" (uDR1));
    1646 #  else
    1647     __asm__ __volatile__("movl   %%dr1, %0\n\t" : "=r" (uDR1));
    1648 #  endif
    1649 # else
    1650     __asm
    1651     {
    1652 #  ifdef RT_ARCH_AMD64
    1653         mov     rax, dr1
    1654         mov     [uDR1], rax
    1655 #  else
    1656         mov     eax, dr1
    1657         mov     [uDR1], eax
    1658 #  endif
    1659     }
    1660 # endif
    1661     return uDR1;
    1662 }
    1663 #endif
    1664 
    1665 
    1666 /**
    1667  * Gets dr2.
    1668  *
    1669  * @returns dr2.
    1670  */
    1671 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1672 DECLASM(RTCCUINTREG) ASMGetDR2(void);
    1673 #else
    1674 DECLINLINE(RTCCUINTREG) ASMGetDR2(void)
    1675 {
    1676     RTCCUINTREG uDR2;
    1677 # if RT_INLINE_ASM_USES_INTRIN
    1678     uDR2 = __readdr(2);
    1679 # elif RT_INLINE_ASM_GNU_STYLE
    1680 #  ifdef RT_ARCH_AMD64
    1681     __asm__ __volatile__("movq   %%dr2, %0\n\t" : "=r" (uDR2));
    1682 #  else
    1683     __asm__ __volatile__("movl   %%dr2, %0\n\t" : "=r" (uDR2));
    1684 #  endif
    1685 # else
    1686     __asm
    1687     {
    1688 #  ifdef RT_ARCH_AMD64
    1689         mov     rax, dr2
    1690         mov     [uDR2], rax
    1691 #  else
    1692         mov     eax, dr2
    1693         mov     [uDR2], eax
    1694 #  endif
    1695     }
    1696 # endif
    1697     return uDR2;
    1698 }
    1699 #endif
    1700 
    1701 
    1702 /**
    1703  * Gets dr3.
    1704  *
    1705  * @returns dr3.
    1706  */
    1707 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1708 DECLASM(RTCCUINTREG) ASMGetDR3(void);
    1709 #else
    1710 DECLINLINE(RTCCUINTREG) ASMGetDR3(void)
    1711 {
    1712     RTCCUINTREG uDR3;
    1713 # if RT_INLINE_ASM_USES_INTRIN
    1714     uDR3 = __readdr(3);
    1715 # elif RT_INLINE_ASM_GNU_STYLE
    1716 #  ifdef RT_ARCH_AMD64
    1717     __asm__ __volatile__("movq   %%dr3, %0\n\t" : "=r" (uDR3));
    1718 #  else
    1719     __asm__ __volatile__("movl   %%dr3, %0\n\t" : "=r" (uDR3));
    1720 #  endif
    1721 # else
    1722     __asm
    1723     {
    1724 #  ifdef RT_ARCH_AMD64
    1725         mov     rax, dr3
    1726         mov     [uDR3], rax
    1727 #  else
    1728         mov     eax, dr3
    1729         mov     [uDR3], eax
    1730 #  endif
    1731     }
    1732 # endif
    1733     return uDR3;
    1734 }
    1735 #endif
    1736 
    1737 
    1738 /**
    1739  * Gets dr6.
    1740  *
    1741  * @returns dr6.
    1742  */
    1743 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1744 DECLASM(RTCCUINTREG) ASMGetDR6(void);
    1745 #else
    1746 DECLINLINE(RTCCUINTREG) ASMGetDR6(void)
    1747 {
    1748     RTCCUINTREG uDR6;
    1749 # if RT_INLINE_ASM_USES_INTRIN
    1750     uDR6 = __readdr(6);
    1751 # elif RT_INLINE_ASM_GNU_STYLE
    1752 #  ifdef RT_ARCH_AMD64
    1753     __asm__ __volatile__("movq   %%dr6, %0\n\t" : "=r" (uDR6));
    1754 #  else
    1755     __asm__ __volatile__("movl   %%dr6, %0\n\t" : "=r" (uDR6));
    1756 #  endif
    1757 # else
    1758     __asm
    1759     {
    1760 #  ifdef RT_ARCH_AMD64
    1761         mov     rax, dr6
    1762         mov     [uDR6], rax
    1763 #  else
    1764         mov     eax, dr6
    1765         mov     [uDR6], eax
    1766 #  endif
    1767     }
    1768 # endif
    1769     return uDR6;
    1770 }
    1771 #endif
    1772 
    1773 
    1774 /**
    1775  * Reads and clears DR6.
    1776  *
    1777  * @returns DR6.
    1778  */
    1779 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1780 DECLASM(RTCCUINTREG) ASMGetAndClearDR6(void);
    1781 #else
    1782 DECLINLINE(RTCCUINTREG) ASMGetAndClearDR6(void)
    1783 {
    1784     RTCCUINTREG uDR6;
    1785 # if RT_INLINE_ASM_USES_INTRIN
    1786     uDR6 = __readdr(6);
    1787     __writedr(6, 0xffff0ff0U);          /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
    1788 # elif RT_INLINE_ASM_GNU_STYLE
    1789     RTCCUINTREG uNewValue = 0xffff0ff0U;/* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
    1790 #  ifdef RT_ARCH_AMD64
    1791     __asm__ __volatile__("movq   %%dr6, %0\n\t"
    1792                          "movq   %1, %%dr6\n\t"
    1793                          : "=r" (uDR6)
    1794                          : "r" (uNewValue));
    1795 #  else
    1796     __asm__ __volatile__("movl   %%dr6, %0\n\t"
    1797                          "movl   %1, %%dr6\n\t"
    1798                          : "=r" (uDR6)
    1799                          : "r" (uNewValue));
    1800 #  endif
    1801 # else
    1802     __asm
    1803     {
    1804 #  ifdef RT_ARCH_AMD64
    1805         mov     rax, dr6
    1806         mov     [uDR6], rax
    1807         mov     rcx, rax
    1808         mov     ecx, 0ffff0ff0h;        /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */
    1809         mov     dr6, rcx
    1810 #  else
    1811         mov     eax, dr6
    1812         mov     [uDR6], eax
    1813         mov     ecx, 0ffff0ff0h;        /* 31-16 and 4-11 are 1's, 12 is zero. */
    1814         mov     dr6, ecx
    1815 #  endif
    1816     }
    1817 # endif
    1818     return uDR6;
    1819 }
    1820 #endif
    1821 
    1822 
    1823 /**
    1824  * Gets dr7.
    1825  *
    1826  * @returns dr7.
    1827  */
    1828 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1829 DECLASM(RTCCUINTREG) ASMGetDR7(void);
    1830 #else
    1831 DECLINLINE(RTCCUINTREG) ASMGetDR7(void)
    1832 {
    1833     RTCCUINTREG uDR7;
    1834 # if RT_INLINE_ASM_USES_INTRIN
    1835     uDR7 = __readdr(7);
    1836 # elif RT_INLINE_ASM_GNU_STYLE
    1837 #  ifdef RT_ARCH_AMD64
    1838     __asm__ __volatile__("movq   %%dr7, %0\n\t" : "=r" (uDR7));
    1839 #  else
    1840     __asm__ __volatile__("movl   %%dr7, %0\n\t" : "=r" (uDR7));
    1841 #  endif
    1842 # else
    1843     __asm
    1844     {
    1845 #  ifdef RT_ARCH_AMD64
    1846         mov     rax, dr7
    1847         mov     [uDR7], rax
    1848 #  else
    1849         mov     eax, dr7
    1850         mov     [uDR7], eax
    1851 #  endif
    1852     }
    1853 # endif
    1854     return uDR7;
    1855 }
    1856 #endif
    1857 
    1858 
    1859 /**
    1860  * Sets dr0.
    1861  *
    1862  * @param   uDRVal   Debug register value to write
    1863  */
    1864 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1865 DECLASM(void) ASMSetDR0(RTCCUINTREG uDRVal);
    1866 #else
    1867 DECLINLINE(void) ASMSetDR0(RTCCUINTREG uDRVal)
    1868 {
    1869 # if RT_INLINE_ASM_USES_INTRIN
    1870     __writedr(0, uDRVal);
    1871 # elif RT_INLINE_ASM_GNU_STYLE
    1872 #  ifdef RT_ARCH_AMD64
    1873     __asm__ __volatile__("movq   %0, %%dr0\n\t" : : "r" (uDRVal));
    1874 #  else
    1875     __asm__ __volatile__("movl   %0, %%dr0\n\t" : : "r" (uDRVal));
    1876 #  endif
    1877 # else
    1878     __asm
    1879     {
    1880 #  ifdef RT_ARCH_AMD64
    1881         mov     rax, [uDRVal]
    1882         mov     dr0, rax
    1883 #  else
    1884         mov     eax, [uDRVal]
    1885         mov     dr0, eax
    1886 #  endif
    1887     }
    1888 # endif
    1889 }
    1890 #endif
    1891 
    1892 
    1893 /**
    1894  * Sets dr1.
    1895  *
    1896  * @param   uDRVal   Debug register value to write
    1897  */
    1898 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1899 DECLASM(void) ASMSetDR1(RTCCUINTREG uDRVal);
    1900 #else
    1901 DECLINLINE(void) ASMSetDR1(RTCCUINTREG uDRVal)
    1902 {
    1903 # if RT_INLINE_ASM_USES_INTRIN
    1904     __writedr(1, uDRVal);
    1905 # elif RT_INLINE_ASM_GNU_STYLE
    1906 #  ifdef RT_ARCH_AMD64
    1907     __asm__ __volatile__("movq   %0, %%dr1\n\t" : : "r" (uDRVal));
    1908 #  else
    1909     __asm__ __volatile__("movl   %0, %%dr1\n\t" : : "r" (uDRVal));
    1910 #  endif
    1911 # else
    1912     __asm
    1913     {
    1914 #  ifdef RT_ARCH_AMD64
    1915         mov     rax, [uDRVal]
    1916         mov     dr1, rax
    1917 #  else
    1918         mov     eax, [uDRVal]
    1919         mov     dr1, eax
    1920 #  endif
    1921     }
    1922 # endif
    1923 }
    1924 #endif
    1925 
    1926 
    1927 /**
    1928  * Sets dr2.
    1929  *
    1930  * @param   uDRVal   Debug register value to write
    1931  */
    1932 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1933 DECLASM(void) ASMSetDR2(RTCCUINTREG uDRVal);
    1934 #else
    1935 DECLINLINE(void) ASMSetDR2(RTCCUINTREG uDRVal)
    1936 {
    1937 # if RT_INLINE_ASM_USES_INTRIN
    1938     __writedr(2, uDRVal);
    1939 # elif RT_INLINE_ASM_GNU_STYLE
    1940 #  ifdef RT_ARCH_AMD64
    1941     __asm__ __volatile__("movq   %0, %%dr2\n\t" : : "r" (uDRVal));
    1942 #  else
    1943     __asm__ __volatile__("movl   %0, %%dr2\n\t" : : "r" (uDRVal));
    1944 #  endif
    1945 # else
    1946     __asm
    1947     {
    1948 #  ifdef RT_ARCH_AMD64
    1949         mov     rax, [uDRVal]
    1950         mov     dr2, rax
    1951 #  else
    1952         mov     eax, [uDRVal]
    1953         mov     dr2, eax
    1954 #  endif
    1955     }
    1956 # endif
    1957 }
    1958 #endif
    1959 
    1960 
    1961 /**
    1962  * Sets dr3.
    1963  *
    1964  * @param   uDRVal   Debug register value to write
    1965  */
    1966 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    1967 DECLASM(void) ASMSetDR3(RTCCUINTREG uDRVal);
    1968 #else
    1969 DECLINLINE(void) ASMSetDR3(RTCCUINTREG uDRVal)
    1970 {
    1971 # if RT_INLINE_ASM_USES_INTRIN
    1972     __writedr(3, uDRVal);
    1973 # elif RT_INLINE_ASM_GNU_STYLE
    1974 #  ifdef RT_ARCH_AMD64
    1975     __asm__ __volatile__("movq   %0, %%dr3\n\t" : : "r" (uDRVal));
    1976 #  else
    1977     __asm__ __volatile__("movl   %0, %%dr3\n\t" : : "r" (uDRVal));
    1978 #  endif
    1979 # else
    1980     __asm
    1981     {
    1982 #  ifdef RT_ARCH_AMD64
    1983         mov     rax, [uDRVal]
    1984         mov     dr3, rax
    1985 #  else
    1986         mov     eax, [uDRVal]
    1987         mov     dr3, eax
    1988 #  endif
    1989     }
    1990 # endif
    1991 }
    1992 #endif
    1993 
    1994 
    1995 /**
    1996  * Sets dr6.
    1997  *
    1998  * @param   uDRVal   Debug register value to write
    1999  */
    2000 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2001 DECLASM(void) ASMSetDR6(RTCCUINTREG uDRVal);
    2002 #else
    2003 DECLINLINE(void) ASMSetDR6(RTCCUINTREG uDRVal)
    2004 {
    2005 # if RT_INLINE_ASM_USES_INTRIN
    2006     __writedr(6, uDRVal);
    2007 # elif RT_INLINE_ASM_GNU_STYLE
    2008 #  ifdef RT_ARCH_AMD64
    2009     __asm__ __volatile__("movq   %0, %%dr6\n\t" : : "r" (uDRVal));
    2010 #  else
    2011     __asm__ __volatile__("movl   %0, %%dr6\n\t" : : "r" (uDRVal));
    2012 #  endif
    2013 # else
    2014     __asm
    2015     {
    2016 #  ifdef RT_ARCH_AMD64
    2017         mov     rax, [uDRVal]
    2018         mov     dr6, rax
    2019 #  else
    2020         mov     eax, [uDRVal]
    2021         mov     dr6, eax
    2022 #  endif
    2023     }
    2024 # endif
    2025 }
    2026 #endif
    2027 
    2028 
    2029 /**
    2030  * Sets dr7.
    2031  *
    2032  * @param   uDRVal   Debug register value to write
    2033  */
    2034 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2035 DECLASM(void) ASMSetDR7(RTCCUINTREG uDRVal);
    2036 #else
    2037 DECLINLINE(void) ASMSetDR7(RTCCUINTREG uDRVal)
    2038 {
    2039 # if RT_INLINE_ASM_USES_INTRIN
    2040     __writedr(7, uDRVal);
    2041 # elif RT_INLINE_ASM_GNU_STYLE
    2042 #  ifdef RT_ARCH_AMD64
    2043     __asm__ __volatile__("movq   %0, %%dr7\n\t" : : "r" (uDRVal));
    2044 #  else
    2045     __asm__ __volatile__("movl   %0, %%dr7\n\t" : : "r" (uDRVal));
    2046 #  endif
    2047 # else
    2048     __asm
    2049     {
    2050 #  ifdef RT_ARCH_AMD64
    2051         mov     rax, [uDRVal]
    2052         mov     dr7, rax
    2053 #  else
    2054         mov     eax, [uDRVal]
    2055         mov     dr7, eax
    2056 #  endif
    2057     }
    2058 # endif
    2059 }
    2060 #endif
    2061 
    2062 
    2063 /**
    2064  * Writes a 8-bit unsigned integer to an I/O port, ordered.
    2065  *
    2066  * @param   Port    I/O port to write to.
    2067  * @param   u8      8-bit integer to write.
    2068  */
    2069 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2070 DECLASM(void) ASMOutU8(RTIOPORT Port, uint8_t u8);
    2071 #else
    2072 DECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8)
    2073 {
    2074 # if RT_INLINE_ASM_GNU_STYLE
    2075     __asm__ __volatile__("outb %b1, %w0\n\t"
    2076                          :: "Nd" (Port),
    2077                             "a" (u8));
    2078 
    2079 # elif RT_INLINE_ASM_USES_INTRIN
    2080     __outbyte(Port, u8);
    2081 
    2082 # else
    2083     __asm
    2084     {
    2085         mov     dx, [Port]
    2086         mov     al, [u8]
    2087         out     dx, al
    2088     }
    2089 # endif
    2090 }
    2091 #endif
    2092 
    2093 
    2094 /**
    2095  * Reads a 8-bit unsigned integer from an I/O port, ordered.
    2096  *
    2097  * @returns 8-bit integer.
    2098  * @param   Port    I/O port to read from.
    2099  */
    2100 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2101 DECLASM(uint8_t) ASMInU8(RTIOPORT Port);
    2102 #else
    2103 DECLINLINE(uint8_t) ASMInU8(RTIOPORT Port)
    2104 {
    2105     uint8_t u8;
    2106 # if RT_INLINE_ASM_GNU_STYLE
    2107     __asm__ __volatile__("inb %w1, %b0\n\t"
    2108                          : "=a" (u8)
    2109                          : "Nd" (Port));
    2110 
    2111 # elif RT_INLINE_ASM_USES_INTRIN
    2112     u8 = __inbyte(Port);
    2113 
    2114 # else
    2115     __asm
    2116     {
    2117         mov     dx, [Port]
    2118         in      al, dx
    2119         mov     [u8], al
    2120     }
    2121 # endif
    2122     return u8;
    2123 }
    2124 #endif
    2125 
    2126 
    2127 /**
    2128  * Writes a 16-bit unsigned integer to an I/O port, ordered.
    2129  *
    2130  * @param   Port    I/O port to write to.
    2131  * @param   u16     16-bit integer to write.
    2132  */
    2133 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2134 DECLASM(void) ASMOutU16(RTIOPORT Port, uint16_t u16);
    2135 #else
    2136 DECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16)
    2137 {
    2138 # if RT_INLINE_ASM_GNU_STYLE
    2139     __asm__ __volatile__("outw %w1, %w0\n\t"
    2140                          :: "Nd" (Port),
    2141                             "a" (u16));
    2142 
    2143 # elif RT_INLINE_ASM_USES_INTRIN
    2144     __outword(Port, u16);
    2145 
    2146 # else
    2147     __asm
    2148     {
    2149         mov     dx, [Port]
    2150         mov     ax, [u16]
    2151         out     dx, ax
    2152     }
    2153 # endif
    2154 }
    2155 #endif
    2156 
    2157 
    2158 /**
    2159  * Reads a 16-bit unsigned integer from an I/O port, ordered.
    2160  *
    2161  * @returns 16-bit integer.
    2162  * @param   Port    I/O port to read from.
    2163  */
    2164 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2165 DECLASM(uint16_t) ASMInU16(RTIOPORT Port);
    2166 #else
    2167 DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port)
    2168 {
    2169     uint16_t u16;
    2170 # if RT_INLINE_ASM_GNU_STYLE
    2171     __asm__ __volatile__("inw %w1, %w0\n\t"
    2172                          : "=a" (u16)
    2173                          : "Nd" (Port));
    2174 
    2175 # elif RT_INLINE_ASM_USES_INTRIN
    2176     u16 = __inword(Port);
    2177 
    2178 # else
    2179     __asm
    2180     {
    2181         mov     dx, [Port]
    2182         in      ax, dx
    2183         mov     [u16], ax
    2184     }
    2185 # endif
    2186     return u16;
    2187 }
    2188 #endif
    2189 
    2190 
    2191 /**
    2192  * Writes a 32-bit unsigned integer to an I/O port, ordered.
    2193  *
    2194  * @param   Port    I/O port to write to.
    2195  * @param   u32     32-bit integer to write.
    2196  */
    2197 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2198 DECLASM(void) ASMOutU32(RTIOPORT Port, uint32_t u32);
    2199 #else
    2200 DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32)
    2201 {
    2202 # if RT_INLINE_ASM_GNU_STYLE
    2203     __asm__ __volatile__("outl %1, %w0\n\t"
    2204                          :: "Nd" (Port),
    2205                             "a" (u32));
    2206 
    2207 # elif RT_INLINE_ASM_USES_INTRIN
    2208     __outdword(Port, u32);
    2209 
    2210 # else
    2211     __asm
    2212     {
    2213         mov     dx, [Port]
    2214         mov     eax, [u32]
    2215         out     dx, eax
    2216     }
    2217 # endif
    2218 }
    2219 #endif
    2220 
    2221 
    2222 /**
    2223  * Reads a 32-bit unsigned integer from an I/O port, ordered.
    2224  *
    2225  * @returns 32-bit integer.
    2226  * @param   Port    I/O port to read from.
    2227  */
    2228 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2229 DECLASM(uint32_t) ASMInU32(RTIOPORT Port);
    2230 #else
    2231 DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port)
    2232 {
    2233     uint32_t u32;
    2234 # if RT_INLINE_ASM_GNU_STYLE
    2235     __asm__ __volatile__("inl %w1, %0\n\t"
    2236                          : "=a" (u32)
    2237                          : "Nd" (Port));
    2238 
    2239 # elif RT_INLINE_ASM_USES_INTRIN
    2240     u32 = __indword(Port);
    2241 
    2242 # else
    2243     __asm
    2244     {
    2245         mov     dx, [Port]
    2246         in      eax, dx
    2247         mov     [u32], eax
    2248     }
    2249 # endif
    2250     return u32;
    2251 }
    2252 #endif
    2253 
    2254 
    2255 /**
    2256  * Writes a string of 8-bit unsigned integer items to an I/O port, ordered.
    2257  *
    2258  * @param   Port    I/O port to write to.
    2259  * @param   pau8    Pointer to the string buffer.
    2260  * @param   c       The number of items to write.
    2261  */
    2262 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2263 DECLASM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c);
    2264 #else
    2265 DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c)
    2266 {
    2267 # if RT_INLINE_ASM_GNU_STYLE
    2268     __asm__ __volatile__("rep; outsb\n\t"
    2269                          : "+S" (pau8),
    2270                            "+c" (c)
    2271                          : "d" (Port));
    2272 
    2273 # elif RT_INLINE_ASM_USES_INTRIN
    2274     __outbytestring(Port, (unsigned char *)pau8, (unsigned long)c);
    2275 
    2276 # else
    2277     __asm
    2278     {
    2279         mov     dx, [Port]
    2280         mov     ecx, [c]
    2281         mov     eax, [pau8]
    2282         xchg    esi, eax
    2283         rep outsb
    2284         xchg    esi, eax
    2285     }
    2286 # endif
    2287 }
    2288 #endif
    2289 
    2290 
    2291 /**
    2292  * Reads a string of 8-bit unsigned integer items from an I/O port, ordered.
    2293  *
    2294  * @param   Port    I/O port to read from.
    2295  * @param   pau8    Pointer to the string buffer (output).
    2296  * @param   c       The number of items to read.
    2297  */
    2298 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2299 DECLASM(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c);
    2300 #else
    2301 DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c)
    2302 {
    2303 # if RT_INLINE_ASM_GNU_STYLE
    2304     __asm__ __volatile__("rep; insb\n\t"
    2305                          : "+D" (pau8),
    2306                            "+c" (c)
    2307                          : "d" (Port));
    2308 
    2309 # elif RT_INLINE_ASM_USES_INTRIN
    2310     __inbytestring(Port, pau8, (unsigned long)c);
    2311 
    2312 # else
    2313     __asm
    2314     {
    2315         mov     dx, [Port]
    2316         mov     ecx, [c]
    2317         mov     eax, [pau8]
    2318         xchg    edi, eax
    2319         rep insb
    2320         xchg    edi, eax
    2321     }
    2322 # endif
    2323 }
    2324 #endif
    2325 
    2326 
    2327 /**
    2328  * Writes a string of 16-bit unsigned integer items to an I/O port, ordered.
    2329  *
    2330  * @param   Port    I/O port to write to.
    2331  * @param   pau16   Pointer to the string buffer.
    2332  * @param   c       The number of items to write.
    2333  */
    2334 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2335 DECLASM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c);
    2336 #else
    2337 DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c)
    2338 {
    2339 # if RT_INLINE_ASM_GNU_STYLE
    2340     __asm__ __volatile__("rep; outsw\n\t"
    2341                          : "+S" (pau16),
    2342                            "+c" (c)
    2343                          : "d" (Port));
    2344 
    2345 # elif RT_INLINE_ASM_USES_INTRIN
    2346     __outwordstring(Port, (unsigned short *)pau16, (unsigned long)c);
    2347 
    2348 # else
    2349     __asm
    2350     {
    2351         mov     dx, [Port]
    2352         mov     ecx, [c]
    2353         mov     eax, [pau16]
    2354         xchg    esi, eax
    2355         rep outsw
    2356         xchg    esi, eax
    2357     }
    2358 # endif
    2359 }
    2360 #endif
    2361 
    2362 
    2363 /**
    2364  * Reads a string of 16-bit unsigned integer items from an I/O port, ordered.
    2365  *
    2366  * @param   Port    I/O port to read from.
    2367  * @param   pau16   Pointer to the string buffer (output).
    2368  * @param   c       The number of items to read.
    2369  */
    2370 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2371 DECLASM(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c);
    2372 #else
    2373 DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c)
    2374 {
    2375 # if RT_INLINE_ASM_GNU_STYLE
    2376     __asm__ __volatile__("rep; insw\n\t"
    2377                          : "+D" (pau16),
    2378                            "+c" (c)
    2379                          : "d" (Port));
    2380 
    2381 # elif RT_INLINE_ASM_USES_INTRIN
    2382     __inwordstring(Port, pau16, (unsigned long)c);
    2383 
    2384 # else
    2385     __asm
    2386     {
    2387         mov     dx, [Port]
    2388         mov     ecx, [c]
    2389         mov     eax, [pau16]
    2390         xchg    edi, eax
    2391         rep insw
    2392         xchg    edi, eax
    2393     }
    2394 # endif
    2395 }
    2396 #endif
    2397 
    2398 
    2399 /**
    2400  * Writes a string of 32-bit unsigned integer items to an I/O port, ordered.
    2401  *
    2402  * @param   Port    I/O port to write to.
    2403  * @param   pau32   Pointer to the string buffer.
    2404  * @param   c       The number of items to write.
    2405  */
    2406 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2407 DECLASM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c);
    2408 #else
    2409 DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c)
    2410 {
    2411 # if RT_INLINE_ASM_GNU_STYLE
    2412     __asm__ __volatile__("rep; outsl\n\t"
    2413                          : "+S" (pau32),
    2414                            "+c" (c)
    2415                          : "d" (Port));
    2416 
    2417 # elif RT_INLINE_ASM_USES_INTRIN
    2418     __outdwordstring(Port, (unsigned long *)pau32, (unsigned long)c);
    2419 
    2420 # else
    2421     __asm
    2422     {
    2423         mov     dx, [Port]
    2424         mov     ecx, [c]
    2425         mov     eax, [pau32]
    2426         xchg    esi, eax
    2427         rep outsd
    2428         xchg    esi, eax
    2429     }
    2430 # endif
    2431 }
    2432 #endif
    2433 
    2434 
    2435 /**
    2436  * Reads a string of 32-bit unsigned integer items from an I/O port, ordered.
    2437  *
    2438  * @param   Port    I/O port to read from.
    2439  * @param   pau32   Pointer to the string buffer (output).
    2440  * @param   c       The number of items to read.
    2441  */
    2442 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2443 DECLASM(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c);
    2444 #else
    2445 DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c)
    2446 {
    2447 # if RT_INLINE_ASM_GNU_STYLE
    2448     __asm__ __volatile__("rep; insl\n\t"
    2449                          : "+D" (pau32),
    2450                            "+c" (c)
    2451                          : "d" (Port));
    2452 
    2453 # elif RT_INLINE_ASM_USES_INTRIN
    2454     __indwordstring(Port, (unsigned long *)pau32, (unsigned long)c);
    2455 
    2456 # else
    2457     __asm
    2458     {
    2459         mov     dx, [Port]
    2460         mov     ecx, [c]
    2461         mov     eax, [pau32]
    2462         xchg    edi, eax
    2463         rep insd
    2464         xchg    edi, eax
    2465     }
    2466 # endif
    2467 }
    2468 #endif
    2469 
    2470 
    2471 /**
    2472  * Invalidate page.
    2473  *
    2474  * @param   pv      Address of the page to invalidate.
    2475  */
    2476 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2477 DECLASM(void) ASMInvalidatePage(void *pv);
    2478 #else
    2479 DECLINLINE(void) ASMInvalidatePage(void *pv)
    2480 {
    2481 # if RT_INLINE_ASM_USES_INTRIN
    2482     __invlpg(pv);
    2483 
    2484 # elif RT_INLINE_ASM_GNU_STYLE
    2485     __asm__ __volatile__("invlpg %0\n\t"
    2486                          : : "m" (*(uint8_t *)pv));
    2487 # else
    2488     __asm
    2489     {
    2490 #  ifdef RT_ARCH_AMD64
    2491         mov     rax, [pv]
    2492         invlpg  [rax]
    2493 #  else
    2494         mov     eax, [pv]
    2495         invlpg  [eax]
    2496 #  endif
    2497     }
    2498 # endif
    2499 }
    2500 #endif
    2501 
    2502 
    2503 /**
    2504  * Write back the internal caches and invalidate them.
    2505  */
    2506 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
    2507 DECLASM(void) ASMWriteBackAndInvalidateCaches(void);
    2508 #else
    2509 DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
    2510 {
    2511 # if RT_INLINE_ASM_USES_INTRIN
    2512     __wbinvd();
    2513 
    2514 # elif RT_INLINE_ASM_GNU_STYLE
    2515     __asm__ __volatile__("wbinvd");
    2516 # else
    2517     __asm
    2518     {
    2519         wbinvd
    2520     }
    2521 # endif
    2522 }
    2523 #endif
    2524 
    2525 
    2526 /**
    2527  * Invalidate internal and (perhaps) external caches without first
    2528  * flushing dirty cache lines. Use with extreme care.
    2529  */
    2530 #if RT_INLINE_ASM_EXTERNAL
    2531 DECLASM(void) ASMInvalidateInternalCaches(void);
    2532 #else
    2533 DECLINLINE(void) ASMInvalidateInternalCaches(void)
    2534 {
    2535 # if RT_INLINE_ASM_GNU_STYLE
    2536     __asm__ __volatile__("invd");
    2537 # else
    2538     __asm
    2539     {
    2540         invd
    2541     }
    2542 # endif
    2543 }
    2544 #endif
    2545 
    2546 
    2547 /**
    2548  * Memory load/store fence, waits for any pending writes and reads to complete.
    2549  * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
    2550  */
    2551 DECLINLINE(void) ASMMemoryFenceSSE2(void)
    2552 {
    2553 #if RT_INLINE_ASM_GNU_STYLE
    2554     __asm__ __volatile__ (".byte 0x0f,0xae,0xf0\n\t");
    2555 #elif RT_INLINE_ASM_USES_INTRIN
    2556     _mm_mfence();
    2557 #else
    2558     __asm
    2559     {
    2560         _emit   0x0f
    2561         _emit   0xae
    2562         _emit   0xf0
    2563     }
    2564 #endif
    2565 }
    2566 
    2567 
    2568 /**
    2569  * Memory store fence, waits for any writes to complete.
    2570  * Requires the X86_CPUID_FEATURE_EDX_SSE CPUID bit set.
    2571  */
    2572 DECLINLINE(void) ASMWriteFenceSSE(void)
    2573 {
    2574 #if RT_INLINE_ASM_GNU_STYLE
    2575     __asm__ __volatile__ (".byte 0x0f,0xae,0xf8\n\t");
    2576 #elif RT_INLINE_ASM_USES_INTRIN
    2577     _mm_sfence();
    2578 #else
    2579     __asm
    2580     {
    2581         _emit   0x0f
    2582         _emit   0xae
    2583         _emit   0xf8
    2584     }
    2585 #endif
    2586 }
    2587 
    2588 
    2589 /**
    2590  * Memory load fence, waits for any pending reads to complete.
    2591  * Requires the X86_CPUID_FEATURE_EDX_SSE2 CPUID bit set.
    2592  */
    2593 DECLINLINE(void) ASMReadFenceSSE2(void)
    2594 {
    2595 #if RT_INLINE_ASM_GNU_STYLE
    2596     __asm__ __volatile__ (".byte 0x0f,0xae,0xe8\n\t");
    2597 #elif RT_INLINE_ASM_USES_INTRIN
    2598     _mm_lfence();
    2599 #else
    2600     __asm
    2601     {
    2602         _emit   0x0f
    2603         _emit   0xae
    2604         _emit   0xe8
    2605     }
    2606 #endif
    2607 }
    2608 
    2609 
    2610 /** @name Interger Math Optimizations
    261134 * @{ */
    261235
     
    261639 * @returns u32F1 * u32F2.
    261740 */
    2618 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     41#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    261942DECLASM(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2);
    262043#else
    262144DECLINLINE(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2)
    262245{
    2623 # ifdef RT_ARCH_AMD64
    2624     return (uint64_t)u32F1 * u32F2;
    2625 # else /* !RT_ARCH_AMD64 */
     46# ifdef RT_ARCH_X86
    262647    uint64_t u64;
    262748#  if RT_INLINE_ASM_GNU_STYLE
     
    264061#  endif
    264162    return u64;
    2642 # endif /* !RT_ARCH_AMD64 */
     63# else  /* generic: */
     64    return (uint64_t)u32F1 * u32F2;
     65# endif
    264366}
    264467#endif
     
    265073 * @returns u32F1 * u32F2.
    265174 */
    2652 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     75#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    265376DECLASM(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2);
    265477#else
    265578DECLINLINE(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2)
    265679{
    2657 # ifdef RT_ARCH_AMD64
    2658     return (int64_t)i32F1 * i32F2;
    2659 # else /* !RT_ARCH_AMD64 */
     80# ifdef RT_ARCH_X86
    266081    int64_t i64;
    266182#  if RT_INLINE_ASM_GNU_STYLE
     
    267495#  endif
    267596    return i64;
    2676 # endif /* !RT_ARCH_AMD64 */
     97# else  /* generic: */
     98    return (int64_t)i32F1 * i32F2;
     99# endif
    2677100}
    2678101#endif
     
    2684107 * @returns u64 / u32.
    2685108 */
    2686 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     109#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    2687110DECLASM(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32);
    2688111#else
    2689112DECLINLINE(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32)
    2690113{
    2691 # ifdef RT_ARCH_AMD64
    2692     return (uint32_t)(u64 / u32);
    2693 # else /* !RT_ARCH_AMD64 */
     114# ifdef RT_ARCH_X86
    2694115#  if RT_INLINE_ASM_GNU_STYLE
    2695116    RTCCUINTREG uDummy;
     
    2708129#  endif
    2709130    return u32;
    2710 # endif /* !RT_ARCH_AMD64 */
     131# else   /* generic: */
     132    return (uint32_t)(u64 / u32);
     133# endif
    2711134}
    2712135#endif
     
    2718141 * @returns u64 / u32.
    2719142 */
    2720 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     143#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    2721144DECLASM(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32);
    2722145#else
    2723146DECLINLINE(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32)
    2724147{
    2725 # ifdef RT_ARCH_AMD64
    2726     return (int32_t)(i64 / i32);
    2727 # else /* !RT_ARCH_AMD64 */
     148# ifdef RT_ARCH_X86
    2728149#  if RT_INLINE_ASM_GNU_STYLE
    2729150    RTCCUINTREG iDummy;
     
    2742163#  endif
    2743164    return i32;
    2744 # endif /* !RT_ARCH_AMD64 */
     165# else  /* generic: */
     166    return (int32_t)(i64 / i32);
     167# endif
    2745168}
    2746169#endif
     
    2755178 * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash.
    2756179 */
    2757 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     180#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    2758181DECLASM(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32);
    2759182#else
    2760183DECLINLINE(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32)
    2761184{
    2762 # ifdef RT_ARCH_AMD64
    2763     return (uint32_t)(u64 % u32);
    2764 # else /* !RT_ARCH_AMD64 */
     185# ifdef RT_ARCH_X86
    2765186#  if RT_INLINE_ASM_GNU_STYLE
    2766187    RTCCUINTREG uDummy;
     
    2779200#  endif
    2780201    return u32;
    2781 # endif /* !RT_ARCH_AMD64 */
     202# else  /* generic: */
     203    return (uint32_t)(u64 % u32);
     204# endif
    2782205}
    2783206#endif
     
    2792215 * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash.
    2793216 */
    2794 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)
     217#if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86)
    2795218DECLASM(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32);
    2796219#else
    2797220DECLINLINE(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32)
    2798221{
    2799 # ifdef RT_ARCH_AMD64
    2800     return (int32_t)(i64 % i32);
    2801 # else /* !RT_ARCH_AMD64 */
     222# ifdef RT_ARCH_X86
    2802223#  if RT_INLINE_ASM_GNU_STYLE
    2803224    RTCCUINTREG iDummy;
     
    2816237#  endif
    2817238    return i32;
    2818 # endif /* !RT_ARCH_AMD64 */
     239# else  /* generic: */
     240    return (int32_t)(i64 % i32);
     241# endif
    2819242}
    2820243#endif
     
    2831254 * @param   u32B    The 32-bit value to multiple by A.
    2832255 * @param   u32C    The 32-bit value to divide A*B by.
    2833  */
    2834 #if RT_INLINE_ASM_EXTERNAL || !defined(__GNUC__)
     256 *
     257 * @remarks Architecture specific.
     258 */
     259#if RT_INLINE_ASM_EXTERNAL || !defined(__GNUC__) || (!defined(RT_ARCH_AMD64) && defined(RT_ARCH_X86))
    2835260DECLASM(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C);
    2836261#else
     
    2891316
    2892317/** @} */
    2893 
    2894 /** @} */
    2895 #endif
    2896 
     318#endif
     319
Note: See TracChangeset for help on using the changeset viewer.

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