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