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