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