1 /* SPDX-License-Identifier: BSD-3-Clause */
4 * Copyright (c) 2011, Advanced Micro Devices, Inc. All rights reserved.
5 * Copyright (c) 2014, Edward O'Callaghan <eocallaghan@alterapraxis.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <check_for_wrapper.h>
33 #if defined (__GNUC__)
35 /* I/O intrin functions. */
36 static __inline__
__attribute__((always_inline
)) uint8_t __inbyte(uint16_t Port
)
40 __asm__
__volatile__ (
49 static __inline__
__attribute__((always_inline
)) uint16_t __inword(uint16_t Port
)
53 __asm__
__volatile__ (
62 static __inline__
__attribute__((always_inline
)) uint32_t __indword(uint16_t Port
)
66 __asm__
__volatile__ (
75 static __inline__
__attribute__((always_inline
)) void __outbyte(uint16_t Port
,uint8_t Data
)
77 __asm__
__volatile__ (
80 : "a" (Data
), "Nd" (Port
)
84 static __inline__
__attribute__((always_inline
)) void __outword(uint16_t Port
,uint16_t Data
)
86 __asm__
__volatile__ (
89 : "a" (Data
), "Nd" (Port
)
93 static __inline__
__attribute__((always_inline
)) void __outdword(uint16_t Port
,uint32_t Data
)
95 __asm__
__volatile__ (
98 : "a" (Data
), "Nd" (Port
)
102 static __inline__
__attribute__((always_inline
)) void __inbytestring(uint16_t Port
,uint8_t *Buffer
,unsigned long Count
)
104 __asm__
__volatile__ (
106 : "+D" (Buffer
), "+c" (Count
)
111 static __inline__
__attribute__((always_inline
)) void __inwordstring(uint16_t Port
,uint16_t *Buffer
,unsigned long Count
)
113 __asm__
__volatile__ (
115 : "+D" (Buffer
), "+c" (Count
)
120 static __inline__
__attribute__((always_inline
)) void __indwordstring(uint16_t Port
,unsigned long *Buffer
,unsigned long Count
)
122 __asm__
__volatile__ (
124 : "+D" (Buffer
), "+c" (Count
)
129 static __inline__
__attribute__((always_inline
)) void __outbytestring(uint16_t Port
,uint8_t *Buffer
,unsigned long Count
)
131 __asm__
__volatile__ (
133 : "+S" (Buffer
), "+c" (Count
)
138 static __inline__
__attribute__((always_inline
)) void __outwordstring(uint16_t Port
,uint16_t *Buffer
,unsigned long Count
)
140 __asm__
__volatile__ (
142 : "+S" (Buffer
), "+c" (Count
)
147 static __inline__
__attribute__((always_inline
)) void __outdwordstring(uint16_t Port
,unsigned long *Buffer
,unsigned long Count
)
149 __asm__
__volatile__ (
151 : "+S" (Buffer
), "+c" (Count
)
156 static __inline__
__attribute__((always_inline
)) unsigned long __readdr0(void)
159 __asm__
__volatile__ (
160 "mov %%dr0, %[value]"
161 : [value
] "=r" (value
)
166 static __inline__
__attribute__((always_inline
)) unsigned long __readdr1(void)
169 __asm__
__volatile__ (
170 "mov %%dr1, %[value]"
171 : [value
] "=r" (value
)
176 static __inline__
__attribute__((always_inline
)) unsigned long __readdr2(void)
179 __asm__
__volatile__ (
180 "mov %%dr2, %[value]"
181 : [value
] "=r" (value
)
186 static __inline__
__attribute__((always_inline
)) unsigned long __readdr3(void)
189 __asm__
__volatile__ (
190 "mov %%dr3, %[value]"
191 : [value
] "=r" (value
)
196 static __inline__
__attribute__((always_inline
)) unsigned long __readdr7(void)
199 __asm__
__volatile__ (
200 "mov %%dr7, %[value]"
201 : [value
] "=r" (value
)
206 static __inline__
__attribute__((always_inline
)) unsigned long __readdr(unsigned long reg
)
234 static __inline__
__attribute__((always_inline
)) void __writedr0(unsigned long Data
)
236 __asm__
__volatile__ (
243 static __inline__
__attribute__((always_inline
)) void __writedr1(unsigned long Data
)
245 __asm__
__volatile__ (
252 static __inline__
__attribute__((always_inline
)) void __writedr2(unsigned long Data
)
254 __asm__
__volatile__ (
261 static __inline__
__attribute__((always_inline
)) void __writedr3(unsigned long Data
)
263 __asm__
__volatile__ (
270 static __inline__
__attribute__((always_inline
)) void __writedr7(unsigned long Data
)
272 __asm__
__volatile__ (
279 static __inline__
__attribute__((always_inline
)) void __writedr(unsigned long reg
, unsigned long Data
)
307 static __inline__
__attribute__((always_inline
)) unsigned long __readcr0(void)
310 __asm__
__volatile__ (
311 "mov %%cr0, %[value]"
312 : [value
] "=r" (value
));
316 static __inline__
__attribute__((always_inline
)) unsigned long __readcr2(void)
319 __asm__
__volatile__ (
320 "mov %%cr2, %[value]"
321 : [value
] "=r" (value
));
325 static __inline__
__attribute__((always_inline
)) unsigned long __readcr3(void)
328 __asm__
__volatile__ (
329 "mov %%cr3, %[value]"
330 : [value
] "=r" (value
));
334 static __inline__
__attribute__((always_inline
)) unsigned long __readcr4(void)
337 __asm__
__volatile__ (
338 "mov %%cr4, %[value]"
339 : [value
] "=r" (value
));
343 static __inline__
__attribute__((always_inline
)) unsigned long __readcr8(void)
346 __asm__
__volatile__ (
347 "mov %%cr8, %[value]"
348 : [value
] "=r" (value
));
352 static __inline__
__attribute__((always_inline
)) unsigned long __readcr(unsigned long reg
)
380 static __inline__
__attribute__((always_inline
)) void __writecr0(unsigned long Data
)
382 __asm__
__volatile__ (
390 static __inline__
__attribute__((always_inline
)) void __writecr2(unsigned long Data
)
392 __asm__
__volatile__ (
399 static __inline__
__attribute__((always_inline
)) void __writecr3(unsigned long Data
)
401 __asm__
__volatile__ (
408 static __inline__
__attribute__((always_inline
)) void __writecr4(unsigned long Data
)
410 __asm__
__volatile__ (
417 static __inline__
__attribute__((always_inline
)) void __writecr8(unsigned long Data
)
419 __asm__
__volatile__ (
426 static __inline__
__attribute__((always_inline
)) void __writecr(unsigned long reg
, unsigned long Data
)
454 static __inline__
__attribute__((always_inline
)) UINT64
__readmsr(UINT32 msr
)
457 __asm__
__volatile__(
465 static __inline__
__attribute__((always_inline
)) void __writemsr (UINT32 msr
, UINT64 Value
)
467 __asm__
__volatile__ (
470 : "c" (msr
), "A" (Value
)
474 #if !defined(__clang__)
475 static __inline__
__attribute__((always_inline
)) UINT64
__rdtsc(void)
478 __asm__
__volatile__ (
485 static __inline__
__attribute__((always_inline
)) void __cpuid(int CPUInfo
[], const int InfoType
)
487 __asm__
__volatile__(
489 :"=a" (CPUInfo
[0]), "=b" (CPUInfo
[1]), "=c" (CPUInfo
[2]), "=d" (CPUInfo
[3])
495 static __inline__
__attribute__((always_inline
)) void _disable(void)
497 __asm__
__volatile__ ("cli");
501 static __inline__
__attribute__((always_inline
)) void _enable(void)
503 __asm__
__volatile__ ("sti");
507 static __inline__
__attribute__((always_inline
)) void __halt(void)
509 __asm__
__volatile__ ("hlt");
513 static __inline__
__attribute__((always_inline
)) void __debugbreak(void)
515 __asm__
__volatile__ ("int3");
518 static __inline__
__attribute__((always_inline
)) void __invd(void)
520 __asm__
__volatile__ ("invd");
523 static __inline__
__attribute__((always_inline
)) void __wbinvd(void)
525 __asm__
__volatile__ ("wbinvd");
528 static __inline__
__attribute__((always_inline
)) void __lidt(void *Source
)
530 __asm__
__volatile__("lidt %0" : : "m"(*(short*)Source
));
533 static __inline__
__attribute__((always_inline
)) void
534 __writefsbyte(const unsigned long Offset
, const uint8_t Data
)
536 __asm__ ("movb %[Data], %%fs:%a[Offset]"
538 : [Offset
] "ir" (Offset
), [Data
] "iq" (Data
));
541 static __inline__
__attribute__((always_inline
)) void
542 __writefsword(const unsigned long Offset
, const uint16_t Data
)
544 __asm__ ("movw %[Data], %%fs:%a[Offset]"
546 : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
));
549 static __inline__
__attribute__((always_inline
)) void
550 __writefsdword(const unsigned long Offset
, const uint32_t Data
)
552 __asm__ ("movl %[Data], %%fs:%a[Offset]"
554 : [Offset
] "ir" (Offset
), [Data
] "ir" (Data
));
557 static __inline__
__attribute__((always_inline
)) uint8_t
558 __readfsbyte(const unsigned long Offset
)
561 __asm__ ("movb %%fs:%a[Offset], %[value]"
562 : [value
] "=q" (value
)
563 : [Offset
] "ir" (Offset
));
567 static __inline__
__attribute__((always_inline
)) uint16_t
568 __readfsword(const unsigned long Offset
)
570 unsigned short value
;
571 __asm__ ("movw %%fs:%a[Offset], %[value]"
572 : [value
] "=q" (value
)
573 : [Offset
] "ir" (Offset
));
577 static __inline__
__attribute__((always_inline
)) uint32_t
578 __readfsdword(unsigned long Offset
)
581 __asm__ ("mov %%fs:%a[Offset], %[value]"
582 : [value
] "=r" (value
)
583 : [Offset
] "ir" (Offset
));
588 typedef long long __v2di
__attribute__((__vector_size__ (16)));
589 typedef long long __m128i
__attribute__((__vector_size__ (16), __may_alias__
));
591 static __inline__
__attribute__((always_inline
)) void _mm_stream_si128_fs2 (void *__A
, __m128i __B
)
593 __asm__(".byte 0x64"); // fs prefix
594 #if defined(__clang__)
595 __builtin_nontemporal_store((__v2di
)__B
, (__v2di
*)__A
);
597 __builtin_ia32_movntdq ((__v2di
*)__A
, (__v2di
)__B
);
601 static __inline__
__attribute__((always_inline
)) void _mm_stream_si128_fs (void *__A
, void *__B
)
604 data
= (__m128i
) __builtin_ia32_lddqu ((char const *)__B
);
605 _mm_stream_si128_fs2 (__A
, data
);
608 static __inline__
__attribute__((always_inline
)) void _mm_clflush_fs (void *__A
)
610 __asm__(".byte 0x64"); // fs prefix
611 __builtin_ia32_clflush (__A
);
614 #if !defined(__clang__)
615 static __inline
__attribute__(( __always_inline__
)) void _mm_mfence (void)
617 __builtin_ia32_mfence ();
620 void _mm_mfence(void);
623 #if !defined(__clang__)
624 static __inline
__attribute__(( __always_inline__
)) void _mm_sfence (void)
626 __builtin_ia32_sfence ();
629 void _mm_sfence(void);
631 #endif /* __SSE3__ */
633 #endif /* defined (__GNUC__) */