10b57cec5SDimitry Andric /* ===-------- intrin.h ---------------------------------------------------=== 20b57cec5SDimitry Andric * 30b57cec5SDimitry Andric * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric * See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric * 70b57cec5SDimitry Andric *===-----------------------------------------------------------------------=== 80b57cec5SDimitry Andric */ 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric /* Only include this if we're compiling for the windows platform. */ 110b57cec5SDimitry Andric #ifndef _MSC_VER 120b57cec5SDimitry Andric #include_next <intrin.h> 130b57cec5SDimitry Andric #else 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #ifndef __INTRIN_H 160b57cec5SDimitry Andric #define __INTRIN_H 170b57cec5SDimitry Andric 18*0fca6ea1SDimitry Andric #include <intrin0.h> 19*0fca6ea1SDimitry Andric 200b57cec5SDimitry Andric /* First include the standard intrinsics. */ 21*0fca6ea1SDimitry Andric #if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__)) 220b57cec5SDimitry Andric #include <x86intrin.h> 230b57cec5SDimitry Andric #endif 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric #if defined(__arm__) 260b57cec5SDimitry Andric #include <armintr.h> 270b57cec5SDimitry Andric #endif 280b57cec5SDimitry Andric 29*0fca6ea1SDimitry Andric #if defined(__aarch64__) || defined(__arm64ec__) 300b57cec5SDimitry Andric #include <arm64intr.h> 310b57cec5SDimitry Andric #endif 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric /* For the definition of jmp_buf. */ 340b57cec5SDimitry Andric #if __STDC_HOSTED__ 350b57cec5SDimitry Andric #include <setjmp.h> 360b57cec5SDimitry Andric #endif 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric /* Define the default attributes for the functions in this file. */ 390b57cec5SDimitry Andric #define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) 400b57cec5SDimitry Andric 41480093f4SDimitry Andric #if __x86_64__ 42480093f4SDimitry Andric #define __LPTRINT_TYPE__ __int64 43480093f4SDimitry Andric #else 44480093f4SDimitry Andric #define __LPTRINT_TYPE__ long 45480093f4SDimitry Andric #endif 46480093f4SDimitry Andric 470b57cec5SDimitry Andric #ifdef __cplusplus 480b57cec5SDimitry Andric extern "C" { 490b57cec5SDimitry Andric #endif 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric #if defined(__MMX__) 520b57cec5SDimitry Andric /* And the random ones that aren't in those files. */ 530b57cec5SDimitry Andric __m64 _m_from_float(float); 540b57cec5SDimitry Andric float _m_to_float(__m64); 550b57cec5SDimitry Andric #endif 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric /* Other assorted instruction intrinsics. */ 580b57cec5SDimitry Andric void __addfsbyte(unsigned long, unsigned char); 590b57cec5SDimitry Andric void __addfsdword(unsigned long, unsigned long); 600b57cec5SDimitry Andric void __addfsword(unsigned long, unsigned short); 610b57cec5SDimitry Andric void __code_seg(const char *); 620b57cec5SDimitry Andric void __cpuid(int[4], int); 630b57cec5SDimitry Andric void __cpuidex(int[4], int, int); 640b57cec5SDimitry Andric __int64 __emul(int, int); 650b57cec5SDimitry Andric unsigned __int64 __emulu(unsigned int, unsigned int); 660b57cec5SDimitry Andric unsigned int __getcallerseflags(void); 670b57cec5SDimitry Andric void __halt(void); 680b57cec5SDimitry Andric unsigned char __inbyte(unsigned short); 690b57cec5SDimitry Andric void __inbytestring(unsigned short, unsigned char *, unsigned long); 700b57cec5SDimitry Andric void __incfsbyte(unsigned long); 710b57cec5SDimitry Andric void __incfsdword(unsigned long); 720b57cec5SDimitry Andric void __incfsword(unsigned long); 730b57cec5SDimitry Andric unsigned long __indword(unsigned short); 740b57cec5SDimitry Andric void __indwordstring(unsigned short, unsigned long *, unsigned long); 750b57cec5SDimitry Andric void __int2c(void); 760b57cec5SDimitry Andric void __invlpg(void *); 770b57cec5SDimitry Andric unsigned short __inword(unsigned short); 780b57cec5SDimitry Andric void __inwordstring(unsigned short, unsigned short *, unsigned long); 790b57cec5SDimitry Andric void __lidt(void *); 800b57cec5SDimitry Andric unsigned __int64 __ll_lshift(unsigned __int64, int); 810b57cec5SDimitry Andric __int64 __ll_rshift(__int64, int); 820b57cec5SDimitry Andric void __movsb(unsigned char *, unsigned char const *, size_t); 830b57cec5SDimitry Andric void __movsd(unsigned long *, unsigned long const *, size_t); 840b57cec5SDimitry Andric void __movsw(unsigned short *, unsigned short const *, size_t); 850b57cec5SDimitry Andric void __nop(void); 860b57cec5SDimitry Andric void __nvreg_restore_fence(void); 870b57cec5SDimitry Andric void __nvreg_save_fence(void); 880b57cec5SDimitry Andric void __outbyte(unsigned short, unsigned char); 890b57cec5SDimitry Andric void __outbytestring(unsigned short, unsigned char *, unsigned long); 900b57cec5SDimitry Andric void __outdword(unsigned short, unsigned long); 910b57cec5SDimitry Andric void __outdwordstring(unsigned short, unsigned long *, unsigned long); 920b57cec5SDimitry Andric void __outword(unsigned short, unsigned short); 930b57cec5SDimitry Andric void __outwordstring(unsigned short, unsigned short *, unsigned long); 940b57cec5SDimitry Andric unsigned long __readcr0(void); 950b57cec5SDimitry Andric unsigned long __readcr2(void); 96480093f4SDimitry Andric unsigned __LPTRINT_TYPE__ __readcr3(void); 970b57cec5SDimitry Andric unsigned long __readcr4(void); 980b57cec5SDimitry Andric unsigned long __readcr8(void); 990b57cec5SDimitry Andric unsigned int __readdr(unsigned int); 1000b57cec5SDimitry Andric #ifdef __i386__ 1010b57cec5SDimitry Andric unsigned char __readfsbyte(unsigned long); 1020b57cec5SDimitry Andric unsigned short __readfsword(unsigned long); 103349cc55cSDimitry Andric unsigned long __readfsdword(unsigned long); 104349cc55cSDimitry Andric unsigned __int64 __readfsqword(unsigned long); 1050b57cec5SDimitry Andric #endif 1060b57cec5SDimitry Andric unsigned __int64 __readmsr(unsigned long); 1070b57cec5SDimitry Andric unsigned __int64 __readpmc(unsigned long); 1080b57cec5SDimitry Andric unsigned long __segmentlimit(unsigned long); 1090b57cec5SDimitry Andric void __sidt(void *); 1100b57cec5SDimitry Andric void __stosb(unsigned char *, unsigned char, size_t); 1110b57cec5SDimitry Andric void __stosd(unsigned long *, unsigned long, size_t); 1120b57cec5SDimitry Andric void __stosw(unsigned short *, unsigned short, size_t); 1130b57cec5SDimitry Andric void __svm_clgi(void); 1140b57cec5SDimitry Andric void __svm_invlpga(void *, int); 1150b57cec5SDimitry Andric void __svm_skinit(int); 1160b57cec5SDimitry Andric void __svm_stgi(void); 1170b57cec5SDimitry Andric void __svm_vmload(size_t); 1180b57cec5SDimitry Andric void __svm_vmrun(size_t); 1190b57cec5SDimitry Andric void __svm_vmsave(size_t); 1200b57cec5SDimitry Andric void __ud2(void); 1210b57cec5SDimitry Andric unsigned __int64 __ull_rshift(unsigned __int64, int); 1220b57cec5SDimitry Andric void __vmx_off(void); 1230b57cec5SDimitry Andric void __vmx_vmptrst(unsigned __int64 *); 1240b57cec5SDimitry Andric void __wbinvd(void); 1250b57cec5SDimitry Andric void __writecr0(unsigned int); 126480093f4SDimitry Andric void __writecr3(unsigned __INTPTR_TYPE__); 1270b57cec5SDimitry Andric void __writecr4(unsigned int); 1280b57cec5SDimitry Andric void __writecr8(unsigned int); 1290b57cec5SDimitry Andric void __writedr(unsigned int, unsigned int); 1300b57cec5SDimitry Andric void __writefsbyte(unsigned long, unsigned char); 1310b57cec5SDimitry Andric void __writefsdword(unsigned long, unsigned long); 1320b57cec5SDimitry Andric void __writefsqword(unsigned long, unsigned __int64); 1330b57cec5SDimitry Andric void __writefsword(unsigned long, unsigned short); 1340b57cec5SDimitry Andric void __writemsr(unsigned long, unsigned __int64); 1350b57cec5SDimitry Andric void *_AddressOfReturnAddress(void); 1360b57cec5SDimitry Andric unsigned char _bittest(long const *, long); 1370b57cec5SDimitry Andric unsigned char _bittestandcomplement(long *, long); 1380b57cec5SDimitry Andric unsigned char _bittestandreset(long *, long); 1390b57cec5SDimitry Andric unsigned char _bittestandset(long *, long); 1400b57cec5SDimitry Andric void __cdecl _disable(void); 1410b57cec5SDimitry Andric void __cdecl _enable(void); 1420b57cec5SDimitry Andric long _InterlockedAddLargeStatistic(__int64 volatile *_Addend, long _Value); 1430b57cec5SDimitry Andric unsigned char _interlockedbittestandreset(long volatile *, long); 1440b57cec5SDimitry Andric unsigned char _interlockedbittestandset(long volatile *, long); 1450b57cec5SDimitry Andric void *_InterlockedCompareExchangePointer_HLEAcquire(void *volatile *, void *, 1460b57cec5SDimitry Andric void *); 1470b57cec5SDimitry Andric void *_InterlockedCompareExchangePointer_HLERelease(void *volatile *, void *, 1480b57cec5SDimitry Andric void *); 1490b57cec5SDimitry Andric long _InterlockedExchangeAdd_HLEAcquire(long volatile *, long); 1500b57cec5SDimitry Andric long _InterlockedExchangeAdd_HLERelease(long volatile *, long); 1510b57cec5SDimitry Andric __int64 _InterlockedExchangeAdd64_HLEAcquire(__int64 volatile *, __int64); 1520b57cec5SDimitry Andric __int64 _InterlockedExchangeAdd64_HLERelease(__int64 volatile *, __int64); 153349cc55cSDimitry Andric void _ReadBarrier(void); 1540b57cec5SDimitry Andric unsigned int _rorx_u32(unsigned int, const unsigned int); 1550b57cec5SDimitry Andric int _sarx_i32(int, unsigned int); 1560b57cec5SDimitry Andric #if __STDC_HOSTED__ 1570b57cec5SDimitry Andric int __cdecl _setjmp(jmp_buf); 1580b57cec5SDimitry Andric #endif 1590b57cec5SDimitry Andric unsigned int _shlx_u32(unsigned int, unsigned int); 1600b57cec5SDimitry Andric unsigned int _shrx_u32(unsigned int, unsigned int); 1610b57cec5SDimitry Andric void _Store_HLERelease(long volatile *, long); 1620b57cec5SDimitry Andric void _Store64_HLERelease(__int64 volatile *, __int64); 1630b57cec5SDimitry Andric void _StorePointer_HLERelease(void *volatile *, void *); 164349cc55cSDimitry Andric void _WriteBarrier(void); 1650b57cec5SDimitry Andric unsigned __int32 xbegin(void); 1660b57cec5SDimitry Andric void _xend(void); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric /* These additional intrinsics are turned on in x64/amd64/x86_64 mode. */ 169*0fca6ea1SDimitry Andric #if defined(__x86_64__) && !defined(__arm64ec__) 1700b57cec5SDimitry Andric void __addgsbyte(unsigned long, unsigned char); 1710b57cec5SDimitry Andric void __addgsdword(unsigned long, unsigned long); 1720b57cec5SDimitry Andric void __addgsqword(unsigned long, unsigned __int64); 1730b57cec5SDimitry Andric void __addgsword(unsigned long, unsigned short); 1740b57cec5SDimitry Andric void __faststorefence(void); 1750b57cec5SDimitry Andric void __incgsbyte(unsigned long); 1760b57cec5SDimitry Andric void __incgsdword(unsigned long); 1770b57cec5SDimitry Andric void __incgsqword(unsigned long); 1780b57cec5SDimitry Andric void __incgsword(unsigned long); 1790b57cec5SDimitry Andric void __movsq(unsigned long long *, unsigned long long const *, size_t); 1800b57cec5SDimitry Andric unsigned char __readgsbyte(unsigned long); 1810b57cec5SDimitry Andric unsigned long __readgsdword(unsigned long); 1820b57cec5SDimitry Andric unsigned __int64 __readgsqword(unsigned long); 1830b57cec5SDimitry Andric unsigned short __readgsword(unsigned long); 1840b57cec5SDimitry Andric void __stosq(unsigned __int64 *, unsigned __int64, size_t); 1850b57cec5SDimitry Andric unsigned char __vmx_on(unsigned __int64 *); 1860b57cec5SDimitry Andric unsigned char __vmx_vmclear(unsigned __int64 *); 1870b57cec5SDimitry Andric unsigned char __vmx_vmlaunch(void); 1880b57cec5SDimitry Andric unsigned char __vmx_vmptrld(unsigned __int64 *); 1890b57cec5SDimitry Andric unsigned char __vmx_vmread(size_t, size_t *); 1900b57cec5SDimitry Andric unsigned char __vmx_vmresume(void); 1910b57cec5SDimitry Andric unsigned char __vmx_vmwrite(size_t, size_t); 1920b57cec5SDimitry Andric void __writegsbyte(unsigned long, unsigned char); 1930b57cec5SDimitry Andric void __writegsdword(unsigned long, unsigned long); 1940b57cec5SDimitry Andric void __writegsqword(unsigned long, unsigned __int64); 1950b57cec5SDimitry Andric void __writegsword(unsigned long, unsigned short); 1960b57cec5SDimitry Andric unsigned char _bittest64(__int64 const *, __int64); 1970b57cec5SDimitry Andric unsigned char _bittestandcomplement64(__int64 *, __int64); 1980b57cec5SDimitry Andric unsigned char _bittestandreset64(__int64 *, __int64); 1990b57cec5SDimitry Andric unsigned char _bittestandset64(__int64 *, __int64); 2000b57cec5SDimitry Andric long _InterlockedAnd_np(long volatile *_Value, long _Mask); 2010b57cec5SDimitry Andric short _InterlockedAnd16_np(short volatile *_Value, short _Mask); 2020b57cec5SDimitry Andric __int64 _InterlockedAnd64_np(__int64 volatile *_Value, __int64 _Mask); 2030b57cec5SDimitry Andric char _InterlockedAnd8_np(char volatile *_Value, char _Mask); 2040b57cec5SDimitry Andric unsigned char _interlockedbittestandreset64(__int64 volatile *, __int64); 2050b57cec5SDimitry Andric unsigned char _interlockedbittestandset64(__int64 volatile *, __int64); 2060b57cec5SDimitry Andric long _InterlockedCompareExchange_np(long volatile *_Destination, long _Exchange, 2070b57cec5SDimitry Andric long _Comparand); 2080b57cec5SDimitry Andric unsigned char _InterlockedCompareExchange128_np(__int64 volatile *_Destination, 2090b57cec5SDimitry Andric __int64 _ExchangeHigh, 2100b57cec5SDimitry Andric __int64 _ExchangeLow, 2110b57cec5SDimitry Andric __int64 *_ComparandResult); 2120b57cec5SDimitry Andric short _InterlockedCompareExchange16_np(short volatile *_Destination, 2130b57cec5SDimitry Andric short _Exchange, short _Comparand); 2140b57cec5SDimitry Andric __int64 _InterlockedCompareExchange64_np(__int64 volatile *_Destination, 2150b57cec5SDimitry Andric __int64 _Exchange, __int64 _Comparand); 2160b57cec5SDimitry Andric void *_InterlockedCompareExchangePointer_np(void *volatile *_Destination, 2170b57cec5SDimitry Andric void *_Exchange, void *_Comparand); 2180b57cec5SDimitry Andric long _InterlockedOr_np(long volatile *_Value, long _Mask); 2190b57cec5SDimitry Andric short _InterlockedOr16_np(short volatile *_Value, short _Mask); 2200b57cec5SDimitry Andric __int64 _InterlockedOr64_np(__int64 volatile *_Value, __int64 _Mask); 2210b57cec5SDimitry Andric char _InterlockedOr8_np(char volatile *_Value, char _Mask); 2220b57cec5SDimitry Andric long _InterlockedXor_np(long volatile *_Value, long _Mask); 2230b57cec5SDimitry Andric short _InterlockedXor16_np(short volatile *_Value, short _Mask); 2240b57cec5SDimitry Andric __int64 _InterlockedXor64_np(__int64 volatile *_Value, __int64 _Mask); 2250b57cec5SDimitry Andric char _InterlockedXor8_np(char volatile *_Value, char _Mask); 2260b57cec5SDimitry Andric unsigned __int64 _rorx_u64(unsigned __int64, const unsigned int); 2270b57cec5SDimitry Andric __int64 _sarx_i64(__int64, unsigned int); 2280b57cec5SDimitry Andric unsigned __int64 _shlx_u64(unsigned __int64, unsigned int); 2290b57cec5SDimitry Andric unsigned __int64 _shrx_u64(unsigned __int64, unsigned int); 2300b57cec5SDimitry Andric __int64 __mulh(__int64, __int64); 2310b57cec5SDimitry Andric unsigned __int64 __umulh(unsigned __int64, unsigned __int64); 2320b57cec5SDimitry Andric __int64 _mul128(__int64, __int64, __int64 *); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric #endif /* __x86_64__ */ 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric /*----------------------------------------------------------------------------*\ 2370b57cec5SDimitry Andric |* movs, stos 2380b57cec5SDimitry Andric \*----------------------------------------------------------------------------*/ 239*0fca6ea1SDimitry Andric 240*0fca6ea1SDimitry Andric #if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__)) 241927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __movsb(unsigned char *__dst, 242927c847dSDimitry Andric unsigned char const *__src, 243927c847dSDimitry Andric size_t __n) { 244fe6060f1SDimitry Andric #if defined(__x86_64__) 245fe6060f1SDimitry Andric __asm__ __volatile__("rep movsb" 246fe6060f1SDimitry Andric : "+D"(__dst), "+S"(__src), "+c"(__n) 247fe6060f1SDimitry Andric : 248fe6060f1SDimitry Andric : "memory"); 249fe6060f1SDimitry Andric #else 250349cc55cSDimitry Andric __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" 251349cc55cSDimitry Andric "rep movsb\n" 252349cc55cSDimitry Andric "xchg {%%esi, %1|%1, esi}" 253fe6060f1SDimitry Andric : "+D"(__dst), "+r"(__src), "+c"(__n) 254fe6060f1SDimitry Andric : 255fe6060f1SDimitry Andric : "memory"); 256fe6060f1SDimitry Andric #endif 2570b57cec5SDimitry Andric } 258927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __movsd(unsigned long *__dst, 259927c847dSDimitry Andric unsigned long const *__src, 260927c847dSDimitry Andric size_t __n) { 261fe6060f1SDimitry Andric #if defined(__x86_64__) 262349cc55cSDimitry Andric __asm__ __volatile__("rep movs{l|d}" 263927c847dSDimitry Andric : "+D"(__dst), "+S"(__src), "+c"(__n) 264927c847dSDimitry Andric : 2650b57cec5SDimitry Andric : "memory"); 266fe6060f1SDimitry Andric #else 267349cc55cSDimitry Andric __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" 268349cc55cSDimitry Andric "rep movs{l|d}\n" 269349cc55cSDimitry Andric "xchg {%%esi, %1|%1, esi}" 270fe6060f1SDimitry Andric : "+D"(__dst), "+r"(__src), "+c"(__n) 271fe6060f1SDimitry Andric : 272fe6060f1SDimitry Andric : "memory"); 273fe6060f1SDimitry Andric #endif 2740b57cec5SDimitry Andric } 275927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __movsw(unsigned short *__dst, 276927c847dSDimitry Andric unsigned short const *__src, 277927c847dSDimitry Andric size_t __n) { 278fe6060f1SDimitry Andric #if defined(__x86_64__) 279927c847dSDimitry Andric __asm__ __volatile__("rep movsw" 280927c847dSDimitry Andric : "+D"(__dst), "+S"(__src), "+c"(__n) 281927c847dSDimitry Andric : 282927c847dSDimitry Andric : "memory"); 283fe6060f1SDimitry Andric #else 284349cc55cSDimitry Andric __asm__ __volatile__("xchg {%%esi, %1|%1, esi}\n" 285349cc55cSDimitry Andric "rep movsw\n" 286349cc55cSDimitry Andric "xchg {%%esi, %1|%1, esi}" 287fe6060f1SDimitry Andric : "+D"(__dst), "+r"(__src), "+c"(__n) 288fe6060f1SDimitry Andric : 289fe6060f1SDimitry Andric : "memory"); 290fe6060f1SDimitry Andric #endif 291927c847dSDimitry Andric } 292927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __stosd(unsigned long *__dst, 293927c847dSDimitry Andric unsigned long __x, 294927c847dSDimitry Andric size_t __n) { 295349cc55cSDimitry Andric __asm__ __volatile__("rep stos{l|d}" 296927c847dSDimitry Andric : "+D"(__dst), "+c"(__n) 297927c847dSDimitry Andric : "a"(__x) 298927c847dSDimitry Andric : "memory"); 299927c847dSDimitry Andric } 300927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __stosw(unsigned short *__dst, 301927c847dSDimitry Andric unsigned short __x, 302927c847dSDimitry Andric size_t __n) { 303927c847dSDimitry Andric __asm__ __volatile__("rep stosw" 304927c847dSDimitry Andric : "+D"(__dst), "+c"(__n) 305927c847dSDimitry Andric : "a"(__x) 3060b57cec5SDimitry Andric : "memory"); 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric #endif 309*0fca6ea1SDimitry Andric #if defined(__x86_64__) && !defined(__arm64ec__) 310927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __movsq( 311927c847dSDimitry Andric unsigned long long *__dst, unsigned long long const *__src, size_t __n) { 312927c847dSDimitry Andric __asm__ __volatile__("rep movsq" 313927c847dSDimitry Andric : "+D"(__dst), "+S"(__src), "+c"(__n) 314927c847dSDimitry Andric : 315927c847dSDimitry Andric : "memory"); 3160b57cec5SDimitry Andric } 317927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst, 318927c847dSDimitry Andric unsigned __int64 __x, 319927c847dSDimitry Andric size_t __n) { 3200b57cec5SDimitry Andric __asm__ __volatile__("rep stosq" : "+D"(__dst), "+c"(__n) : "a"(__x) 3210b57cec5SDimitry Andric : "memory"); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric #endif 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric /*----------------------------------------------------------------------------*\ 3260b57cec5SDimitry Andric |* Misc 3270b57cec5SDimitry Andric \*----------------------------------------------------------------------------*/ 328*0fca6ea1SDimitry Andric #if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__)) 329927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __halt(void) { 3300b57cec5SDimitry Andric __asm__ volatile("hlt"); 3310b57cec5SDimitry Andric } 332*0fca6ea1SDimitry Andric 333*0fca6ea1SDimitry Andric static inline unsigned char __inbyte(unsigned short port) { 334*0fca6ea1SDimitry Andric unsigned char ret; 335*0fca6ea1SDimitry Andric __asm__ __volatile__("inb %w1, %b0" : "=a"(ret) : "Nd"(port)); 336*0fca6ea1SDimitry Andric return ret; 337*0fca6ea1SDimitry Andric } 338*0fca6ea1SDimitry Andric 339*0fca6ea1SDimitry Andric static inline unsigned short __inword(unsigned short port) { 340*0fca6ea1SDimitry Andric unsigned short ret; 341*0fca6ea1SDimitry Andric __asm__ __volatile__("inw %w1, %w0" : "=a"(ret) : "Nd"(port)); 342*0fca6ea1SDimitry Andric return ret; 343*0fca6ea1SDimitry Andric } 344*0fca6ea1SDimitry Andric 345*0fca6ea1SDimitry Andric static inline unsigned long __indword(unsigned short port) { 346*0fca6ea1SDimitry Andric unsigned long ret; 347*0fca6ea1SDimitry Andric __asm__ __volatile__("inl %w1, %k0" : "=a"(ret) : "Nd"(port)); 348*0fca6ea1SDimitry Andric return ret; 349*0fca6ea1SDimitry Andric } 350*0fca6ea1SDimitry Andric 351*0fca6ea1SDimitry Andric static inline void __outbyte(unsigned short port, unsigned char data) { 352*0fca6ea1SDimitry Andric __asm__ __volatile__("outb %b0, %w1" : : "a"(data), "Nd"(port)); 353*0fca6ea1SDimitry Andric } 354*0fca6ea1SDimitry Andric 355*0fca6ea1SDimitry Andric static inline void __outword(unsigned short port, unsigned short data) { 356*0fca6ea1SDimitry Andric __asm__ __volatile__("outw %w0, %w1" : : "a"(data), "Nd"(port)); 357*0fca6ea1SDimitry Andric } 358*0fca6ea1SDimitry Andric 359*0fca6ea1SDimitry Andric static inline void __outdword(unsigned short port, unsigned long data) { 360*0fca6ea1SDimitry Andric __asm__ __volatile__("outl %k0, %w1" : : "a"(data), "Nd"(port)); 361*0fca6ea1SDimitry Andric } 3620b57cec5SDimitry Andric #endif 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) 365927c847dSDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS __nop(void) { 3660b57cec5SDimitry Andric __asm__ volatile("nop"); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric #endif 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric /*----------------------------------------------------------------------------*\ 3710b57cec5SDimitry Andric |* MS AArch64 specific 3720b57cec5SDimitry Andric \*----------------------------------------------------------------------------*/ 373*0fca6ea1SDimitry Andric #if defined(__aarch64__) || defined(__arm64ec__) 3740b57cec5SDimitry Andric unsigned __int64 __getReg(int); 3750b57cec5SDimitry Andric long _InterlockedAdd(long volatile *Addend, long Value); 376*0fca6ea1SDimitry Andric __int64 _InterlockedAdd64(__int64 volatile *Addend, __int64 Value); 3770b57cec5SDimitry Andric __int64 _ReadStatusReg(int); 3780b57cec5SDimitry Andric void _WriteStatusReg(int, __int64); 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric unsigned short __cdecl _byteswap_ushort(unsigned short val); 3810b57cec5SDimitry Andric unsigned long __cdecl _byteswap_ulong (unsigned long val); 3820b57cec5SDimitry Andric unsigned __int64 __cdecl _byteswap_uint64(unsigned __int64 val); 3836e75b2fbSDimitry Andric 3846e75b2fbSDimitry Andric __int64 __mulh(__int64 __a, __int64 __b); 3856e75b2fbSDimitry Andric unsigned __int64 __umulh(unsigned __int64 __a, unsigned __int64 __b); 38681ad6265SDimitry Andric 38781ad6265SDimitry Andric void __break(int); 38881ad6265SDimitry Andric 38981ad6265SDimitry Andric void __writex18byte(unsigned long offset, unsigned char data); 39081ad6265SDimitry Andric void __writex18word(unsigned long offset, unsigned short data); 39181ad6265SDimitry Andric void __writex18dword(unsigned long offset, unsigned long data); 39281ad6265SDimitry Andric void __writex18qword(unsigned long offset, unsigned __int64 data); 39381ad6265SDimitry Andric 39481ad6265SDimitry Andric unsigned char __readx18byte(unsigned long offset); 39581ad6265SDimitry Andric unsigned short __readx18word(unsigned long offset); 39681ad6265SDimitry Andric unsigned long __readx18dword(unsigned long offset); 39781ad6265SDimitry Andric unsigned __int64 __readx18qword(unsigned long offset); 3985f757f3fSDimitry Andric 3995f757f3fSDimitry Andric double _CopyDoubleFromInt64(__int64); 4005f757f3fSDimitry Andric float _CopyFloatFromInt32(__int32); 4015f757f3fSDimitry Andric __int32 _CopyInt32FromFloat(float); 4025f757f3fSDimitry Andric __int64 _CopyInt64FromDouble(double); 4035f757f3fSDimitry Andric 4045f757f3fSDimitry Andric unsigned int _CountLeadingOnes(unsigned long); 4055f757f3fSDimitry Andric unsigned int _CountLeadingOnes64(unsigned __int64); 4065f757f3fSDimitry Andric unsigned int _CountLeadingSigns(long); 4075f757f3fSDimitry Andric unsigned int _CountLeadingSigns64(__int64); 4085f757f3fSDimitry Andric unsigned int _CountOneBits(unsigned long); 4095f757f3fSDimitry Andric unsigned int _CountOneBits64(unsigned __int64); 4105f757f3fSDimitry Andric 411*0fca6ea1SDimitry Andric unsigned int __hlt(unsigned int, ...); 412*0fca6ea1SDimitry Andric 413*0fca6ea1SDimitry Andric void __cdecl __prefetch(const void *); 414*0fca6ea1SDimitry Andric 4150b57cec5SDimitry Andric #endif 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric /*----------------------------------------------------------------------------*\ 4180b57cec5SDimitry Andric |* Privileged intrinsics 4190b57cec5SDimitry Andric \*----------------------------------------------------------------------------*/ 420*0fca6ea1SDimitry Andric #if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__)) 4210b57cec5SDimitry Andric static __inline__ unsigned __int64 __DEFAULT_FN_ATTRS 4220b57cec5SDimitry Andric __readmsr(unsigned long __register) { 4230b57cec5SDimitry Andric // Loads the contents of a 64-bit model specific register (MSR) specified in 4240b57cec5SDimitry Andric // the ECX register into registers EDX:EAX. The EDX register is loaded with 4250b57cec5SDimitry Andric // the high-order 32 bits of the MSR and the EAX register is loaded with the 4260b57cec5SDimitry Andric // low-order 32 bits. If less than 64 bits are implemented in the MSR being 4270b57cec5SDimitry Andric // read, the values returned to EDX:EAX in unimplemented bit locations are 4280b57cec5SDimitry Andric // undefined. 4290b57cec5SDimitry Andric unsigned long __edx; 4300b57cec5SDimitry Andric unsigned long __eax; 4310b57cec5SDimitry Andric __asm__ ("rdmsr" : "=d"(__edx), "=a"(__eax) : "c"(__register)); 4320b57cec5SDimitry Andric return (((unsigned __int64)__edx) << 32) | (unsigned __int64)__eax; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 435927c847dSDimitry Andric static __inline__ unsigned __LPTRINT_TYPE__ __DEFAULT_FN_ATTRS __readcr3(void) { 436480093f4SDimitry Andric unsigned __LPTRINT_TYPE__ __cr3_val; 437349cc55cSDimitry Andric __asm__ __volatile__( 438349cc55cSDimitry Andric "mov {%%cr3, %0|%0, cr3}" 439349cc55cSDimitry Andric : "=r"(__cr3_val) 440349cc55cSDimitry Andric : 441349cc55cSDimitry Andric : "memory"); 4420b57cec5SDimitry Andric return __cr3_val; 4430b57cec5SDimitry Andric } 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS 446480093f4SDimitry Andric __writecr3(unsigned __INTPTR_TYPE__ __cr3_val) { 447349cc55cSDimitry Andric __asm__ ("mov {%0, %%cr3|cr3, %0}" : : "r"(__cr3_val) : "memory"); 4480b57cec5SDimitry Andric } 449*0fca6ea1SDimitry Andric #endif 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric #ifdef __cplusplus 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric #endif 4540b57cec5SDimitry Andric 455480093f4SDimitry Andric #undef __LPTRINT_TYPE__ 456480093f4SDimitry Andric 4570b57cec5SDimitry Andric #undef __DEFAULT_FN_ATTRS 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric #endif /* __INTRIN_H */ 4600b57cec5SDimitry Andric #endif /* _MSC_VER */ 461