• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2011, Advanced Micro Devices, Inc. All rights reserved.
3  * Copyright (c) 2014, Edward O'Callaghan <eocallaghan@alterapraxis.com>
4  *
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.
15  *
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.
26  *
27  */
28 
29 #if defined (__GNUC__)
30 #include <stdint.h>
31 /* I/O intrin functions.  */
__inbyte(uint16_t Port)32 static __inline__ __attribute__((always_inline)) uint8_t __inbyte(uint16_t Port)
33 {
34   uint8_t value;
35 
36   __asm__ __volatile__ (
37     "in  %1, %0"
38     : "=a" (value)
39     : "Nd" (Port)
40     );
41 
42   return value;
43 }
44 
__inword(uint16_t Port)45 static __inline__ __attribute__((always_inline)) uint16_t __inword(uint16_t Port)
46 {
47   uint16_t value;
48 
49   __asm__ __volatile__ (
50     "in  %1, %0"
51     : "=a" (value)
52     : "Nd" (Port)
53     );
54 
55   return value;
56 }
57 
__indword(uint16_t Port)58 static __inline__ __attribute__((always_inline)) uint32_t __indword(uint16_t Port)
59 {
60   uint32_t value;
61 
62   __asm__ __volatile__ (
63     "in  %1, %0"
64     : "=a" (value)
65     : "Nd" (Port)
66     );
67   return value;
68 
69 }
70 
__outbyte(uint16_t Port,uint8_t Data)71 static __inline__ __attribute__((always_inline)) void __outbyte(uint16_t Port,uint8_t Data)
72 {
73   __asm__ __volatile__ (
74     "out  %0, %1"
75     :
76     : "a" (Data), "Nd" (Port)
77     );
78 }
79 
__outword(uint16_t Port,uint16_t Data)80 static __inline__ __attribute__((always_inline)) void __outword(uint16_t Port,uint16_t Data)
81 {
82   __asm__ __volatile__ (
83     "out  %0, %1"
84     :
85     : "a" (Data), "Nd" (Port)
86     );
87 }
88 
__outdword(uint16_t Port,uint32_t Data)89 static __inline__ __attribute__((always_inline)) void __outdword(uint16_t Port,uint32_t Data)
90 {
91   __asm__ __volatile__ (
92     "out  %0, %1"
93     :
94     : "a" (Data), "Nd" (Port)
95     );
96 }
97 
__inbytestring(uint16_t Port,uint8_t * Buffer,unsigned long Count)98 static __inline__ __attribute__((always_inline)) void __inbytestring(uint16_t Port,uint8_t *Buffer,unsigned long Count)
99 {
100   __asm__ __volatile__ (
101     "rep ; insb"
102     : "+D" (Buffer), "+c" (Count)
103     : "d"(Port)
104     );
105 }
106 
__inwordstring(uint16_t Port,uint16_t * Buffer,unsigned long Count)107 static __inline__ __attribute__((always_inline)) void __inwordstring(uint16_t Port,uint16_t *Buffer,unsigned long Count)
108 {
109   __asm__ __volatile__ (
110     "rep ; insw"
111     : "+D" (Buffer), "+c" (Count)
112     : "d"(Port)
113     );
114 }
115 
__indwordstring(uint16_t Port,unsigned long * Buffer,unsigned long Count)116 static __inline__ __attribute__((always_inline)) void __indwordstring(uint16_t Port,unsigned long *Buffer,unsigned long Count)
117 {
118   __asm__ __volatile__ (
119     "rep ; insl"
120     : "+D" (Buffer), "+c" (Count)
121     : "d"(Port)
122     );
123 }
124 
__outbytestring(uint16_t Port,uint8_t * Buffer,unsigned long Count)125 static __inline__ __attribute__((always_inline)) void __outbytestring(uint16_t Port,uint8_t *Buffer,unsigned long Count)
126 {
127   __asm__ __volatile__ (
128     "rep ; outsb"
129     : "+S" (Buffer), "+c" (Count)
130     : "d"(Port)
131     );
132 }
133 
__outwordstring(uint16_t Port,uint16_t * Buffer,unsigned long Count)134 static __inline__ __attribute__((always_inline)) void __outwordstring(uint16_t Port,uint16_t *Buffer,unsigned long Count)
135 {
136   __asm__ __volatile__ (
137     "rep ; outsw"
138     : "+S" (Buffer), "+c" (Count)
139     : "d"(Port)
140   );
141 }
142 
__outdwordstring(uint16_t Port,unsigned long * Buffer,unsigned long Count)143 static __inline__ __attribute__((always_inline)) void __outdwordstring(uint16_t Port,unsigned long *Buffer,unsigned long Count)
144 {
145   __asm__ __volatile__ (
146    "rep ; outsl"
147    : "+S" (Buffer), "+c" (Count)
148    : "d"(Port)
149    );
150 }
151 
__readdr0(void)152 static __inline__ __attribute__((always_inline)) unsigned long __readdr0(void)
153 {
154   unsigned long value;
155   __asm__ __volatile__ (
156     "mov %%dr0, %[value]"
157     : [value] "=r" (value)
158     );
159   return value;
160 }
161 
__readdr1(void)162 static __inline__ __attribute__((always_inline)) unsigned long __readdr1(void)
163 {
164   unsigned long value;
165   __asm__ __volatile__ (
166     "mov %%dr1, %[value]"
167     : [value] "=r" (value)
168     );
169   return value;
170 }
171 
__readdr2(void)172 static __inline__ __attribute__((always_inline)) unsigned long __readdr2(void)
173 {
174   unsigned long value;
175   __asm__ __volatile__ (
176     "mov %%dr2, %[value]"
177     : [value] "=r" (value)
178     );
179   return value;
180 }
181 
__readdr3(void)182 static __inline__ __attribute__((always_inline)) unsigned long __readdr3(void)
183 {
184   unsigned long value;
185   __asm__ __volatile__ (
186     "mov %%dr3, %[value]"
187     : [value] "=r" (value)
188     );
189   return value;
190 }
191 
__readdr7(void)192 static __inline__ __attribute__((always_inline)) unsigned long __readdr7(void)
193 {
194   unsigned long value;
195   __asm__ __volatile__ (
196     "mov %%dr7, %[value]"
197     : [value] "=r" (value)
198     );
199   return value;
200 }
201 
__readdr(unsigned long reg)202 static __inline__ __attribute__((always_inline)) unsigned long __readdr(unsigned long reg)
203 {
204   switch (reg){
205     case 0:
206       return __readdr0 ();
207       break;
208 
209     case 1:
210       return __readdr1 ();
211       break;
212 
213     case 2:
214       return __readdr2 ();
215       break;
216 
217     case 3:
218       return __readdr3 ();
219       break;
220 
221     case 7:
222       return __readdr7 ();
223       break;
224 
225     default:
226       return -1;
227   }
228 }
229 
__writedr0(unsigned long Data)230 static __inline__ __attribute__((always_inline)) void __writedr0(unsigned long Data)
231 {
232   __asm__ __volatile__ (
233     "mov %0, %%dr0"
234     :
235     : "r" (Data)
236     );
237 }
238 
__writedr1(unsigned long Data)239 static __inline__ __attribute__((always_inline)) void __writedr1(unsigned long Data)
240 {
241   __asm__ __volatile__ (
242     "mov %0, %%dr1"
243     :
244     : "r" (Data)
245     );
246 }
247 
__writedr2(unsigned long Data)248 static __inline__ __attribute__((always_inline)) void __writedr2(unsigned long Data)
249 {
250   __asm__ __volatile__ (
251     "mov %0, %%dr2"
252     :
253     : "r" (Data)
254     );
255 }
256 
__writedr3(unsigned long Data)257 static __inline__ __attribute__((always_inline)) void __writedr3(unsigned long Data)
258 {
259   __asm__ __volatile__ (
260     "mov %0, %%dr3"
261     :
262     : "r" (Data)
263     );
264 }
265 
__writedr7(unsigned long Data)266 static __inline__ __attribute__((always_inline)) void __writedr7(unsigned long Data)
267 {
268   __asm__ __volatile__ (
269     "mov %0, %%dr7"
270     :
271     : "r" (Data)
272     );
273 }
274 
__writedr(unsigned long reg,unsigned long Data)275 static __inline__ __attribute__((always_inline)) void __writedr(unsigned long reg, unsigned long Data)
276 {
277   switch (reg){
278     case 0:
279       __writedr0 (Data);
280       break;
281 
282     case 1:
283       __writedr1 (Data);
284       break;
285 
286     case 2:
287       __writedr2 (Data);
288       break;
289 
290     case 3:
291       __writedr3 (Data);
292       break;
293 
294     case 7:
295       __writedr7 (Data);
296       break;
297 
298     default:
299       ;
300   }
301 }
302 
__readcr0(void)303 static __inline__ __attribute__((always_inline)) unsigned long __readcr0(void)
304 {
305   unsigned long value;
306   __asm__ __volatile__ (
307     "mov %%cr0, %[value]"
308     : [value] "=r" (value));
309   return value;
310 }
311 
__readcr2(void)312 static __inline__ __attribute__((always_inline)) unsigned long __readcr2(void)
313 {
314   unsigned long value;
315   __asm__ __volatile__ (
316     "mov %%cr2, %[value]"
317     : [value] "=r" (value));
318   return value;
319 }
320 
__readcr3(void)321 static __inline__ __attribute__((always_inline)) unsigned long __readcr3(void)
322 {
323   unsigned long value;
324   __asm__ __volatile__ (
325     "mov %%cr3, %[value]"
326     : [value] "=r" (value));
327   return value;
328 }
329 
__readcr4(void)330 static __inline__ __attribute__((always_inline)) unsigned long __readcr4(void)
331 {
332   unsigned long value;
333   __asm__ __volatile__ (
334     "mov %%cr4, %[value]"
335     : [value] "=r" (value));
336   return value;
337 }
338 
__readcr8(void)339 static __inline__ __attribute__((always_inline)) unsigned long __readcr8(void)
340 {
341   unsigned long value;
342   __asm__ __volatile__ (
343     "mov %%cr8, %[value]"
344     : [value] "=r" (value));
345   return value;
346 }
347 
__readcr(unsigned long reg)348 static __inline__ __attribute__((always_inline)) unsigned long __readcr(unsigned long reg)
349 {
350   switch (reg){
351     case 0:
352       return __readcr0 ();
353       break;
354 
355     case 2:
356       return __readcr2 ();
357       break;
358 
359     case 3:
360       return __readcr3 ();
361       break;
362 
363     case 4:
364       return __readcr4 ();
365       break;
366 
367     case 8:
368       return __readcr8 ();
369       break;
370 
371     default:
372       return -1;
373   }
374 }
375 
__writecr0(unsigned long Data)376 static __inline__ __attribute__((always_inline)) void __writecr0(unsigned long Data)
377 {
378   __asm__ __volatile__ (
379     "mov %0, %%cr0"
380     :
381     : "r" (Data)
382     : "memory"
383     );
384 }
385 
__writecr2(unsigned long Data)386 static __inline__ __attribute__((always_inline)) void __writecr2(unsigned long Data)
387 {
388   __asm__ __volatile__ (
389     "mov %0, %%cr2"
390     :
391     : "r" (Data)
392     );
393 }
394 
__writecr3(unsigned long Data)395 static __inline__ __attribute__((always_inline)) void __writecr3(unsigned long Data)
396 {
397   __asm__ __volatile__ (
398     "mov %0, %%cr3"
399     :
400     : "r" (Data)
401     );
402 }
403 
__writecr4(unsigned long Data)404 static __inline__ __attribute__((always_inline)) void __writecr4(unsigned long Data)
405 {
406   __asm__ __volatile__ (
407     "mov %0, %%cr4"
408     :
409     : "r" (Data)
410     );
411 }
412 
__writecr8(unsigned long Data)413 static __inline__ __attribute__((always_inline)) void __writecr8(unsigned long Data)
414 {
415   __asm__ __volatile__ (
416     "mov %0, %%cr8"
417     :
418     : "r" (Data)
419     );
420 }
421 
__writecr(unsigned long reg,unsigned long Data)422 static __inline__ __attribute__((always_inline)) void __writecr(unsigned long reg, unsigned long Data)
423 {
424   switch (reg){
425     case 0:
426       __writecr0 (Data);
427       break;
428 
429     case 2:
430       __writecr2 (Data);
431       break;
432 
433     case 3:
434       __writecr3 (Data);
435       break;
436 
437     case 4:
438       __writecr4 (Data);
439       break;
440 
441     case 8:
442       __writecr8 (Data);
443       break;
444 
445     default:
446       ;
447   }
448 }
449 
__readmsr(UINT32 msr)450 static __inline__ __attribute__((always_inline)) UINT64 __readmsr(UINT32 msr)
451 {
452   UINT64 retval;
453   __asm__ __volatile__(
454        "rdmsr"
455        : "=A" (retval)
456        : "c" (msr)
457        );
458    return retval;
459 }
460 
__writemsr(UINT32 msr,UINT64 Value)461 static __inline__ __attribute__((always_inline)) void __writemsr (UINT32 msr, UINT64 Value)
462 {
463   __asm__ __volatile__ (
464      "wrmsr"
465      :
466      : "c" (msr), "A" (Value)
467      );
468 }
469 
470 #if !defined(__clang__)
__rdtsc(void)471 static __inline__ __attribute__((always_inline)) UINT64 __rdtsc(void)
472 {
473   UINT64 retval;
474   __asm__ __volatile__ (
475      "rdtsc"
476      : "=A" (retval));
477   return retval;
478 }
479 #endif
480 
__cpuid(int CPUInfo[],const int InfoType)481 static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)
482 {
483    __asm__ __volatile__(
484      "cpuid"
485      :"=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3])
486      : "a" (InfoType)
487      );
488 }
489 
490 
_disable(void)491 static __inline__ __attribute__((always_inline)) void _disable(void)
492 {
493   __asm__ __volatile__ ("cli");
494 }
495 
496 
_enable(void)497 static __inline__ __attribute__((always_inline)) void _enable(void)
498 {
499   __asm__ __volatile__ ("sti");
500 }
501 
502 
__halt(void)503 static __inline__ __attribute__((always_inline)) void __halt(void)
504 {
505   __asm__ __volatile__ ("hlt");
506 }
507 
508 
__debugbreak(void)509 static __inline__ __attribute__((always_inline)) void __debugbreak(void)
510 {
511   __asm__ __volatile__ ("int3");
512 }
513 
__invd(void)514 static __inline__ __attribute__((always_inline)) void __invd(void)
515 {
516   __asm__ __volatile__ ("invd");
517 }
518 
__wbinvd(void)519 static __inline__ __attribute__((always_inline)) void __wbinvd(void)
520 {
521   __asm__ __volatile__ ("wbinvd");
522 }
523 
__lidt(void * Source)524 static __inline__ __attribute__((always_inline)) void __lidt(void *Source)
525 {
526   __asm__ __volatile__("lidt %0" : : "m"(*(short*)Source));
527 }
528 
529 static __inline__ __attribute__((always_inline)) void
__writefsbyte(const unsigned long Offset,const uint8_t Data)530 __writefsbyte(const unsigned long Offset, const uint8_t Data)
531 {
532   __asm__ ("movb %[Data], %%fs:%a[Offset]"
533           :
534           : [Offset] "ir" (Offset), [Data] "iq" (Data));
535 }
536 
537 static __inline__ __attribute__((always_inline)) void
__writefsword(const unsigned long Offset,const uint16_t Data)538 __writefsword(const unsigned long Offset, const uint16_t Data)
539 {
540   __asm__ ("movw %[Data], %%fs:%a[Offset]"
541           :
542           : [Offset] "ir" (Offset), [Data] "ir" (Data));
543 }
544 
545 static __inline__ __attribute__((always_inline)) void
__writefsdword(const unsigned long Offset,const uint32_t Data)546 __writefsdword(const unsigned long Offset, const uint32_t Data)
547 {
548   __asm__ ("movl %[Data], %%fs:%a[Offset]"
549            :
550            : [Offset] "ir" (Offset), [Data] "ir" (Data));
551 }
552 
553 static __inline__ __attribute__((always_inline)) uint8_t
__readfsbyte(const unsigned long Offset)554 __readfsbyte(const unsigned long Offset)
555 {
556   unsigned char value;
557   __asm__ ("movb %%fs:%a[Offset], %[value]"
558           : [value] "=q" (value)
559           : [Offset] "ir" (Offset));
560   return value;
561 }
562 
563 static __inline__ __attribute__((always_inline)) uint16_t
__readfsword(const unsigned long Offset)564 __readfsword(const unsigned long Offset)
565 {
566   unsigned short value;
567   __asm__ ("movw %%fs:%a[Offset], %[value]"
568            : [value] "=q" (value)
569            : [Offset] "ir" (Offset));
570   return value;
571 }
572 
573 static __inline__ __attribute__((always_inline)) uint32_t
__readfsdword(unsigned long Offset)574 __readfsdword(unsigned long Offset)
575 {
576   unsigned long value;
577   __asm__ ("mov %%fs:%a[Offset], %[value]"
578            : [value] "=r" (value)
579            : [Offset] "ir" (Offset));
580   return value;
581 }
582 
583 #ifdef __SSE3__
584 typedef long long __v2di __attribute__((__vector_size__ (16)));
585 typedef long long __m128i __attribute__((__vector_size__ (16), __may_alias__));
586 
_mm_stream_si128_fs2(void * __A,__m128i __B)587 static __inline__ __attribute__((always_inline)) void _mm_stream_si128_fs2 (void *__A, __m128i __B)
588 {
589   __asm__(".byte 0x64"); // fs prefix
590 #if defined(__clang__)
591   __builtin_nontemporal_store((__v2di)__B, (__v2di *)__A);
592 #else
593   __builtin_ia32_movntdq ((__v2di *)__A, (__v2di)__B);
594 #endif
595 }
596 
_mm_stream_si128_fs(void * __A,void * __B)597 static __inline__ __attribute__((always_inline)) void _mm_stream_si128_fs (void *__A, void *__B)
598 {
599   __m128i data;
600   data = (__m128i) __builtin_ia32_lddqu ((char const *)__B);
601   _mm_stream_si128_fs2 (__A, data);
602 }
603 
_mm_clflush_fs(void * __A)604 static __inline__ __attribute__((always_inline)) void _mm_clflush_fs (void *__A)
605 {
606   __asm__(".byte 0x64"); // fs prefix
607   __builtin_ia32_clflush (__A);
608 }
609 
610 #if !defined(__clang__)
_mm_mfence(void)611 static __inline __attribute__(( __always_inline__)) void _mm_mfence (void)
612 {
613   __builtin_ia32_mfence ();
614 }
615 #else
616 void _mm_mfence(void);
617 #endif
618 
619 #if !defined(__clang__)
_mm_sfence(void)620 static __inline __attribute__(( __always_inline__)) void _mm_sfence (void)
621 {
622   __builtin_ia32_sfence ();
623 }
624 #else
625 void _mm_sfence(void);
626 #endif
627 #endif /* __SSE3__ */
628 
629 #endif /* defined (__GNUC__) */
630