--- /dev/null
+/** @file\r
+ LoongArch synchronization functions.\r
+\r
+ Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include <Library/DebugLib.h>\r
+\r
+UINT32\r
+EFIAPI\r
+AsmInternalSyncCompareExchange16 (\r
+ IN volatile UINT32 *,\r
+ IN UINT64,\r
+ IN UINT64,\r
+ IN UINT64\r
+ );\r
+\r
+UINT32\r
+EFIAPI\r
+AsmInternalSyncCompareExchange32 (\r
+ IN volatile UINT32 *,\r
+ IN UINT64,\r
+ IN UINT64\r
+ );\r
+\r
+UINT64\r
+EFIAPI\r
+AsmInternalSyncCompareExchange64 (\r
+ IN volatile UINT64 *,\r
+ IN UINT64,\r
+ IN UINT64\r
+ );\r
+\r
+UINT32\r
+EFIAPI\r
+AsmInternalSyncIncrement (\r
+ IN volatile UINT32 *\r
+ );\r
+\r
+UINT32\r
+EFIAPI\r
+AsmInternalSyncDecrement (\r
+ IN volatile UINT32 *\r
+ );\r
+\r
+/**\r
+ Performs an atomic compare exchange operation on a 16-bit\r
+ unsigned integer.\r
+\r
+ Performs an atomic compare exchange operation on the 16-bit\r
+ unsigned integer specified by Value. If Value is equal to\r
+ CompareValue, then Value is set to ExchangeValue and\r
+ CompareValue is returned. If Value is not equal to\r
+ CompareValue, then Value is returned. The compare exchange\r
+ operation must be performed using MP safe mechanisms.\r
+\r
+ @param[in] Value A pointer to the 16-bit value for the\r
+ compare exchange operation.\r
+ @param[in] CompareValue 16-bit value used in compare operation.\r
+ @param[in] 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
+{\r
+ UINT32 RetValue;\r
+ UINT32 Shift;\r
+ UINT64 Mask;\r
+ UINT64 LocalCompareValue;\r
+ UINT64 LocalExchangeValue;\r
+ volatile UINT32 *Ptr32;\r
+\r
+ /* Check that ptr is naturally aligned */\r
+ ASSERT (!((UINT64)Value & (sizeof (Value) - 1)));\r
+\r
+ /* Mask inputs to the correct size. */\r
+ Mask = (((~0UL) - (1UL << (0)) + 1) & (~0UL >> (64 - 1 - ((sizeof (UINT16) * 8) - 1))));\r
+ LocalCompareValue = ((UINT64)CompareValue) & Mask;\r
+ LocalExchangeValue = ((UINT64)ExchangeValue) & Mask;\r
+\r
+ /*\r
+ * Calculate a shift & mask that correspond to the value we wish to\r
+ * compare & exchange within the naturally aligned 4 byte integer\r
+ * that includes it.\r
+ */\r
+ Shift = (UINT64)Value & 0x3;\r
+ Shift *= 8; /* BITS_PER_BYTE */\r
+ LocalCompareValue <<= Shift;\r
+ LocalExchangeValue <<= Shift;\r
+ Mask <<= Shift;\r
+\r
+ /*\r
+ * Calculate a pointer to the naturally aligned 4 byte integer that\r
+ * includes our byte of interest, and load its value.\r
+ */\r
+ Ptr32 = (UINT32 *)((UINT64)Value & ~0x3);\r
+\r
+ RetValue = AsmInternalSyncCompareExchange16 (\r
+ Ptr32,\r
+ Mask,\r
+ LocalCompareValue,\r
+ LocalExchangeValue\r
+ );\r
+\r
+ return (RetValue & Mask) >> Shift;\r
+}\r
+\r
+/**\r
+ Performs an atomic compare exchange operation on a 32-bit\r
+ unsigned integer.\r
+\r
+ Performs an atomic compare exchange operation on the 32-bit\r
+ unsigned integer specified by Value. If Value is equal to\r
+ CompareValue, then Value is set to ExchangeValue and\r
+ CompareValue is returned. If Value is not equal to\r
+ CompareValue, then Value is returned. The compare exchange\r
+ operation must be performed using MP safe mechanisms.\r
+\r
+ @param[in] Value A pointer to the 32-bit value for the\r
+ compare exchange operation.\r
+ @param[in] CompareValue 32-bit value used in compare operation.\r
+ @param[in] 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
+{\r
+ UINT32 RetValue;\r
+\r
+ RetValue = AsmInternalSyncCompareExchange32 (\r
+ Value,\r
+ CompareValue,\r
+ ExchangeValue\r
+ );\r
+\r
+ return RetValue;\r
+}\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[in] Value A pointer to the 64-bit value for the compare exchange\r
+ operation.\r
+ @param[in] CompareValue 64-bit value used in compare operation.\r
+ @param[in] 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
+{\r
+ UINT64 RetValue;\r
+\r
+ RetValue = AsmInternalSyncCompareExchange64 (\r
+ Value,\r
+ CompareValue,\r
+ ExchangeValue\r
+ );\r
+\r
+ return RetValue;\r
+}\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[in] 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
+{\r
+ return AsmInternalSyncIncrement (Value);\r
+}\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[in] 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
+{\r
+ return AsmInternalSyncDecrement (Value);\r
+}\r