1//  Implementation of synchronization functions for ARM architecture
2//
3//  Copyright (c) 2012-2015, ARM Limited. All rights reserved.
4//  Copyright (c) 2015, Linaro Limited. All rights reserved.
5//
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    EXPORT  InternalSyncCompareExchange16
17    EXPORT  InternalSyncCompareExchange32
18    EXPORT  InternalSyncCompareExchange64
19    EXPORT  InternalSyncIncrement
20    EXPORT  InternalSyncDecrement
21
22    AREA   ArmSynchronization, CODE, READONLY
23
24/**
25  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
26
27  Performs an atomic compare exchange operation on the 16-bit unsigned integer
28  specified by Value.  If Value is equal to CompareValue, then Value is set to
29  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
30  then Value is returned.  The compare exchange operation must be performed using
31  MP safe mechanisms.
32
33  @param  Value         A pointer to the 16-bit value for the compare exchange
34                        operation.
35  @param  CompareValue  16-bit value used in compare operation.
36  @param  ExchangeValue 16-bit value used in exchange operation.
37
38  @return The original *Value before exchange.
39
40**/
41//UINT16
42//EFIAPI
43//InternalSyncCompareExchange16 (
44//  IN      volatile UINT16           *Value,
45//  IN      UINT16                    CompareValue,
46//  IN      UINT16                    ExchangeValue
47//  )
48InternalSyncCompareExchange16
49  dmb
50
51InternalSyncCompareExchange16Again
52  ldrexh  r3, [r0]
53  cmp     r3, r1
54  bne     InternalSyncCompareExchange16Fail
55
56InternalSyncCompareExchange16Exchange
57  strexh  ip, r2, [r0]
58  cmp     ip, #0
59  bne     InternalSyncCompareExchange16Again
60
61InternalSyncCompareExchange16Fail
62  dmb
63  mov     r0, r3
64  bx      lr
65
66/**
67  Performs an atomic compare exchange operation on a 32-bit unsigned integer.
68
69  Performs an atomic compare exchange operation on the 32-bit unsigned integer
70  specified by Value.  If Value is equal to CompareValue, then Value is set to
71  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
72  then Value is returned.  The compare exchange operation must be performed using
73  MP safe mechanisms.
74
75  @param  Value         A pointer to the 32-bit value for the compare exchange
76                        operation.
77  @param  CompareValue  32-bit value used in compare operation.
78  @param  ExchangeValue 32-bit value used in exchange operation.
79
80  @return The original *Value before exchange.
81
82**/
83//UINT32
84//EFIAPI
85//InternalSyncCompareExchange32 (
86//  IN      volatile UINT32           *Value,
87//  IN      UINT32                    CompareValue,
88//  IN      UINT32                    ExchangeValue
89//  )
90InternalSyncCompareExchange32
91  dmb
92
93InternalSyncCompareExchange32Again
94  ldrex   r3, [r0]
95  cmp     r3, r1
96  bne     InternalSyncCompareExchange32Fail
97
98InternalSyncCompareExchange32Exchange
99  strex   ip, r2, [r0]
100  cmp     ip, #0
101  bne     InternalSyncCompareExchange32Again
102
103InternalSyncCompareExchange32Fail
104  dmb
105  mov     r0, r3
106  bx      lr
107
108/**
109  Performs an atomic compare exchange operation on a 64-bit unsigned integer.
110
111  Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
112  by Value.  If Value is equal to CompareValue, then Value is set to ExchangeValue and
113  CompareValue is returned.  If Value is not equal to CompareValue, then Value is returned.
114  The compare exchange operation must be performed using MP safe mechanisms.
115
116  @param  Value         A pointer to the 64-bit value for the compare exchange
117                        operation.
118  @param  CompareValue  64-bit value used in compare operation.
119  @param  ExchangeValue 64-bit value used in exchange operation.
120
121  @return The original *Value before exchange.
122
123**/
124//UINT64
125//EFIAPI
126//InternalSyncCompareExchange64 (
127//  IN      volatile UINT64           *Value,         // r0
128//  IN      UINT64                    CompareValue,   // r2-r3
129//  IN      UINT64                    ExchangeValue   // stack
130//  )
131InternalSyncCompareExchange64
132  push    { r4-r7 }
133  ldrd    r4, r5, [sp, #16]
134  dmb
135
136InternalSyncCompareExchange64Again
137  ldrexd  r6, r7, [r0]
138  cmp     r6, r2
139  cmpeq   r7, r3
140  bne     InternalSyncCompareExchange64Fail
141
142InternalSyncCompareExchange64Exchange
143  strexd  ip, r4, r5, [r0]
144  cmp     ip, #0
145  bne     InternalSyncCompareExchange64Again
146
147InternalSyncCompareExchange64Fail
148  dmb
149  mov     r0, r6
150  mov     r1, r7
151  pop     { r4-r7 }
152  bx      lr
153
154/**
155  Performs an atomic increment of an 32-bit unsigned integer.
156
157  Performs an atomic increment of the 32-bit unsigned integer specified by
158  Value and returns the incremented value. The increment operation must be
159  performed using MP safe mechanisms. The state of the return value is not
160  guaranteed to be MP safe.
161
162  @param  Value A pointer to the 32-bit value to increment.
163
164  @return The incremented value.
165
166**/
167//UINT32
168//EFIAPI
169//InternalSyncIncrement (
170//  IN      volatile UINT32           *Value
171//  )
172InternalSyncIncrement
173  dmb
174TryInternalSyncIncrement
175  ldrex   r1, [r0]
176  add     r1, r1, #1
177  strex   r2, r1, [r0]
178  cmp     r2, #0
179  bne     TryInternalSyncIncrement
180  dmb
181  mov     r0, r1
182  bx      lr
183
184/**
185  Performs an atomic decrement of an 32-bit unsigned integer.
186
187  Performs an atomic decrement of the 32-bit unsigned integer specified by
188  Value and returns the decrement value. The decrement operation must be
189  performed using MP safe mechanisms. The state of the return value is not
190  guaranteed to be MP safe.
191
192  @param  Value A pointer to the 32-bit value to decrement.
193
194  @return The decrement value.
195
196**/
197//UINT32
198//EFIAPI
199//InternalSyncDecrement (
200//  IN      volatile UINT32           *Value
201//  )
202InternalSyncDecrement
203  dmb
204TryInternalSyncDecrement
205  ldrex   r1, [r0]
206  sub     r1, r1, #1
207  strex   r2, r1, [r0]
208  cmp     r2, #0
209  bne     TryInternalSyncDecrement
210  dmb
211  mov     r0, r1
212  bx      lr
213
214  END
215