Home | History | Annotate | Download | only in Arm
      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 
     19 GCC_ASM_EXPORT(InternalSyncCompareExchange16)
     20 GCC_ASM_EXPORT(InternalSyncCompareExchange32)
     21 GCC_ASM_EXPORT(InternalSyncCompareExchange64)
     22 GCC_ASM_EXPORT(InternalSyncIncrement)
     23 GCC_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 //  )
     49 ASM_PFX(InternalSyncCompareExchange16):
     50   dmb
     51 
     52 InternalSyncCompareExchange16Again:
     53   ldrexh  r3, [r0]
     54   cmp     r3, r1
     55   bne     InternalSyncCompareExchange16Fail
     56 
     57 InternalSyncCompareExchange16Exchange:
     58   strexh  ip, r2, [r0]
     59   cmp     ip, #0
     60   bne     InternalSyncCompareExchange16Again
     61 
     62 InternalSyncCompareExchange16Fail:
     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 //  )
     91 ASM_PFX(InternalSyncCompareExchange32):
     92   dmb
     93 
     94 InternalSyncCompareExchange32Again:
     95   ldrex   r3, [r0]
     96   cmp     r3, r1
     97   bne     InternalSyncCompareExchange32Fail
     98 
     99 InternalSyncCompareExchange32Exchange:
    100   strex   ip, r2, [r0]
    101   cmp     ip, #0
    102   bne     InternalSyncCompareExchange32Again
    103 
    104 InternalSyncCompareExchange32Fail:
    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 //  )
    132 ASM_PFX(InternalSyncCompareExchange64):
    133   push    { r4-r7 }
    134   ldrd    r4, r5, [sp, #16]
    135   dmb
    136 
    137 InternalSyncCompareExchange64Again:
    138   ldrexd  r6, r7, [r0]
    139   cmp     r6, r2
    140   cmpeq   r7, r3
    141   bne     InternalSyncCompareExchange64Fail
    142 
    143 InternalSyncCompareExchange64Exchange:
    144   strexd  ip, r4, r5, [r0]
    145   cmp     ip, #0
    146   bne     InternalSyncCompareExchange64Again
    147 
    148 InternalSyncCompareExchange64Fail:
    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 //  )
    173 ASM_PFX(InternalSyncIncrement):
    174   dmb
    175 TryInternalSyncIncrement:
    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 //  )
    203 ASM_PFX(InternalSyncDecrement):
    204   dmb
    205 TryInternalSyncDecrement:
    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