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