]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/CpuIoDxe/Ia32/CpuIoAccessGNU.c
Fix build issue in linux environment.
[mirror_edk2.git] / DuetPkg / CpuIoDxe / Ia32 / CpuIoAccessGNU.c
CommitLineData
a04ef65d 1/* This file is only used when not able to compile the MASM CpuIoAccess.asm\r
2 NOTE: Compiling with -fomit-frame-pointer would get you to roughly the exact\r
3 same code as the MASM file although GCC will typically include movzbl %al, %eax\r
4 or movzwl %ax, %eax instructions on the read functions such that the entire\r
5 eax result register will be valid, not just the lowest 8 or 16 bits.\r
6 */\r
7#ifdef __GNUC__\r
8\r
9/* A quick note about GCC inline asm and the GNU assembler:\r
10 When gas encounters an instruction with a suffix (e.g. inb, inw, or inl vs. just in) it will\r
11 warn if the operand corresponding to the suffix is not of the correct size and will assume you\r
12 meant what you said when you specified the suffix.\r
13\r
14 Because GCC does not enable us to see whether it is replacing %0 with %al, %ax, or %eax it is\r
15 helpful to have the assembler warn us that GCC is making an incorrect assumption. The actual\r
16 in or out instruction will always be generated correctly in this case since the assembler is\r
17 correct in assuming we meant what we said when we specified the suffix. However, GCC might\r
18 generate incorrect surrounding code. For example, if we were to incorrectly specify the\r
19 output size of an in instruction as UINT32, GCC would potentially fail to issue movz(b|w)l after\r
20 it under the assumption that the in instruction filled the entire eax register and not just\r
21 the al or ax portion.\r
22\r
23 GCC determines which size of register to use based on the C data type. So for in instructions\r
24 the interesting type is that of the automatic variable named Data which is specified as an\r
25 output operand to the inline assembly statement. For example:\r
26\r
27 UINT8 Data;\r
28 asm ( "inb %1, %0"\r
29 : "=a"(Data)\r
30 : "d"(Port)\r
31 );\r
32 return Data;\r
33\r
34 In this case, GCC will replace %0 with %al. If Data had been specified as UINT16, it would replace\r
35 %0 with %ax, and for UINT32 with %eax.\r
36\r
37 Likewise in the case of IA32 out instructions, GCC will replace %0 with the appropriately sized\r
38 register based on the size of the input operand. There is one gotcha though. The CpuIoWrite\r
39 series of functions all use UINT32 as the type of the second (Data) argument. This means that\r
40 for GCC to output the correct register size we must cast it appropriately.\r
41\r
42 The Port number is always a UINT16 so GCC will always ouput %dx.\r
43 */\r
44\r
45#include "CpuIoAccess.h"\r
46\r
47UINT8\r
d8bee43c 48EFIAPI\r
a04ef65d 49CpuIoRead8 (\r
50 IN UINT16 Port\r
51 )\r
52{\r
53 UINT8 Data;\r
54 asm ( "inb %1, %0"\r
55 : "=a"(Data)\r
56 : "d"(Port)\r
57 );\r
58 return Data;\r
59}\r
60\r
61UINT16\r
d8bee43c 62EFIAPI\r
a04ef65d 63CpuIoRead16 (\r
64 IN UINT16 Port\r
65 )\r
66{\r
67 UINT16 Data;\r
68 asm ( "inw %1, %0"\r
69 : "=a"(Data)\r
70 : "d"(Port)\r
71 );\r
72 return Data;\r
73}\r
74\r
75UINT32\r
d8bee43c 76EFIAPI\r
a04ef65d 77CpuIoRead32 (\r
78 IN UINT16 Port\r
79 )\r
80{\r
81 UINT32 Data;\r
82 asm ( "inl %1, %0"\r
83 : "=a"(Data)\r
84 : "d"(Port)\r
85 );\r
86 return Data;\r
87}\r
88\r
89VOID\r
d8bee43c 90EFIAPI\r
a04ef65d 91CpuIoWrite8 (\r
92 IN UINT16 Port,\r
93 IN UINT32 Data\r
94 )\r
95{\r
96 asm ( "outb %1, %0"\r
97 : /* No outputs */\r
98 : "d"(Port)\r
99 , "a"((UINT8)Data)\r
100 );\r
101}\r
102\r
103VOID\r
d8bee43c 104EFIAPI\r
a04ef65d 105CpuIoWrite16 (\r
106 IN UINT16 Port,\r
107 IN UINT32 Data\r
108 )\r
109{\r
110 asm ( "outw %1, %0"\r
111 : /* No outputs */\r
112 : "d"(Port)\r
113 , "a"((UINT16)Data)\r
114 );\r
115}\r
116\r
117VOID\r
d8bee43c 118EFIAPI\r
a04ef65d 119CpuIoWrite32 (\r
120 IN UINT16 Port,\r
121 IN UINT32 Data\r
122 )\r
123{\r
124 asm ( "outl %1, %0"\r
125 : /* No outputs */\r
126 : "d"(Port)\r
127 /* NOTE: Cast is technically unnecessary but we use it to illustrate\r
128 that we always want to output a UINT32 and never anything else.\r
129 */\r
130 , "a"((UINT32)Data) \r
131 );\r
132}\r
133\r
134#endif /* def __GNUC__ */\r