1/** @file
2  GCC inline implementation of BaseSynchronizationLib processor specific functions.
3
4  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6  This program and the accompanying materials
7  are licensed and made available under the terms and conditions of the BSD License
8  which accompanies this distribution.  The full text of the license may be found at
9  http://opensource.org/licenses/bsd-license.php.
10
11  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16
17
18/**
19  Performs an atomic increment of an 32-bit unsigned integer.
20
21  Performs an atomic increment of the 32-bit unsigned integer specified by
22  Value and returns the incremented value. The increment operation must be
23  performed using MP safe mechanisms. The state of the return value is not
24  guaranteed to be MP safe.
25
26  @param  Value A pointer to the 32-bit value to increment.
27
28  @return The incremented value.
29
30**/
31UINT32
32EFIAPI
33InternalSyncIncrement (
34  IN      volatile UINT32    *Value
35  )
36{
37  UINT32  Result;
38
39  __asm__ __volatile__ (
40    "lock               \n\t"
41    "incl    %2         \n\t"
42    "movl    %2, %%eax      "
43    : "=a" (Result),          // %0
44      "=m" (*Value)           // %1
45    : "m"  (*Value)           // %2
46    : "memory",
47      "cc"
48    );
49
50  return Result;
51
52}
53
54
55/**
56  Performs an atomic decrement of an 32-bit unsigned integer.
57
58  Performs an atomic decrement of the 32-bit unsigned integer specified by
59  Value and returns the decremented value. The decrement operation must be
60  performed using MP safe mechanisms. The state of the return value is not
61  guaranteed to be MP safe.
62
63  @param  Value A pointer to the 32-bit value to decrement.
64
65  @return The decremented value.
66
67**/
68UINT32
69EFIAPI
70InternalSyncDecrement (
71  IN      volatile UINT32       *Value
72  )
73{
74   UINT32  Result;
75
76  __asm__ __volatile__ (
77    "lock               \n\t"
78    "decl    %2         \n\t"
79    "movl    %2, %%eax      "
80    : "=a" (Result),          // %0
81      "=m" (*Value)           // %1
82    : "m"  (*Value)           // %2
83    : "memory",
84      "cc"
85    );
86
87  return Result;
88}
89
90/**
91  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
92
93  Performs an atomic compare exchange operation on the 16-bit unsigned integer
94  specified by Value.  If Value is equal to CompareValue, then Value is set to
95  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
96  then Value is returned.  The compare exchange operation must be performed using
97  MP safe mechanisms.
98
99
100  @param  Value         A pointer to the 16-bit value for the compare exchange
101                        operation.
102  @param  CompareValue  16-bit value used in compare operation.
103  @param  ExchangeValue 16-bit value used in exchange operation.
104
105  @return The original *Value before exchange.
106
107**/
108UINT16
109EFIAPI
110InternalSyncCompareExchange16 (
111  IN OUT volatile  UINT16           *Value,
112  IN      UINT16                    CompareValue,
113  IN      UINT16                    ExchangeValue
114  )
115{
116
117  __asm__ __volatile__ (
118    "                     \n\t"
119    "lock                 \n\t"
120    "cmpxchgw    %1, %2   \n\t"
121    : "=a" (CompareValue)
122    : "q"  (ExchangeValue),
123      "m"  (*Value),
124      "0"  (CompareValue)
125    : "memory",
126      "cc"
127    );
128
129  return CompareValue;
130}
131
132/**
133  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
134
135  Performs an atomic compare exchange operation on the 32-bit unsigned integer
136  specified by Value.  If Value is equal to CompareValue, then Value is set to
137  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
138  then Value is returned.  The compare exchange operation must be performed using
139  MP safe mechanisms.
140
141
142  @param  Value         A pointer to the 32-bit value for the compare exchange
143                        operation.
144  @param  CompareValue  32-bit value used in compare operation.
145  @param  ExchangeValue 32-bit value used in exchange operation.
146
147  @return The original *Value before exchange.
148
149**/
150UINT32
151EFIAPI
152InternalSyncCompareExchange32 (
153  IN OUT volatile  UINT32           *Value,
154  IN      UINT32                    CompareValue,
155  IN      UINT32                    ExchangeValue
156  )
157{
158
159  __asm__ __volatile__ (
160    "                     \n\t"
161    "lock                 \n\t"
162    "cmpxchgl    %1, %2   \n\t"
163    : "=a" (CompareValue)     // %0
164    : "q"  (ExchangeValue),   // %1
165      "m"  (*Value),          // %2
166      "0"  (CompareValue)     // %4
167    : "memory",
168      "cc"
169    );
170
171  return CompareValue;
172}
173
174/**
175  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
176
177  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
178  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
179  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
180  The compare exchange operation must be performed using MP safe mechanisms.
181
182
183  @param  Value         A pointer to the 64-bit value for the compare exchange
184                        operation.
185  @param  CompareValue  64-bit value used in compare operation.
186  @param  ExchangeValue 64-bit value used in exchange operation.
187
188  @return The original *Value before exchange.
189
190**/
191UINT64
192EFIAPI
193InternalSyncCompareExchange64 (
194  IN OUT  volatile UINT64           *Value,
195  IN      UINT64                    CompareValue,
196  IN      UINT64                    ExchangeValue
197  )
198{
199  __asm__ __volatile__ (
200    "                       \n\t"
201    "push        %%ebx      \n\t"
202    "movl        %2,%%ebx   \n\t"
203    "lock                   \n\t"
204    "cmpxchg8b   (%1)       \n\t"
205    "pop         %%ebx      \n\t"
206    : "+A"  (CompareValue)                    // %0
207    : "S"   (Value),                          // %1
208      "r"   ((UINT32) ExchangeValue),         // %2
209      "c"   ((UINT32) (ExchangeValue >> 32))  // %3
210    : "memory",
211      "cc"
212    );
213
214  return CompareValue;
215}
216