+; Implementation of synchronization functions for ARM architecture (AArch64)\r
+;\r
+; Copyright (c) 2012-2015, ARM Limited. All rights reserved.\r
+; Copyright (c) 2015, Linaro Limited. All rights reserved.\r
+;\r
+; This program and the accompanying materials\r
+; are licensed and made available under the terms and conditions of the BSD License\r
+; which accompanies this distribution. The full text of the license may be found at\r
+; http://opensource.org/licenses/bsd-license.php\r
+;\r
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+;\r
+;\r
+\r
+ EXPORT InternalSyncCompareExchange16\r
+ EXPORT InternalSyncCompareExchange32\r
+ EXPORT InternalSyncCompareExchange64\r
+ EXPORT InternalSyncIncrement\r
+ EXPORT InternalSyncDecrement\r
+ AREA BaseSynchronizationLib_LowLevel, CODE, READONLY\r
+\r
+;/**\r
+; Performs an atomic compare exchange operation on a 16-bit unsigned integer.\r
+;\r
+; Performs an atomic compare exchange operation on the 16-bit unsigned integer\r
+; specified by Value. If Value is equal to CompareValue, then Value is set to\r
+; ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,\r
+; then Value is returned. The compare exchange operation must be performed using\r
+; MP safe mechanisms.\r
+;\r
+; @param Value A pointer to the 16-bit value for the compare exchange\r
+; operation.\r
+; @param CompareValue 16-bit value used in compare operation.\r
+; @param ExchangeValue 16-bit value used in exchange operation.\r
+;\r
+; @return The original *Value before exchange.\r
+;\r
+;**/\r
+;UINT16\r
+;EFIAPI\r
+;InternalSyncCompareExchange16 (\r
+; IN volatile UINT16 *Value,\r
+; IN UINT16 CompareValue,\r
+; IN UINT16 ExchangeValue\r
+; )\r
+InternalSyncCompareExchange16\r
+ uxth w1, w1\r
+ uxth w2, w2\r
+ dmb sy\r
+\r
+InternalSyncCompareExchange16Again\r
+ ldxrh w3, [x0]\r
+ cmp w3, w1\r
+ bne InternalSyncCompareExchange16Fail\r
+\r
+InternalSyncCompareExchange16Exchange\r
+ stxrh w4, w2, [x0]\r
+ cbnz w4, InternalSyncCompareExchange16Again\r
+\r
+InternalSyncCompareExchange16Fail\r
+ dmb sy\r
+ mov w0, w3\r
+ ret\r
+\r
+;/**\r
+; Performs an atomic compare exchange operation on a 32-bit unsigned integer.\r
+;\r
+; Performs an atomic compare exchange operation on the 32-bit unsigned integer\r
+; specified by Value. If Value is equal to CompareValue, then Value is set to\r
+; ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,\r
+; then Value is returned. The compare exchange operation must be performed using\r
+; MP safe mechanisms.\r
+;\r
+; @param Value A pointer to the 32-bit value for the compare exchange\r
+; operation.\r
+; @param CompareValue 32-bit value used in compare operation.\r
+; @param ExchangeValue 32-bit value used in exchange operation.\r
+;\r
+; @return The original *Value before exchange.\r
+;\r
+;**/\r
+;UINT32\r
+;EFIAPI\r
+;InternalSyncCompareExchange32 (\r
+; IN volatile UINT32 *Value,\r
+; IN UINT32 CompareValue,\r
+; IN UINT32 ExchangeValue\r
+; )\r
+InternalSyncCompareExchange32\r
+ dmb sy\r
+\r
+InternalSyncCompareExchange32Again\r
+ ldxr w3, [x0]\r
+ cmp w3, w1\r
+ bne InternalSyncCompareExchange32Fail\r
+\r
+InternalSyncCompareExchange32Exchange\r
+ stxr w4, w2, [x0]\r
+ cbnz w4, InternalSyncCompareExchange32Again\r
+\r
+InternalSyncCompareExchange32Fail\r
+ dmb sy\r
+ mov w0, w3\r
+ ret\r
+\r
+;/**\r
+; Performs an atomic compare exchange operation on a 64-bit unsigned integer.\r
+;\r
+; Performs an atomic compare exchange operation on the 64-bit unsigned integer specified\r
+; by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and\r
+; CompareValue is returned. If Value is not equal to CompareValue, then Value is returned.\r
+; The compare exchange operation must be performed using MP safe mechanisms.\r
+;\r
+; @param Value A pointer to the 64-bit value for the compare exchange\r
+; operation.\r
+; @param CompareValue 64-bit value used in compare operation.\r
+; @param ExchangeValue 64-bit value used in exchange operation.\r
+;\r
+; @return The original *Value before exchange.\r
+;\r
+;**/\r
+;UINT64\r
+;EFIAPI\r
+;InternalSyncCompareExchange64 (\r
+; IN volatile UINT64 *Value,\r
+; IN UINT64 CompareValue,\r
+; IN UINT64 ExchangeValue\r
+; )\r
+InternalSyncCompareExchange64\r
+ dmb sy\r
+\r
+InternalSyncCompareExchange64Again\r
+ ldxr x3, [x0]\r
+ cmp x3, x1\r
+ bne InternalSyncCompareExchange64Fail\r
+\r
+InternalSyncCompareExchange64Exchange\r
+ stxr w4, x2, [x0]\r
+ cbnz w4, InternalSyncCompareExchange64Again\r
+\r
+InternalSyncCompareExchange64Fail\r
+ dmb sy\r
+ mov x0, x3\r
+ ret\r
+\r
+;/**\r
+; Performs an atomic increment of an 32-bit unsigned integer.\r
+;\r
+; Performs an atomic increment of the 32-bit unsigned integer specified by\r
+; Value and returns the incremented value. The increment operation must be\r
+; performed using MP safe mechanisms. The state of the return value is not\r
+; guaranteed to be MP safe.\r
+;\r
+; @param Value A pointer to the 32-bit value to increment.\r
+;\r
+; @return The incremented value.\r
+;\r
+;**/\r
+;UINT32\r
+;EFIAPI\r
+;InternalSyncIncrement (\r
+; IN volatile UINT32 *Value\r
+; )\r
+InternalSyncIncrement\r
+ dmb sy\r
+TryInternalSyncIncrement\r
+ ldxr w1, [x0]\r
+ add w1, w1, #1\r
+ stxr w2, w1, [x0]\r
+ cbnz w2, TryInternalSyncIncrement\r
+ mov w0, w1\r
+ dmb sy\r
+ ret\r
+\r
+;/**\r
+; Performs an atomic decrement of an 32-bit unsigned integer.\r
+;\r
+; Performs an atomic decrement of the 32-bit unsigned integer specified by\r
+; Value and returns the decrement value. The decrement operation must be\r
+; performed using MP safe mechanisms. The state of the return value is not\r
+; guaranteed to be MP safe.\r
+;\r
+; @param Value A pointer to the 32-bit value to decrement.\r
+;\r
+; @return The decrement value.\r
+;\r
+;**/\r
+;UINT32\r
+;EFIAPI\r
+;InternalSyncDecrement (\r
+; IN volatile UINT32 *Value\r
+; )\r
+InternalSyncDecrement\r
+ dmb sy\r
+TryInternalSyncDecrement\r
+ ldxr w1, [x0]\r
+ sub w1, w1, #1\r
+ stxr w2, w1, [x0]\r
+ cbnz w2, TryInternalSyncDecrement\r
+ mov w0, w1\r
+ dmb sy\r
+ ret\r
+\r
+ END\r