2 * Copyright (c) 2011, Advanced Micro Devices, Inc. All rights reserved.
3 * Copyright (c) 2014, Edward O'Callaghan <eocallaghan@alterapraxis.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
13 * its contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #if defined (__GNUC__)
31 /* I/O intrin functions. */
32 static __inline__
__attribute__((always_inline
)) uint8_t __inbyte(uint16_t Port
)
36 __asm__
__volatile__ (
45 static __inline__
__attribute__((always_inline
)) uint16_t __inword(uint16_t Port
)
49 __asm__
__volatile__ (
58 static __inline__
__attribute__((always_inline
)) uint32_t __indword(uint16_t Port
)
62 __asm__
__volatile__ (
71 static __inline__
__attribute__((always_inline
)) void __outbyte(uint16_t Port
,uint8_t Data
)
73 __asm__
__volatile__ (
76 : "a" (Data
), "Nd" (Port
)
80 static __inline__
__attribute__((always_inline
)) void __outword(uint16_t Port
,uint16_t Data
)
82 __asm__
__volatile__ (
85 : "a" (Data
), "Nd" (Port
)
89 static __inline__
__attribute__((always_inline
)) void __outdword(uint16_t Port
,uint32_t Data
)
91 __asm__
__volatile__ (
94 : "a" (Data
), "Nd" (Port
)
98 static __inline__
__attribute__((always_inline
)) void __inbytestring(uint16_t Port
,uint8_t *Buffer
,unsigned long Count
)
100 __asm__
__volatile__ (
102 : "+D" (Buffer
), "+c" (Count
)
107 static __inline__
__attribute__((always_inline
)) void __inwordstring(uint16_t Port
,uint16_t *Buffer
,unsigned long Count
)
109 __asm__
__volatile__ (
111 : "+D" (Buffer
), "+c" (Count
)
116 static __inline__
__attribute__((always_inline
)) void __indwordstring(uint16_t Port
,unsigned long *Buffer
,unsigned long Count
)
118 __asm__
__volatile__ (
120 : "+D" (Buffer
), "+c" (Count
)
125 static __inline__
__attribute__((always_inline
)) void __outbytestring(uint16_t Port
,uint8_t *Buffer
,unsigned long Count
)
127 __asm__
__volatile__ (
129 : "+S" (Buffer
), "+c" (Count
)
134 static __inline__
__attribute__((always_inline
)) void __outwordstring(uint16_t Port
,uint16_t *Buffer
,unsigned long Count
)
136 __asm__
__volatile__ (
138 : "+S" (Buffer
), "+c" (Count
)
143 static __inline__
__attribute__((always_inline
)) void __outdwordstring(uint16_t Port
,unsigned long *Buffer
,unsigned long Count
)
145 __asm__
__volatile__ (
147 : "+S" (Buffer
), "+c" (Count
)
152 static __inline__
__attribute__((always_inline
)) unsigned long __readdr0(void)
155 __asm__
__volatile__ (
156 "mov %%dr0, %[value]"
157 : [value
] "=r" (value
)
162 static __inline__
__attribute__((always_inline
)) unsigned long __readdr1(void)
165 __asm__
__volatile__ (
166 "mov %%dr1, %[value]"
167 : [value
] "=r" (value
)
172 static __inline__
__attribute__((always_inline
)) unsigned long __readdr2(void)
175 __asm__
__volatile__ (
176 "mov %%dr2, %[value]"
177 : [value
] "=r" (value
)
182 static __inline__
__attribute__((always_inline
)) unsigned long __readdr3(void)
185 __asm__
__volatile__ (
186 "mov %%dr3, %[value]"
187 : [value
] "=r" (value
)
192 static __inline__
__attribute__((always_inline
)) unsigned long __readdr7(void)
195 __asm__
__volatile__ (
196 "mov %%dr7, %[value]"
197 : [value
] "=r" (value
)
202 static __inline__
__attribute__((always_inline
)) unsigned long __readdr(unsigned long reg
)
230 static __inline__
__attribute__((always_inline
)) void __writedr0(unsigned long Data
)
232 __asm__
__volatile__ (
239 static __inline__
__attribute__((always_inline
)) void __writedr1(unsigned long Data
)
241 __asm__
__volatile__ (
248 static __inline__
__attribute__((always_inline
)) void __writedr2(unsigned long Data
)
250 __asm__
__volatile__ (
257 static __inline__
__attribute__((always_inline
)) void __writedr3(unsigned long Data
)
259 __asm__
__volatile__ (
266 static __inline__
__attribute__((always_inline
)) void __writedr7(unsigned long Data
)
268 __asm__
__volatile__ (
275 static __inline__
__attribute__((always_inline
)) void __writedr(unsigned long reg
, unsigned long Data
)
303 static __inline__
__attribute__((always_inline
)) unsigned long __readcr0(void)
306 __asm__
__volatile__ (
307 "mov %%cr0, %[value]"
308 : [value
] "=r" (value
));
312 static __inline__
__attribute__((always_inline
)) unsigned long __readcr2(void)
315 __asm__
__volatile__ (
316 "mov %%cr2, %[value]"
317 : [value
] "=r" (value
));
321 static __inline__
__attribute__((always_inline
)) unsigned long __readcr3(void)
324 __asm__
__volatile__ (
325 "mov %%cr3, %[value]"
326 : [value
] "=r" (value
));
330 static __inline__
__attribute__((always_inline
)) unsigned long __readcr4(void)
333 __asm__
__volatile__ (
334 "mov %%cr4, %[value]"
335 : [value
] "=r" (value
));
339 static __inline__
__attribute__((always_inline
)) unsigned long __readcr8(void)
342 __asm__
__volatile__ (
343 "mov %%cr8, %[value]"
344 : [value
] "=r" (value
));
348 static __inline__
__attribute__((always_inline
)) unsigned long __readcr(unsigned long reg
)
376 static __inline__
__attribute__((always_inline
)) void __writecr0(unsigned long Data
)
378 __asm__
__volatile__ (
386 static __inline__
__attribute__((always_inline
)) void __writecr2(unsigned long Data
)
388 __asm__
__volatile__ (
395 static __inline__
__attribute__((always_inline
)) void __writecr3(unsigned long Data
)
397 __asm__
__volatile__ (
404 static __inline__
__attribute__((always_inline
)) void __writecr4(unsigned long Data
)
406 __asm__
__volatile__ (
413 static __inline__
__attribute__((always_inline
)) void __writecr8(unsigned long Data
)
415 __asm__
__volatile__ (
422 static __inline__
__attribute__((always_inline
)) void __writecr(unsigned long reg
, unsigned long Data
)
450 static __inline__
__attribute__((always_inline
)) UINT64
__readmsr(UINT32 msr
)
453 __asm__
__volatile__(
461 static __inline__
__attribute__((always_inline
)) void __writemsr (UINT32 msr
, UINT64 Value
)
463 __asm__
__volatile__ (
466 : "c" (msr
), "A" (Value
)
470 #if !defined(__clang__)
471 static __inline__
__attribute__((always_inline
)) UINT64
__rdtsc(void)
474 __asm__
__volatile__ (
481 static __inline__
__attribute__((always_inline
)) void __cpuid(int CPUInfo
[], const int InfoType
)
483 __asm__
__volatile__(
485 :"=a" (CPUInfo
[0]), "=b" (CPUInfo
[1]), "=c" (CPUInfo
[2]), "=d" (CPUInfo
[3])
491 static __inline__
__attribute__((always_inline
)) void _disable(void)
493 __asm__
__volatile__ ("cli");
497 static __inline__
__attribute__((always_inline
)) void _enable(void)
499 __asm__
__volatile__ ("sti");
503 static __inline__
__attribute__((always_inline
)) void __halt(void)
505 __asm__
__volatile__ ("hlt");
509 static __inline__
__attribute__((always_inline
)) void __debugbreak(void)
511 __asm__
__volatile__ ("int3");
514 static __inline__
__attribute__((always_inline
)) void __invd(void)
516 __asm__
__volatile__ ("invd");
519 static __inline__
__attribute__((always_inline
)) void __wbinvd(void)
521 __asm__
__volatile__ ("wbinvd");
524 static __inline__
__attribute__((always_inline
)) void __lidt(void *Source
)
526 __asm__
__volatile__("lidt %0" : : "m"(*(short*)Source
));
529 static __inline__
__attribute__((always_inline
)) void
530 __writefsbyte(const unsigned long Offset
, const uint8_t Data
)
532 __asm__ ("movb %[Data], %%fs:%a[Offset]"
534 : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
));
537 static __inline__
__attribute__((always_inline
)) void
538 __writefsword(const unsigned long Offset
, const uint16_t Data
)
540 __asm__ ("movw %[Data], %%fs:%a[Offset]"
542 : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
));
545 static __inline__
__attribute__((always_inline
)) void
546 __writefsdword(const unsigned long Offset
, const uint32_t Data
)
548 __asm__ ("movl %[Data], %%fs:%a[Offset]"
550 : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
));
553 static __inline__
__attribute__((always_inline
)) uint8_t
554 __readfsbyte(const unsigned long Offset
)
557 __asm__ ("movb %%fs:%a[Offset], %[value]"
558 : [value
] "=q" (value
)
559 : [Offset
] "ir" (Offset
));
563 static __inline__
__attribute__((always_inline
)) uint16_t
564 __readfsword(const unsigned long Offset
)
566 unsigned short value
;
567 __asm__ ("movw %%fs:%a[Offset], %[value]"
568 : [value
] "=q" (value
)
569 : [Offset
] "ir" (Offset
));
573 static __inline__
__attribute__((always_inline
)) uint32_t
574 __readfsdword(unsigned long Offset
)
577 __asm__ ("mov %%fs:%a[Offset], %[value]"
578 : [value
] "=r" (value
)
579 : [Offset
] "ir" (Offset
));
584 typedef long long __v2di
__attribute__((__vector_size__ (16)));
585 typedef long long __m128i
__attribute__((__vector_size__ (16), __may_alias__
));
587 static __inline__
__attribute__((always_inline
)) void _mm_stream_si128_fs2 (void *__A
, __m128i __B
)
589 __asm__(".byte 0x64"); // fs prefix
590 #if defined(__clang__)
591 __builtin_nontemporal_store((__v2di
)__B
, (__v2di
*)__A
);
593 __builtin_ia32_movntdq ((__v2di
*)__A
, (__v2di
)__B
);
597 static __inline__
__attribute__((always_inline
)) void _mm_stream_si128_fs (void *__A
, void *__B
)
600 data
= (__m128i
) __builtin_ia32_lddqu ((char const *)__B
);
601 _mm_stream_si128_fs2 (__A
, data
);
604 static __inline__
__attribute__((always_inline
)) void _mm_clflush_fs (void *__A
)
606 __asm__(".byte 0x64"); // fs prefix
607 __builtin_ia32_clflush (__A
);
610 #if !defined(__clang__)
611 static __inline
__attribute__(( __always_inline__
)) void _mm_mfence (void)
613 __builtin_ia32_mfence ();
616 void _mm_mfence(void);
619 #if !defined(__clang__)
620 static __inline
__attribute__(( __always_inline__
)) void _mm_sfence (void)
622 __builtin_ia32_sfence ();
625 void _mm_sfence(void);
627 #endif /* __SSE3__ */
629 #endif /* defined (__GNUC__) */