Changeset 29250 in vbox for trunk/include/iprt/asm-math.h
- Timestamp:
- May 9, 2010 5:53:58 PM (15 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/asm-math.h
r29245 r29250 1 1 /** @file 2 * IPRT - A MD64 and x86 Specific Assembly Functions.2 * IPRT - Assembly Routines for Optimizing some Integers Math Operations. 3 3 */ 4 4 … … 24 24 */ 25 25 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 75 33 * @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 RTIDTR83 {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 RTGDTR94 {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_EXTERNAL108 DECLASM(void) ASMGetIDTR(PRTIDTR pIdtr);109 #else110 DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)111 {112 # if RT_INLINE_ASM_GNU_STYLE113 __asm__ __volatile__("sidt %0" : "=m" (*pIdtr));114 # else115 __asm116 {117 # ifdef RT_ARCH_AMD64118 mov rax, [pIdtr]119 sidt [rax]120 # else121 mov eax, [pIdtr]122 sidt [eax]123 # endif124 }125 # endif126 }127 #endif128 129 130 /**131 * Sets the content of the IDTR CPU register.132 * @param pIdtr Where to load the IDTR contents from133 */134 #if RT_INLINE_ASM_EXTERNAL135 DECLASM(void) ASMSetIDTR(const RTIDTR *pIdtr);136 #else137 DECLINLINE(void) ASMSetIDTR(const RTIDTR *pIdtr)138 {139 # if RT_INLINE_ASM_GNU_STYLE140 __asm__ __volatile__("lidt %0" : : "m" (*pIdtr));141 # else142 __asm143 {144 # ifdef RT_ARCH_AMD64145 mov rax, [pIdtr]146 lidt [rax]147 # else148 mov eax, [pIdtr]149 lidt [eax]150 # endif151 }152 # endif153 }154 #endif155 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_EXTERNAL162 DECLASM(void) ASMGetGDTR(PRTGDTR pGdtr);163 #else164 DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)165 {166 # if RT_INLINE_ASM_GNU_STYLE167 __asm__ __volatile__("sgdt %0" : "=m" (*pGdtr));168 # else169 __asm170 {171 # ifdef RT_ARCH_AMD64172 mov rax, [pGdtr]173 sgdt [rax]174 # else175 mov eax, [pGdtr]176 sgdt [eax]177 # endif178 }179 # endif180 }181 #endif182 183 /**184 * Get the cs register.185 * @returns cs.186 */187 #if RT_INLINE_ASM_EXTERNAL188 DECLASM(RTSEL) ASMGetCS(void);189 #else190 DECLINLINE(RTSEL) ASMGetCS(void)191 {192 RTSEL SelCS;193 # if RT_INLINE_ASM_GNU_STYLE194 __asm__ __volatile__("movw %%cs, %0\n\t" : "=r" (SelCS));195 # else196 __asm197 {198 mov ax, cs199 mov [SelCS], ax200 }201 # endif202 return SelCS;203 }204 #endif205 206 207 /**208 * Get the DS register.209 * @returns DS.210 */211 #if RT_INLINE_ASM_EXTERNAL212 DECLASM(RTSEL) ASMGetDS(void);213 #else214 DECLINLINE(RTSEL) ASMGetDS(void)215 {216 RTSEL SelDS;217 # if RT_INLINE_ASM_GNU_STYLE218 __asm__ __volatile__("movw %%ds, %0\n\t" : "=r" (SelDS));219 # else220 __asm221 {222 mov ax, ds223 mov [SelDS], ax224 }225 # endif226 return SelDS;227 }228 #endif229 230 231 /**232 * Get the ES register.233 * @returns ES.234 */235 #if RT_INLINE_ASM_EXTERNAL236 DECLASM(RTSEL) ASMGetES(void);237 #else238 DECLINLINE(RTSEL) ASMGetES(void)239 {240 RTSEL SelES;241 # if RT_INLINE_ASM_GNU_STYLE242 __asm__ __volatile__("movw %%es, %0\n\t" : "=r" (SelES));243 # else244 __asm245 {246 mov ax, es247 mov [SelES], ax248 }249 # endif250 return SelES;251 }252 #endif253 254 255 /**256 * Get the FS register.257 * @returns FS.258 */259 #if RT_INLINE_ASM_EXTERNAL260 DECLASM(RTSEL) ASMGetFS(void);261 #else262 DECLINLINE(RTSEL) ASMGetFS(void)263 {264 RTSEL SelFS;265 # if RT_INLINE_ASM_GNU_STYLE266 __asm__ __volatile__("movw %%fs, %0\n\t" : "=r" (SelFS));267 # else268 __asm269 {270 mov ax, fs271 mov [SelFS], ax272 }273 # endif274 return SelFS;275 }276 # endif277 278 279 /**280 * Get the GS register.281 * @returns GS.282 */283 #if RT_INLINE_ASM_EXTERNAL284 DECLASM(RTSEL) ASMGetGS(void);285 #else286 DECLINLINE(RTSEL) ASMGetGS(void)287 {288 RTSEL SelGS;289 # if RT_INLINE_ASM_GNU_STYLE290 __asm__ __volatile__("movw %%gs, %0\n\t" : "=r" (SelGS));291 # else292 __asm293 {294 mov ax, gs295 mov [SelGS], ax296 }297 # endif298 return SelGS;299 }300 #endif301 302 303 /**304 * Get the SS register.305 * @returns SS.306 */307 #if RT_INLINE_ASM_EXTERNAL308 DECLASM(RTSEL) ASMGetSS(void);309 #else310 DECLINLINE(RTSEL) ASMGetSS(void)311 {312 RTSEL SelSS;313 # if RT_INLINE_ASM_GNU_STYLE314 __asm__ __volatile__("movw %%ss, %0\n\t" : "=r" (SelSS));315 # else316 __asm317 {318 mov ax, ss319 mov [SelSS], ax320 }321 # endif322 return SelSS;323 }324 #endif325 326 327 /**328 * Get the TR register.329 * @returns TR.330 */331 #if RT_INLINE_ASM_EXTERNAL332 DECLASM(RTSEL) ASMGetTR(void);333 #else334 DECLINLINE(RTSEL) ASMGetTR(void)335 {336 RTSEL SelTR;337 # if RT_INLINE_ASM_GNU_STYLE338 __asm__ __volatile__("str %w0\n\t" : "=r" (SelTR));339 # else340 __asm341 {342 str ax343 mov [SelTR], ax344 }345 # endif346 return SelTR;347 }348 #endif349 350 351 /**352 * Get the [RE]FLAGS register.353 * @returns [RE]FLAGS.354 */355 #if RT_INLINE_ASM_EXTERNAL356 DECLASM(RTCCUINTREG) ASMGetFlags(void);357 #else358 DECLINLINE(RTCCUINTREG) ASMGetFlags(void)359 {360 RTCCUINTREG uFlags;361 # if RT_INLINE_ASM_GNU_STYLE362 # ifdef RT_ARCH_AMD64363 __asm__ __volatile__("pushfq\n\t"364 "popq %0\n\t"365 : "=r" (uFlags));366 # else367 __asm__ __volatile__("pushfl\n\t"368 "popl %0\n\t"369 : "=r" (uFlags));370 # endif371 # else372 __asm373 {374 # ifdef RT_ARCH_AMD64375 pushfq376 pop [uFlags]377 # else378 pushfd379 pop [uFlags]380 # endif381 }382 # endif383 return uFlags;384 }385 #endif386 387 388 /**389 * Set the [RE]FLAGS register.390 * @param uFlags The new [RE]FLAGS value.391 */392 #if RT_INLINE_ASM_EXTERNAL393 DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);394 #else395 DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)396 {397 # if RT_INLINE_ASM_GNU_STYLE398 # ifdef RT_ARCH_AMD64399 __asm__ __volatile__("pushq %0\n\t"400 "popfq\n\t"401 : : "g" (uFlags));402 # else403 __asm__ __volatile__("pushl %0\n\t"404 "popfl\n\t"405 : : "g" (uFlags));406 # endif407 # else408 __asm409 {410 # ifdef RT_ARCH_AMD64411 push [uFlags]412 popfq413 # else414 push [uFlags]415 popfd416 # endif417 }418 # endif419 }420 #endif421 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_INTRIN429 DECLASM(uint64_t) ASMReadTSC(void);430 #else431 DECLINLINE(uint64_t) ASMReadTSC(void)432 {433 RTUINT64U u;434 # if RT_INLINE_ASM_GNU_STYLE435 __asm__ __volatile__("rdtsc\n\t" : "=a" (u.s.Lo), "=d" (u.s.Hi));436 # else437 # if RT_INLINE_ASM_USES_INTRIN438 u.u = __rdtsc();439 # else440 __asm441 {442 rdtsc443 mov [u.s.Lo], eax444 mov [u.s.Hi], edx445 }446 # endif447 # endif448 return u.u;449 }450 #endif451 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_INTRIN464 DECLASM(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);465 #else466 DECLINLINE(void) ASMCpuId(uint32_t uOperator, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX)467 {468 # if RT_INLINE_ASM_GNU_STYLE469 # ifdef RT_ARCH_AMD64470 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 # else482 __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 # endif491 492 # elif RT_INLINE_ASM_USES_INTRIN493 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 # else501 uint32_t uEAX;502 uint32_t uEBX;503 uint32_t uECX;504 uint32_t uEDX;505 __asm506 {507 push ebx508 mov eax, [uOperator]509 cpuid510 mov [uEAX], eax511 mov [uEBX], ebx512 mov [uECX], ecx513 mov [uEDX], edx514 pop ebx515 }516 *(uint32_t *)pvEAX = uEAX;517 *(uint32_t *)pvEBX = uEBX;518 *(uint32_t *)pvECX = uECX;519 *(uint32_t *)pvEDX = uEDX;520 # endif521 }522 #endif523 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 index531 * @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_INTRIN538 DECLASM(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void *pvEAX, void *pvEBX, void *pvECX, void *pvEDX);539 #else540 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_STYLE543 # ifdef RT_ARCH_AMD64544 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 # else557 __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 # endif567 568 # elif RT_INLINE_ASM_USES_INTRIN569 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 # else578 uint32_t uEAX;579 uint32_t uEBX;580 uint32_t uECX;581 uint32_t uEDX;582 __asm583 {584 push ebx585 mov eax, [uOperator]586 mov ecx, [uIdxECX]587 cpuid588 mov [uEAX], eax589 mov [uEBX], ebx590 mov [uECX], ecx591 mov [uEDX], edx592 pop ebx593 }594 *(uint32_t *)pvEAX = uEAX;595 *(uint32_t *)pvEBX = uEBX;596 *(uint32_t *)pvECX = uECX;597 *(uint32_t *)pvEDX = uEDX;598 # endif599 }600 #endif601 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_INTRIN612 DECLASM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void *pvECX, void *pvEDX);613 #else614 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 #endif620 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_INTRIN629 DECLASM(uint32_t) ASMCpuId_EDX(uint32_t uOperator);630 #else631 DECLINLINE(uint32_t) ASMCpuId_EDX(uint32_t uOperator)632 {633 RTCCUINTREG xDX;634 # if RT_INLINE_ASM_GNU_STYLE635 # ifdef RT_ARCH_AMD64636 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 # else651 __asm__ ("cpuid"652 : "=a" (uOperator),653 "=d" (xDX)654 : "0" (uOperator)655 : "ebx", "ecx");656 # endif657 658 # elif RT_INLINE_ASM_USES_INTRIN659 int aInfo[4];660 __cpuid(aInfo, uOperator);661 xDX = aInfo[3];662 663 # else664 __asm665 {666 push ebx667 mov eax, [uOperator]668 cpuid669 mov [xDX], edx670 pop ebx671 }672 # endif673 return (uint32_t)xDX;674 }675 #endif676 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_INTRIN685 DECLASM(uint32_t) ASMCpuId_ECX(uint32_t uOperator);686 #else687 DECLINLINE(uint32_t) ASMCpuId_ECX(uint32_t uOperator)688 {689 RTCCUINTREG xCX;690 # if RT_INLINE_ASM_GNU_STYLE691 # ifdef RT_ARCH_AMD64692 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 # else707 __asm__ ("cpuid"708 : "=a" (uOperator),709 "=c" (xCX)710 : "0" (uOperator)711 : "ebx", "edx");712 713 # endif714 715 # elif RT_INLINE_ASM_USES_INTRIN716 int aInfo[4];717 __cpuid(aInfo, uOperator);718 xCX = aInfo[2];719 720 # else721 __asm722 {723 push ebx724 mov eax, [uOperator]725 cpuid726 mov [xCX], ecx727 pop ebx728 }729 # endif730 return (uint32_t)xCX;731 }732 #endif733 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_AMD64743 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_STYLE747 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 # else763 __asm764 {765 pushfd766 pop eax767 mov ebx, eax768 xor eax, 0200000h769 push eax770 popfd771 pushfd772 pop eax773 cmp eax, ebx774 setne fRet775 push ebx776 popfd777 }778 # endif779 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_INTRIN790 DECLASM(uint8_t) ASMGetApicId(void);791 #else792 DECLINLINE(uint8_t) ASMGetApicId(void)793 {794 RTCCUINTREG xBX;795 # if RT_INLINE_ASM_GNU_STYLE796 # ifdef RT_ARCH_AMD64797 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 # else813 RTCCUINTREG uSpill;814 __asm__ ("cpuid"815 : "=a" (uSpill),816 "=b" (xBX)817 : "0" (1)818 : "ecx", "edx");819 # endif820 821 # elif RT_INLINE_ASM_USES_INTRIN822 int aInfo[4];823 __cpuid(aInfo, 1);824 xBX = aInfo[1];825 826 # else827 __asm828 {829 push ebx830 mov eax, 1831 cpuid832 mov [xBX], ebx833 pop ebx834 }835 # endif836 return (uint8_t)(xBX >> 24);837 }838 #endif839 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) == 0xf910 ? ((uEAX >> 20) & 0x7f) + 0xf911 : ((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) == 0xf938 ? ((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_INTRIN975 DECLASM(RTCCUINTREG) ASMGetCR0(void);976 #else977 DECLINLINE(RTCCUINTREG) ASMGetCR0(void)978 {979 RTCCUINTREG uCR0;980 # if RT_INLINE_ASM_USES_INTRIN981 uCR0 = __readcr0();982 983 # elif RT_INLINE_ASM_GNU_STYLE984 # ifdef RT_ARCH_AMD64985 __asm__ __volatile__("movq %%cr0, %0\t\n" : "=r" (uCR0));986 # else987 __asm__ __volatile__("movl %%cr0, %0\t\n" : "=r" (uCR0));988 # endif989 # else990 __asm991 {992 # ifdef RT_ARCH_AMD64993 mov rax, cr0994 mov [uCR0], rax995 # else996 mov eax, cr0997 mov [uCR0], eax998 # endif999 }1000 # endif1001 return uCR0;1002 }1003 #endif1004 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_INTRIN1011 DECLASM(void) ASMSetCR0(RTCCUINTREG uCR0);1012 #else1013 DECLINLINE(void) ASMSetCR0(RTCCUINTREG uCR0)1014 {1015 # if RT_INLINE_ASM_USES_INTRIN1016 __writecr0(uCR0);1017 1018 # elif RT_INLINE_ASM_GNU_STYLE1019 # ifdef RT_ARCH_AMD641020 __asm__ __volatile__("movq %0, %%cr0\n\t" :: "r" (uCR0));1021 # else1022 __asm__ __volatile__("movl %0, %%cr0\n\t" :: "r" (uCR0));1023 # endif1024 # else1025 __asm1026 {1027 # ifdef RT_ARCH_AMD641028 mov rax, [uCR0]1029 mov cr0, rax1030 # else1031 mov eax, [uCR0]1032 mov cr0, eax1033 # endif1034 }1035 # endif1036 }1037 #endif1038 1039 1040 /**1041 * Get cr2.1042 * @returns cr2.1043 */1044 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1045 DECLASM(RTCCUINTREG) ASMGetCR2(void);1046 #else1047 DECLINLINE(RTCCUINTREG) ASMGetCR2(void)1048 {1049 RTCCUINTREG uCR2;1050 # if RT_INLINE_ASM_USES_INTRIN1051 uCR2 = __readcr2();1052 1053 # elif RT_INLINE_ASM_GNU_STYLE1054 # ifdef RT_ARCH_AMD641055 __asm__ __volatile__("movq %%cr2, %0\t\n" : "=r" (uCR2));1056 # else1057 __asm__ __volatile__("movl %%cr2, %0\t\n" : "=r" (uCR2));1058 # endif1059 # else1060 __asm1061 {1062 # ifdef RT_ARCH_AMD641063 mov rax, cr21064 mov [uCR2], rax1065 # else1066 mov eax, cr21067 mov [uCR2], eax1068 # endif1069 }1070 # endif1071 return uCR2;1072 }1073 #endif1074 1075 1076 /**1077 * Sets the CR2 register.1078 * @param uCR2 The new CR0 value.1079 */1080 #if RT_INLINE_ASM_EXTERNAL1081 DECLASM(void) ASMSetCR2(RTCCUINTREG uCR2);1082 #else1083 DECLINLINE(void) ASMSetCR2(RTCCUINTREG uCR2)1084 {1085 # if RT_INLINE_ASM_GNU_STYLE1086 # ifdef RT_ARCH_AMD641087 __asm__ __volatile__("movq %0, %%cr2\n\t" :: "r" (uCR2));1088 # else1089 __asm__ __volatile__("movl %0, %%cr2\n\t" :: "r" (uCR2));1090 # endif1091 # else1092 __asm1093 {1094 # ifdef RT_ARCH_AMD641095 mov rax, [uCR2]1096 mov cr2, rax1097 # else1098 mov eax, [uCR2]1099 mov cr2, eax1100 # endif1101 }1102 # endif1103 }1104 #endif1105 1106 1107 /**1108 * Get cr3.1109 * @returns cr3.1110 */1111 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1112 DECLASM(RTCCUINTREG) ASMGetCR3(void);1113 #else1114 DECLINLINE(RTCCUINTREG) ASMGetCR3(void)1115 {1116 RTCCUINTREG uCR3;1117 # if RT_INLINE_ASM_USES_INTRIN1118 uCR3 = __readcr3();1119 1120 # elif RT_INLINE_ASM_GNU_STYLE1121 # ifdef RT_ARCH_AMD641122 __asm__ __volatile__("movq %%cr3, %0\t\n" : "=r" (uCR3));1123 # else1124 __asm__ __volatile__("movl %%cr3, %0\t\n" : "=r" (uCR3));1125 # endif1126 # else1127 __asm1128 {1129 # ifdef RT_ARCH_AMD641130 mov rax, cr31131 mov [uCR3], rax1132 # else1133 mov eax, cr31134 mov [uCR3], eax1135 # endif1136 }1137 # endif1138 return uCR3;1139 }1140 #endif1141 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_INTRIN1149 DECLASM(void) ASMSetCR3(RTCCUINTREG uCR3);1150 #else1151 DECLINLINE(void) ASMSetCR3(RTCCUINTREG uCR3)1152 {1153 # if RT_INLINE_ASM_USES_INTRIN1154 __writecr3(uCR3);1155 1156 # elif RT_INLINE_ASM_GNU_STYLE1157 # ifdef RT_ARCH_AMD641158 __asm__ __volatile__("movq %0, %%cr3\n\t" : : "r" (uCR3));1159 # else1160 __asm__ __volatile__("movl %0, %%cr3\n\t" : : "r" (uCR3));1161 # endif1162 # else1163 __asm1164 {1165 # ifdef RT_ARCH_AMD641166 mov rax, [uCR3]1167 mov cr3, rax1168 # else1169 mov eax, [uCR3]1170 mov cr3, eax1171 # endif1172 }1173 # endif1174 }1175 #endif1176 1177 1178 /**1179 * Reloads the CR3 register.1180 */1181 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1182 DECLASM(void) ASMReloadCR3(void);1183 #else1184 DECLINLINE(void) ASMReloadCR3(void)1185 {1186 # if RT_INLINE_ASM_USES_INTRIN1187 __writecr3(__readcr3());1188 1189 # elif RT_INLINE_ASM_GNU_STYLE1190 RTCCUINTREG u;1191 # ifdef RT_ARCH_AMD641192 __asm__ __volatile__("movq %%cr3, %0\n\t"1193 "movq %0, %%cr3\n\t"1194 : "=r" (u));1195 # else1196 __asm__ __volatile__("movl %%cr3, %0\n\t"1197 "movl %0, %%cr3\n\t"1198 : "=r" (u));1199 # endif1200 # else1201 __asm1202 {1203 # ifdef RT_ARCH_AMD641204 mov rax, cr31205 mov cr3, rax1206 # else1207 mov eax, cr31208 mov cr3, eax1209 # endif1210 }1211 # endif1212 }1213 #endif1214 1215 1216 /**1217 * Get cr4.1218 * @returns cr4.1219 */1220 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1221 DECLASM(RTCCUINTREG) ASMGetCR4(void);1222 #else1223 DECLINLINE(RTCCUINTREG) ASMGetCR4(void)1224 {1225 RTCCUINTREG uCR4;1226 # if RT_INLINE_ASM_USES_INTRIN1227 uCR4 = __readcr4();1228 1229 # elif RT_INLINE_ASM_GNU_STYLE1230 # ifdef RT_ARCH_AMD641231 __asm__ __volatile__("movq %%cr4, %0\t\n" : "=r" (uCR4));1232 # else1233 __asm__ __volatile__("movl %%cr4, %0\t\n" : "=r" (uCR4));1234 # endif1235 # else1236 __asm1237 {1238 # ifdef RT_ARCH_AMD641239 mov rax, cr41240 mov [uCR4], rax1241 # else1242 push eax /* just in case */1243 /*mov eax, cr4*/1244 _emit 0x0f1245 _emit 0x201246 _emit 0xe01247 mov [uCR4], eax1248 pop eax1249 # endif1250 }1251 # endif1252 return uCR4;1253 }1254 #endif1255 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_INTRIN1263 DECLASM(void) ASMSetCR4(RTCCUINTREG uCR4);1264 #else1265 DECLINLINE(void) ASMSetCR4(RTCCUINTREG uCR4)1266 {1267 # if RT_INLINE_ASM_USES_INTRIN1268 __writecr4(uCR4);1269 1270 # elif RT_INLINE_ASM_GNU_STYLE1271 # ifdef RT_ARCH_AMD641272 __asm__ __volatile__("movq %0, %%cr4\n\t" : : "r" (uCR4));1273 # else1274 __asm__ __volatile__("movl %0, %%cr4\n\t" : : "r" (uCR4));1275 # endif1276 # else1277 __asm1278 {1279 # ifdef RT_ARCH_AMD641280 mov rax, [uCR4]1281 mov cr4, rax1282 # else1283 mov eax, [uCR4]1284 _emit 0x0F1285 _emit 0x221286 _emit 0xE0 /* mov cr4, eax */1287 # endif1288 }1289 # endif1290 }1291 #endif1292 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_INTRIN1300 DECLASM(RTCCUINTREG) ASMGetCR8(void);1301 #else1302 DECLINLINE(RTCCUINTREG) ASMGetCR8(void)1303 {1304 # ifdef RT_ARCH_AMD641305 RTCCUINTREG uCR8;1306 # if RT_INLINE_ASM_USES_INTRIN1307 uCR8 = __readcr8();1308 1309 # elif RT_INLINE_ASM_GNU_STYLE1310 __asm__ __volatile__("movq %%cr8, %0\t\n" : "=r" (uCR8));1311 # else1312 __asm1313 {1314 mov rax, cr81315 mov [uCR8], rax1316 }1317 # endif1318 return uCR8;1319 # else /* !RT_ARCH_AMD64 */1320 return 0;1321 # endif /* !RT_ARCH_AMD64 */1322 }1323 #endif1324 1325 1326 /**1327 * Enables interrupts (EFLAGS.IF).1328 */1329 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1330 DECLASM(void) ASMIntEnable(void);1331 #else1332 DECLINLINE(void) ASMIntEnable(void)1333 {1334 # if RT_INLINE_ASM_GNU_STYLE1335 __asm("sti\n");1336 # elif RT_INLINE_ASM_USES_INTRIN1337 _enable();1338 # else1339 __asm sti1340 # endif1341 }1342 #endif1343 1344 1345 /**1346 * Disables interrupts (!EFLAGS.IF).1347 */1348 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1349 DECLASM(void) ASMIntDisable(void);1350 #else1351 DECLINLINE(void) ASMIntDisable(void)1352 {1353 # if RT_INLINE_ASM_GNU_STYLE1354 __asm("cli\n");1355 # elif RT_INLINE_ASM_USES_INTRIN1356 _disable();1357 # else1358 __asm cli1359 # endif1360 }1361 #endif1362 1363 1364 /**1365 * Disables interrupts and returns previous xFLAGS.1366 */1367 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1368 DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);1369 #else1370 DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)1371 {1372 RTCCUINTREG xFlags;1373 # if RT_INLINE_ASM_GNU_STYLE1374 # ifdef RT_ARCH_AMD641375 __asm__ __volatile__("pushfq\n\t"1376 "cli\n\t"1377 "popq %0\n\t"1378 : "=r" (xFlags));1379 # else1380 __asm__ __volatile__("pushfl\n\t"1381 "cli\n\t"1382 "popl %0\n\t"1383 : "=r" (xFlags));1384 # endif1385 # elif RT_INLINE_ASM_USES_INTRIN && !defined(RT_ARCH_X86)1386 xFlags = ASMGetFlags();1387 _disable();1388 # else1389 __asm {1390 pushfd1391 cli1392 pop [xFlags]1393 }1394 # endif1395 return xFlags;1396 }1397 #endif1398 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_EXTERNAL1416 DECLASM(void) ASMHalt(void);1417 #else1418 DECLINLINE(void) ASMHalt(void)1419 {1420 # if RT_INLINE_ASM_GNU_STYLE1421 __asm__ __volatile__("hlt\n\t");1422 # else1423 __asm {1424 hlt1425 }1426 # endif1427 }1428 #endif1429 1430 1431 /**1432 * The PAUSE variant of NOP for helping hyperthreaded CPUs detecing spin locks.1433 */1434 #if RT_INLINE_ASM_EXTERNAL1435 DECLASM(void) ASMNopPause(void);1436 #else1437 DECLINLINE(void) ASMNopPause(void)1438 {1439 # if RT_INLINE_ASM_GNU_STYLE1440 __asm__ __volatile__(".byte 0xf3,0x90\n\t");1441 # else1442 __asm {1443 _emit 0f3h1444 _emit 090h1445 }1446 # endif1447 }1448 #endif1449 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_INTRIN1458 DECLASM(uint64_t) ASMRdMsr(uint32_t uRegister);1459 #else1460 DECLINLINE(uint64_t) ASMRdMsr(uint32_t uRegister)1461 {1462 RTUINT64U u;1463 # if RT_INLINE_ASM_GNU_STYLE1464 __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_INTRIN1470 u.u = __readmsr(uRegister);1471 1472 # else1473 __asm1474 {1475 mov ecx, [uRegister]1476 rdmsr1477 mov [u.s.Lo], eax1478 mov [u.s.Hi], edx1479 }1480 # endif1481 1482 return u.u;1483 }1484 #endif1485 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_INTRIN1495 DECLASM(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val);1496 #else1497 DECLINLINE(void) ASMWrMsr(uint32_t uRegister, uint64_t u64Val)1498 {1499 RTUINT64U u;1500 1501 u.u = u64Val;1502 # if RT_INLINE_ASM_GNU_STYLE1503 __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_INTRIN1509 __writemsr(uRegister, u.u);1510 1511 # else1512 __asm1513 {1514 mov ecx, [uRegister]1515 mov edx, [u.s.Hi]1516 mov eax, [u.s.Lo]1517 wrmsr1518 }1519 # endif1520 }1521 #endif1522 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_INTRIN1531 DECLASM(uint32_t) ASMRdMsr_Low(uint32_t uRegister);1532 #else1533 DECLINLINE(uint32_t) ASMRdMsr_Low(uint32_t uRegister)1534 {1535 uint32_t u32;1536 # if RT_INLINE_ASM_GNU_STYLE1537 __asm__ __volatile__("rdmsr\n\t"1538 : "=a" (u32)1539 : "c" (uRegister)1540 : "edx");1541 1542 # elif RT_INLINE_ASM_USES_INTRIN1543 u32 = (uint32_t)__readmsr(uRegister);1544 1545 #else1546 __asm1547 {1548 mov ecx, [uRegister]1549 rdmsr1550 mov [u32], eax1551 }1552 # endif1553 1554 return u32;1555 }1556 #endif1557 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_INTRIN1566 DECLASM(uint32_t) ASMRdMsr_High(uint32_t uRegister);1567 #else1568 DECLINLINE(uint32_t) ASMRdMsr_High(uint32_t uRegister)1569 {1570 uint32_t u32;1571 # if RT_INLINE_ASM_GNU_STYLE1572 __asm__ __volatile__("rdmsr\n\t"1573 : "=d" (u32)1574 : "c" (uRegister)1575 : "eax");1576 1577 # elif RT_INLINE_ASM_USES_INTRIN1578 u32 = (uint32_t)(__readmsr(uRegister) >> 32);1579 1580 # else1581 __asm1582 {1583 mov ecx, [uRegister]1584 rdmsr1585 mov [u32], edx1586 }1587 # endif1588 1589 return u32;1590 }1591 #endif1592 1593 1594 /**1595 * Gets dr0.1596 *1597 * @returns dr0.1598 */1599 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1600 DECLASM(RTCCUINTREG) ASMGetDR0(void);1601 #else1602 DECLINLINE(RTCCUINTREG) ASMGetDR0(void)1603 {1604 RTCCUINTREG uDR0;1605 # if RT_INLINE_ASM_USES_INTRIN1606 uDR0 = __readdr(0);1607 # elif RT_INLINE_ASM_GNU_STYLE1608 # ifdef RT_ARCH_AMD641609 __asm__ __volatile__("movq %%dr0, %0\n\t" : "=r" (uDR0));1610 # else1611 __asm__ __volatile__("movl %%dr0, %0\n\t" : "=r" (uDR0));1612 # endif1613 # else1614 __asm1615 {1616 # ifdef RT_ARCH_AMD641617 mov rax, dr01618 mov [uDR0], rax1619 # else1620 mov eax, dr01621 mov [uDR0], eax1622 # endif1623 }1624 # endif1625 return uDR0;1626 }1627 #endif1628 1629 1630 /**1631 * Gets dr1.1632 *1633 * @returns dr1.1634 */1635 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1636 DECLASM(RTCCUINTREG) ASMGetDR1(void);1637 #else1638 DECLINLINE(RTCCUINTREG) ASMGetDR1(void)1639 {1640 RTCCUINTREG uDR1;1641 # if RT_INLINE_ASM_USES_INTRIN1642 uDR1 = __readdr(1);1643 # elif RT_INLINE_ASM_GNU_STYLE1644 # ifdef RT_ARCH_AMD641645 __asm__ __volatile__("movq %%dr1, %0\n\t" : "=r" (uDR1));1646 # else1647 __asm__ __volatile__("movl %%dr1, %0\n\t" : "=r" (uDR1));1648 # endif1649 # else1650 __asm1651 {1652 # ifdef RT_ARCH_AMD641653 mov rax, dr11654 mov [uDR1], rax1655 # else1656 mov eax, dr11657 mov [uDR1], eax1658 # endif1659 }1660 # endif1661 return uDR1;1662 }1663 #endif1664 1665 1666 /**1667 * Gets dr2.1668 *1669 * @returns dr2.1670 */1671 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1672 DECLASM(RTCCUINTREG) ASMGetDR2(void);1673 #else1674 DECLINLINE(RTCCUINTREG) ASMGetDR2(void)1675 {1676 RTCCUINTREG uDR2;1677 # if RT_INLINE_ASM_USES_INTRIN1678 uDR2 = __readdr(2);1679 # elif RT_INLINE_ASM_GNU_STYLE1680 # ifdef RT_ARCH_AMD641681 __asm__ __volatile__("movq %%dr2, %0\n\t" : "=r" (uDR2));1682 # else1683 __asm__ __volatile__("movl %%dr2, %0\n\t" : "=r" (uDR2));1684 # endif1685 # else1686 __asm1687 {1688 # ifdef RT_ARCH_AMD641689 mov rax, dr21690 mov [uDR2], rax1691 # else1692 mov eax, dr21693 mov [uDR2], eax1694 # endif1695 }1696 # endif1697 return uDR2;1698 }1699 #endif1700 1701 1702 /**1703 * Gets dr3.1704 *1705 * @returns dr3.1706 */1707 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1708 DECLASM(RTCCUINTREG) ASMGetDR3(void);1709 #else1710 DECLINLINE(RTCCUINTREG) ASMGetDR3(void)1711 {1712 RTCCUINTREG uDR3;1713 # if RT_INLINE_ASM_USES_INTRIN1714 uDR3 = __readdr(3);1715 # elif RT_INLINE_ASM_GNU_STYLE1716 # ifdef RT_ARCH_AMD641717 __asm__ __volatile__("movq %%dr3, %0\n\t" : "=r" (uDR3));1718 # else1719 __asm__ __volatile__("movl %%dr3, %0\n\t" : "=r" (uDR3));1720 # endif1721 # else1722 __asm1723 {1724 # ifdef RT_ARCH_AMD641725 mov rax, dr31726 mov [uDR3], rax1727 # else1728 mov eax, dr31729 mov [uDR3], eax1730 # endif1731 }1732 # endif1733 return uDR3;1734 }1735 #endif1736 1737 1738 /**1739 * Gets dr6.1740 *1741 * @returns dr6.1742 */1743 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1744 DECLASM(RTCCUINTREG) ASMGetDR6(void);1745 #else1746 DECLINLINE(RTCCUINTREG) ASMGetDR6(void)1747 {1748 RTCCUINTREG uDR6;1749 # if RT_INLINE_ASM_USES_INTRIN1750 uDR6 = __readdr(6);1751 # elif RT_INLINE_ASM_GNU_STYLE1752 # ifdef RT_ARCH_AMD641753 __asm__ __volatile__("movq %%dr6, %0\n\t" : "=r" (uDR6));1754 # else1755 __asm__ __volatile__("movl %%dr6, %0\n\t" : "=r" (uDR6));1756 # endif1757 # else1758 __asm1759 {1760 # ifdef RT_ARCH_AMD641761 mov rax, dr61762 mov [uDR6], rax1763 # else1764 mov eax, dr61765 mov [uDR6], eax1766 # endif1767 }1768 # endif1769 return uDR6;1770 }1771 #endif1772 1773 1774 /**1775 * Reads and clears DR6.1776 *1777 * @returns DR6.1778 */1779 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1780 DECLASM(RTCCUINTREG) ASMGetAndClearDR6(void);1781 #else1782 DECLINLINE(RTCCUINTREG) ASMGetAndClearDR6(void)1783 {1784 RTCCUINTREG uDR6;1785 # if RT_INLINE_ASM_USES_INTRIN1786 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_STYLE1789 RTCCUINTREG uNewValue = 0xffff0ff0U;/* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */1790 # ifdef RT_ARCH_AMD641791 __asm__ __volatile__("movq %%dr6, %0\n\t"1792 "movq %1, %%dr6\n\t"1793 : "=r" (uDR6)1794 : "r" (uNewValue));1795 # else1796 __asm__ __volatile__("movl %%dr6, %0\n\t"1797 "movl %1, %%dr6\n\t"1798 : "=r" (uDR6)1799 : "r" (uNewValue));1800 # endif1801 # else1802 __asm1803 {1804 # ifdef RT_ARCH_AMD641805 mov rax, dr61806 mov [uDR6], rax1807 mov rcx, rax1808 mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 and 63-31 are zero. */1809 mov dr6, rcx1810 # else1811 mov eax, dr61812 mov [uDR6], eax1813 mov ecx, 0ffff0ff0h; /* 31-16 and 4-11 are 1's, 12 is zero. */1814 mov dr6, ecx1815 # endif1816 }1817 # endif1818 return uDR6;1819 }1820 #endif1821 1822 1823 /**1824 * Gets dr7.1825 *1826 * @returns dr7.1827 */1828 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1829 DECLASM(RTCCUINTREG) ASMGetDR7(void);1830 #else1831 DECLINLINE(RTCCUINTREG) ASMGetDR7(void)1832 {1833 RTCCUINTREG uDR7;1834 # if RT_INLINE_ASM_USES_INTRIN1835 uDR7 = __readdr(7);1836 # elif RT_INLINE_ASM_GNU_STYLE1837 # ifdef RT_ARCH_AMD641838 __asm__ __volatile__("movq %%dr7, %0\n\t" : "=r" (uDR7));1839 # else1840 __asm__ __volatile__("movl %%dr7, %0\n\t" : "=r" (uDR7));1841 # endif1842 # else1843 __asm1844 {1845 # ifdef RT_ARCH_AMD641846 mov rax, dr71847 mov [uDR7], rax1848 # else1849 mov eax, dr71850 mov [uDR7], eax1851 # endif1852 }1853 # endif1854 return uDR7;1855 }1856 #endif1857 1858 1859 /**1860 * Sets dr0.1861 *1862 * @param uDRVal Debug register value to write1863 */1864 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1865 DECLASM(void) ASMSetDR0(RTCCUINTREG uDRVal);1866 #else1867 DECLINLINE(void) ASMSetDR0(RTCCUINTREG uDRVal)1868 {1869 # if RT_INLINE_ASM_USES_INTRIN1870 __writedr(0, uDRVal);1871 # elif RT_INLINE_ASM_GNU_STYLE1872 # ifdef RT_ARCH_AMD641873 __asm__ __volatile__("movq %0, %%dr0\n\t" : : "r" (uDRVal));1874 # else1875 __asm__ __volatile__("movl %0, %%dr0\n\t" : : "r" (uDRVal));1876 # endif1877 # else1878 __asm1879 {1880 # ifdef RT_ARCH_AMD641881 mov rax, [uDRVal]1882 mov dr0, rax1883 # else1884 mov eax, [uDRVal]1885 mov dr0, eax1886 # endif1887 }1888 # endif1889 }1890 #endif1891 1892 1893 /**1894 * Sets dr1.1895 *1896 * @param uDRVal Debug register value to write1897 */1898 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1899 DECLASM(void) ASMSetDR1(RTCCUINTREG uDRVal);1900 #else1901 DECLINLINE(void) ASMSetDR1(RTCCUINTREG uDRVal)1902 {1903 # if RT_INLINE_ASM_USES_INTRIN1904 __writedr(1, uDRVal);1905 # elif RT_INLINE_ASM_GNU_STYLE1906 # ifdef RT_ARCH_AMD641907 __asm__ __volatile__("movq %0, %%dr1\n\t" : : "r" (uDRVal));1908 # else1909 __asm__ __volatile__("movl %0, %%dr1\n\t" : : "r" (uDRVal));1910 # endif1911 # else1912 __asm1913 {1914 # ifdef RT_ARCH_AMD641915 mov rax, [uDRVal]1916 mov dr1, rax1917 # else1918 mov eax, [uDRVal]1919 mov dr1, eax1920 # endif1921 }1922 # endif1923 }1924 #endif1925 1926 1927 /**1928 * Sets dr2.1929 *1930 * @param uDRVal Debug register value to write1931 */1932 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1933 DECLASM(void) ASMSetDR2(RTCCUINTREG uDRVal);1934 #else1935 DECLINLINE(void) ASMSetDR2(RTCCUINTREG uDRVal)1936 {1937 # if RT_INLINE_ASM_USES_INTRIN1938 __writedr(2, uDRVal);1939 # elif RT_INLINE_ASM_GNU_STYLE1940 # ifdef RT_ARCH_AMD641941 __asm__ __volatile__("movq %0, %%dr2\n\t" : : "r" (uDRVal));1942 # else1943 __asm__ __volatile__("movl %0, %%dr2\n\t" : : "r" (uDRVal));1944 # endif1945 # else1946 __asm1947 {1948 # ifdef RT_ARCH_AMD641949 mov rax, [uDRVal]1950 mov dr2, rax1951 # else1952 mov eax, [uDRVal]1953 mov dr2, eax1954 # endif1955 }1956 # endif1957 }1958 #endif1959 1960 1961 /**1962 * Sets dr3.1963 *1964 * @param uDRVal Debug register value to write1965 */1966 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN1967 DECLASM(void) ASMSetDR3(RTCCUINTREG uDRVal);1968 #else1969 DECLINLINE(void) ASMSetDR3(RTCCUINTREG uDRVal)1970 {1971 # if RT_INLINE_ASM_USES_INTRIN1972 __writedr(3, uDRVal);1973 # elif RT_INLINE_ASM_GNU_STYLE1974 # ifdef RT_ARCH_AMD641975 __asm__ __volatile__("movq %0, %%dr3\n\t" : : "r" (uDRVal));1976 # else1977 __asm__ __volatile__("movl %0, %%dr3\n\t" : : "r" (uDRVal));1978 # endif1979 # else1980 __asm1981 {1982 # ifdef RT_ARCH_AMD641983 mov rax, [uDRVal]1984 mov dr3, rax1985 # else1986 mov eax, [uDRVal]1987 mov dr3, eax1988 # endif1989 }1990 # endif1991 }1992 #endif1993 1994 1995 /**1996 * Sets dr6.1997 *1998 * @param uDRVal Debug register value to write1999 */2000 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN2001 DECLASM(void) ASMSetDR6(RTCCUINTREG uDRVal);2002 #else2003 DECLINLINE(void) ASMSetDR6(RTCCUINTREG uDRVal)2004 {2005 # if RT_INLINE_ASM_USES_INTRIN2006 __writedr(6, uDRVal);2007 # elif RT_INLINE_ASM_GNU_STYLE2008 # ifdef RT_ARCH_AMD642009 __asm__ __volatile__("movq %0, %%dr6\n\t" : : "r" (uDRVal));2010 # else2011 __asm__ __volatile__("movl %0, %%dr6\n\t" : : "r" (uDRVal));2012 # endif2013 # else2014 __asm2015 {2016 # ifdef RT_ARCH_AMD642017 mov rax, [uDRVal]2018 mov dr6, rax2019 # else2020 mov eax, [uDRVal]2021 mov dr6, eax2022 # endif2023 }2024 # endif2025 }2026 #endif2027 2028 2029 /**2030 * Sets dr7.2031 *2032 * @param uDRVal Debug register value to write2033 */2034 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN2035 DECLASM(void) ASMSetDR7(RTCCUINTREG uDRVal);2036 #else2037 DECLINLINE(void) ASMSetDR7(RTCCUINTREG uDRVal)2038 {2039 # if RT_INLINE_ASM_USES_INTRIN2040 __writedr(7, uDRVal);2041 # elif RT_INLINE_ASM_GNU_STYLE2042 # ifdef RT_ARCH_AMD642043 __asm__ __volatile__("movq %0, %%dr7\n\t" : : "r" (uDRVal));2044 # else2045 __asm__ __volatile__("movl %0, %%dr7\n\t" : : "r" (uDRVal));2046 # endif2047 # else2048 __asm2049 {2050 # ifdef RT_ARCH_AMD642051 mov rax, [uDRVal]2052 mov dr7, rax2053 # else2054 mov eax, [uDRVal]2055 mov dr7, eax2056 # endif2057 }2058 # endif2059 }2060 #endif2061 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_INTRIN2070 DECLASM(void) ASMOutU8(RTIOPORT Port, uint8_t u8);2071 #else2072 DECLINLINE(void) ASMOutU8(RTIOPORT Port, uint8_t u8)2073 {2074 # if RT_INLINE_ASM_GNU_STYLE2075 __asm__ __volatile__("outb %b1, %w0\n\t"2076 :: "Nd" (Port),2077 "a" (u8));2078 2079 # elif RT_INLINE_ASM_USES_INTRIN2080 __outbyte(Port, u8);2081 2082 # else2083 __asm2084 {2085 mov dx, [Port]2086 mov al, [u8]2087 out dx, al2088 }2089 # endif2090 }2091 #endif2092 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_INTRIN2101 DECLASM(uint8_t) ASMInU8(RTIOPORT Port);2102 #else2103 DECLINLINE(uint8_t) ASMInU8(RTIOPORT Port)2104 {2105 uint8_t u8;2106 # if RT_INLINE_ASM_GNU_STYLE2107 __asm__ __volatile__("inb %w1, %b0\n\t"2108 : "=a" (u8)2109 : "Nd" (Port));2110 2111 # elif RT_INLINE_ASM_USES_INTRIN2112 u8 = __inbyte(Port);2113 2114 # else2115 __asm2116 {2117 mov dx, [Port]2118 in al, dx2119 mov [u8], al2120 }2121 # endif2122 return u8;2123 }2124 #endif2125 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_INTRIN2134 DECLASM(void) ASMOutU16(RTIOPORT Port, uint16_t u16);2135 #else2136 DECLINLINE(void) ASMOutU16(RTIOPORT Port, uint16_t u16)2137 {2138 # if RT_INLINE_ASM_GNU_STYLE2139 __asm__ __volatile__("outw %w1, %w0\n\t"2140 :: "Nd" (Port),2141 "a" (u16));2142 2143 # elif RT_INLINE_ASM_USES_INTRIN2144 __outword(Port, u16);2145 2146 # else2147 __asm2148 {2149 mov dx, [Port]2150 mov ax, [u16]2151 out dx, ax2152 }2153 # endif2154 }2155 #endif2156 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_INTRIN2165 DECLASM(uint16_t) ASMInU16(RTIOPORT Port);2166 #else2167 DECLINLINE(uint16_t) ASMInU16(RTIOPORT Port)2168 {2169 uint16_t u16;2170 # if RT_INLINE_ASM_GNU_STYLE2171 __asm__ __volatile__("inw %w1, %w0\n\t"2172 : "=a" (u16)2173 : "Nd" (Port));2174 2175 # elif RT_INLINE_ASM_USES_INTRIN2176 u16 = __inword(Port);2177 2178 # else2179 __asm2180 {2181 mov dx, [Port]2182 in ax, dx2183 mov [u16], ax2184 }2185 # endif2186 return u16;2187 }2188 #endif2189 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_INTRIN2198 DECLASM(void) ASMOutU32(RTIOPORT Port, uint32_t u32);2199 #else2200 DECLINLINE(void) ASMOutU32(RTIOPORT Port, uint32_t u32)2201 {2202 # if RT_INLINE_ASM_GNU_STYLE2203 __asm__ __volatile__("outl %1, %w0\n\t"2204 :: "Nd" (Port),2205 "a" (u32));2206 2207 # elif RT_INLINE_ASM_USES_INTRIN2208 __outdword(Port, u32);2209 2210 # else2211 __asm2212 {2213 mov dx, [Port]2214 mov eax, [u32]2215 out dx, eax2216 }2217 # endif2218 }2219 #endif2220 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_INTRIN2229 DECLASM(uint32_t) ASMInU32(RTIOPORT Port);2230 #else2231 DECLINLINE(uint32_t) ASMInU32(RTIOPORT Port)2232 {2233 uint32_t u32;2234 # if RT_INLINE_ASM_GNU_STYLE2235 __asm__ __volatile__("inl %w1, %0\n\t"2236 : "=a" (u32)2237 : "Nd" (Port));2238 2239 # elif RT_INLINE_ASM_USES_INTRIN2240 u32 = __indword(Port);2241 2242 # else2243 __asm2244 {2245 mov dx, [Port]2246 in eax, dx2247 mov [u32], eax2248 }2249 # endif2250 return u32;2251 }2252 #endif2253 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_INTRIN2263 DECLASM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c);2264 #else2265 DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const *pau8, size_t c)2266 {2267 # if RT_INLINE_ASM_GNU_STYLE2268 __asm__ __volatile__("rep; outsb\n\t"2269 : "+S" (pau8),2270 "+c" (c)2271 : "d" (Port));2272 2273 # elif RT_INLINE_ASM_USES_INTRIN2274 __outbytestring(Port, (unsigned char *)pau8, (unsigned long)c);2275 2276 # else2277 __asm2278 {2279 mov dx, [Port]2280 mov ecx, [c]2281 mov eax, [pau8]2282 xchg esi, eax2283 rep outsb2284 xchg esi, eax2285 }2286 # endif2287 }2288 #endif2289 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_INTRIN2299 DECLASM(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c);2300 #else2301 DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t *pau8, size_t c)2302 {2303 # if RT_INLINE_ASM_GNU_STYLE2304 __asm__ __volatile__("rep; insb\n\t"2305 : "+D" (pau8),2306 "+c" (c)2307 : "d" (Port));2308 2309 # elif RT_INLINE_ASM_USES_INTRIN2310 __inbytestring(Port, pau8, (unsigned long)c);2311 2312 # else2313 __asm2314 {2315 mov dx, [Port]2316 mov ecx, [c]2317 mov eax, [pau8]2318 xchg edi, eax2319 rep insb2320 xchg edi, eax2321 }2322 # endif2323 }2324 #endif2325 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_INTRIN2335 DECLASM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c);2336 #else2337 DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const *pau16, size_t c)2338 {2339 # if RT_INLINE_ASM_GNU_STYLE2340 __asm__ __volatile__("rep; outsw\n\t"2341 : "+S" (pau16),2342 "+c" (c)2343 : "d" (Port));2344 2345 # elif RT_INLINE_ASM_USES_INTRIN2346 __outwordstring(Port, (unsigned short *)pau16, (unsigned long)c);2347 2348 # else2349 __asm2350 {2351 mov dx, [Port]2352 mov ecx, [c]2353 mov eax, [pau16]2354 xchg esi, eax2355 rep outsw2356 xchg esi, eax2357 }2358 # endif2359 }2360 #endif2361 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_INTRIN2371 DECLASM(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c);2372 #else2373 DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t *pau16, size_t c)2374 {2375 # if RT_INLINE_ASM_GNU_STYLE2376 __asm__ __volatile__("rep; insw\n\t"2377 : "+D" (pau16),2378 "+c" (c)2379 : "d" (Port));2380 2381 # elif RT_INLINE_ASM_USES_INTRIN2382 __inwordstring(Port, pau16, (unsigned long)c);2383 2384 # else2385 __asm2386 {2387 mov dx, [Port]2388 mov ecx, [c]2389 mov eax, [pau16]2390 xchg edi, eax2391 rep insw2392 xchg edi, eax2393 }2394 # endif2395 }2396 #endif2397 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_INTRIN2407 DECLASM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c);2408 #else2409 DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const *pau32, size_t c)2410 {2411 # if RT_INLINE_ASM_GNU_STYLE2412 __asm__ __volatile__("rep; outsl\n\t"2413 : "+S" (pau32),2414 "+c" (c)2415 : "d" (Port));2416 2417 # elif RT_INLINE_ASM_USES_INTRIN2418 __outdwordstring(Port, (unsigned long *)pau32, (unsigned long)c);2419 2420 # else2421 __asm2422 {2423 mov dx, [Port]2424 mov ecx, [c]2425 mov eax, [pau32]2426 xchg esi, eax2427 rep outsd2428 xchg esi, eax2429 }2430 # endif2431 }2432 #endif2433 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_INTRIN2443 DECLASM(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c);2444 #else2445 DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t *pau32, size_t c)2446 {2447 # if RT_INLINE_ASM_GNU_STYLE2448 __asm__ __volatile__("rep; insl\n\t"2449 : "+D" (pau32),2450 "+c" (c)2451 : "d" (Port));2452 2453 # elif RT_INLINE_ASM_USES_INTRIN2454 __indwordstring(Port, (unsigned long *)pau32, (unsigned long)c);2455 2456 # else2457 __asm2458 {2459 mov dx, [Port]2460 mov ecx, [c]2461 mov eax, [pau32]2462 xchg edi, eax2463 rep insd2464 xchg edi, eax2465 }2466 # endif2467 }2468 #endif2469 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_INTRIN2477 DECLASM(void) ASMInvalidatePage(void *pv);2478 #else2479 DECLINLINE(void) ASMInvalidatePage(void *pv)2480 {2481 # if RT_INLINE_ASM_USES_INTRIN2482 __invlpg(pv);2483 2484 # elif RT_INLINE_ASM_GNU_STYLE2485 __asm__ __volatile__("invlpg %0\n\t"2486 : : "m" (*(uint8_t *)pv));2487 # else2488 __asm2489 {2490 # ifdef RT_ARCH_AMD642491 mov rax, [pv]2492 invlpg [rax]2493 # else2494 mov eax, [pv]2495 invlpg [eax]2496 # endif2497 }2498 # endif2499 }2500 #endif2501 2502 2503 /**2504 * Write back the internal caches and invalidate them.2505 */2506 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN2507 DECLASM(void) ASMWriteBackAndInvalidateCaches(void);2508 #else2509 DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)2510 {2511 # if RT_INLINE_ASM_USES_INTRIN2512 __wbinvd();2513 2514 # elif RT_INLINE_ASM_GNU_STYLE2515 __asm__ __volatile__("wbinvd");2516 # else2517 __asm2518 {2519 wbinvd2520 }2521 # endif2522 }2523 #endif2524 2525 2526 /**2527 * Invalidate internal and (perhaps) external caches without first2528 * flushing dirty cache lines. Use with extreme care.2529 */2530 #if RT_INLINE_ASM_EXTERNAL2531 DECLASM(void) ASMInvalidateInternalCaches(void);2532 #else2533 DECLINLINE(void) ASMInvalidateInternalCaches(void)2534 {2535 # if RT_INLINE_ASM_GNU_STYLE2536 __asm__ __volatile__("invd");2537 # else2538 __asm2539 {2540 invd2541 }2542 # endif2543 }2544 #endif2545 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_STYLE2554 __asm__ __volatile__ (".byte 0x0f,0xae,0xf0\n\t");2555 #elif RT_INLINE_ASM_USES_INTRIN2556 _mm_mfence();2557 #else2558 __asm2559 {2560 _emit 0x0f2561 _emit 0xae2562 _emit 0xf02563 }2564 #endif2565 }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_STYLE2575 __asm__ __volatile__ (".byte 0x0f,0xae,0xf8\n\t");2576 #elif RT_INLINE_ASM_USES_INTRIN2577 _mm_sfence();2578 #else2579 __asm2580 {2581 _emit 0x0f2582 _emit 0xae2583 _emit 0xf82584 }2585 #endif2586 }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_STYLE2596 __asm__ __volatile__ (".byte 0x0f,0xae,0xe8\n\t");2597 #elif RT_INLINE_ASM_USES_INTRIN2598 _mm_lfence();2599 #else2600 __asm2601 {2602 _emit 0x0f2603 _emit 0xae2604 _emit 0xe82605 }2606 #endif2607 }2608 2609 2610 /** @name Interger Math Optimizations2611 34 * @{ */ 2612 35 … … 2616 39 * @returns u32F1 * u32F2. 2617 40 */ 2618 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)41 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2619 42 DECLASM(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2); 2620 43 #else 2621 44 DECLINLINE(uint64_t) ASMMult2xU32RetU64(uint32_t u32F1, uint32_t u32F2) 2622 45 { 2623 # ifdef RT_ARCH_AMD64 2624 return (uint64_t)u32F1 * u32F2; 2625 # else /* !RT_ARCH_AMD64 */ 46 # ifdef RT_ARCH_X86 2626 47 uint64_t u64; 2627 48 # if RT_INLINE_ASM_GNU_STYLE … … 2640 61 # endif 2641 62 return u64; 2642 # endif /* !RT_ARCH_AMD64 */ 63 # else /* generic: */ 64 return (uint64_t)u32F1 * u32F2; 65 # endif 2643 66 } 2644 67 #endif … … 2650 73 * @returns u32F1 * u32F2. 2651 74 */ 2652 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)75 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2653 76 DECLASM(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2); 2654 77 #else 2655 78 DECLINLINE(int64_t) ASMMult2xS32RetS64(int32_t i32F1, int32_t i32F2) 2656 79 { 2657 # ifdef RT_ARCH_AMD64 2658 return (int64_t)i32F1 * i32F2; 2659 # else /* !RT_ARCH_AMD64 */ 80 # ifdef RT_ARCH_X86 2660 81 int64_t i64; 2661 82 # if RT_INLINE_ASM_GNU_STYLE … … 2674 95 # endif 2675 96 return i64; 2676 # endif /* !RT_ARCH_AMD64 */ 97 # else /* generic: */ 98 return (int64_t)i32F1 * i32F2; 99 # endif 2677 100 } 2678 101 #endif … … 2684 107 * @returns u64 / u32. 2685 108 */ 2686 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)109 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2687 110 DECLASM(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32); 2688 111 #else 2689 112 DECLINLINE(uint32_t) ASMDivU64ByU32RetU32(uint64_t u64, uint32_t u32) 2690 113 { 2691 # ifdef RT_ARCH_AMD64 2692 return (uint32_t)(u64 / u32); 2693 # else /* !RT_ARCH_AMD64 */ 114 # ifdef RT_ARCH_X86 2694 115 # if RT_INLINE_ASM_GNU_STYLE 2695 116 RTCCUINTREG uDummy; … … 2708 129 # endif 2709 130 return u32; 2710 # endif /* !RT_ARCH_AMD64 */ 131 # else /* generic: */ 132 return (uint32_t)(u64 / u32); 133 # endif 2711 134 } 2712 135 #endif … … 2718 141 * @returns u64 / u32. 2719 142 */ 2720 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)143 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2721 144 DECLASM(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32); 2722 145 #else 2723 146 DECLINLINE(int32_t) ASMDivS64ByS32RetS32(int64_t i64, int32_t i32) 2724 147 { 2725 # ifdef RT_ARCH_AMD64 2726 return (int32_t)(i64 / i32); 2727 # else /* !RT_ARCH_AMD64 */ 148 # ifdef RT_ARCH_X86 2728 149 # if RT_INLINE_ASM_GNU_STYLE 2729 150 RTCCUINTREG iDummy; … … 2742 163 # endif 2743 164 return i32; 2744 # endif /* !RT_ARCH_AMD64 */ 165 # else /* generic: */ 166 return (int32_t)(i64 / i32); 167 # endif 2745 168 } 2746 169 #endif … … 2755 178 * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash. 2756 179 */ 2757 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)180 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2758 181 DECLASM(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32); 2759 182 #else 2760 183 DECLINLINE(uint32_t) ASMModU64ByU32RetU32(uint64_t u64, uint32_t u32) 2761 184 { 2762 # ifdef RT_ARCH_AMD64 2763 return (uint32_t)(u64 % u32); 2764 # else /* !RT_ARCH_AMD64 */ 185 # ifdef RT_ARCH_X86 2765 186 # if RT_INLINE_ASM_GNU_STYLE 2766 187 RTCCUINTREG uDummy; … … 2779 200 # endif 2780 201 return u32; 2781 # endif /* !RT_ARCH_AMD64 */ 202 # else /* generic: */ 203 return (uint32_t)(u64 % u32); 204 # endif 2782 205 } 2783 206 #endif … … 2792 215 * @remarks It is important that the result is <= UINT32_MAX or we'll overflow and crash. 2793 216 */ 2794 #if RT_INLINE_ASM_EXTERNAL && !defined(RT_ARCH_AMD64)217 #if RT_INLINE_ASM_EXTERNAL && defined(RT_ARCH_X86) 2795 218 DECLASM(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32); 2796 219 #else 2797 220 DECLINLINE(int32_t) ASMModS64ByS32RetS32(int64_t i64, int32_t i32) 2798 221 { 2799 # ifdef RT_ARCH_AMD64 2800 return (int32_t)(i64 % i32); 2801 # else /* !RT_ARCH_AMD64 */ 222 # ifdef RT_ARCH_X86 2802 223 # if RT_INLINE_ASM_GNU_STYLE 2803 224 RTCCUINTREG iDummy; … … 2816 237 # endif 2817 238 return i32; 2818 # endif /* !RT_ARCH_AMD64 */ 239 # else /* generic: */ 240 return (int32_t)(i64 % i32); 241 # endif 2819 242 } 2820 243 #endif … … 2831 254 * @param u32B The 32-bit value to multiple by A. 2832 255 * @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)) 2835 260 DECLASM(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C); 2836 261 #else … … 2891 316 2892 317 /** @} */ 2893 2894 /** @} */ 2895 #endif 2896 318 #endif 319
Note:
See TracChangeset
for help on using the changeset viewer.