Home | History | Annotate | Download | only in cortexm4f
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <atomic.h>
     18 
     19 uint32_t atomicAddByte(volatile uint8_t *byte, uint32_t addend)
     20 {
     21     uint32_t prevVal, storeFailed, tmp;
     22 
     23     do {
     24         asm volatile(
     25             "ldrexb %0,     [%4] \n"
     26             "add    %2, %0, %3   \n"
     27             "strexb %1, %2, [%4] \n"
     28             :"=r"(prevVal), "=r"(storeFailed), "=r"(tmp), "=r"(addend), "=r"(byte)
     29             :"3"(addend), "4"(byte)
     30             :"memory"
     31         );
     32     } while (storeFailed);
     33 
     34     return prevVal;
     35 }
     36 
     37 uint32_t atomicAdd32bits(volatile uint32_t *word, uint32_t addend)
     38 {
     39     uint32_t prevVal, storeFailed, tmp;
     40 
     41     do {
     42         asm volatile(
     43             "ldrex  %0,     [%4] \n"
     44             "add    %2, %0, %3   \n"
     45             "strex  %1, %2, [%4] \n"
     46             :"=r"(prevVal), "=r"(storeFailed), "=r"(tmp), "=r"(addend), "=r"(word)
     47             :"3"(addend), "4"(word)
     48             :"memory"
     49         );
     50     } while (storeFailed);
     51 
     52     return prevVal;
     53 }
     54 
     55 uint32_t atomicXchgByte(volatile uint8_t *byte, uint32_t newVal)
     56 {
     57     uint32_t prevVal, storeFailed;
     58 
     59     do {
     60         asm volatile(
     61             "ldrexb %0,     [%3] \n"
     62             "strexb %1, %2, [%3] \n"
     63             :"=r"(prevVal), "=r"(storeFailed), "=r"(newVal), "=r"(byte)
     64             :"2"(newVal), "3"(byte)
     65             :"memory"
     66         );
     67     } while (storeFailed);
     68 
     69     return prevVal;
     70 }
     71 
     72 uint32_t atomicXchg32bits(volatile uint32_t *word, uint32_t newVal)
     73 {
     74     uint32_t prevVal, storeFailed;
     75 
     76     do {
     77         asm volatile(
     78             "ldrex %0,     [%3] \n"
     79             "strex %1, %2, [%3] \n"
     80             :"=r"(prevVal), "=r"(storeFailed), "=r"(newVal), "=r"(word)
     81             :"2"(newVal), "3"(word)
     82             :"memory"
     83         );
     84     } while (storeFailed);
     85 
     86     return prevVal;
     87 }
     88 
     89 bool atomicCmpXchgByte(volatile uint8_t *byte, uint32_t prevVal, uint32_t newVal)
     90 {
     91     uint32_t currVal, storeFailed;
     92 
     93     do {
     94         asm volatile(
     95             "ldrexb %0,     [%1] \n"
     96             :"=r"(currVal), "=r"(byte)
     97             :"1"(byte)
     98             :"memory"
     99         );
    100 
    101         if (currVal != prevVal)
    102             return false;
    103 
    104         asm volatile(
    105             "strexb %0, %1, [%2] \n"
    106             :"=r"(storeFailed), "=r"(newVal), "=r"(byte)
    107             :"1"(newVal), "2"(byte)
    108             :"memory"
    109         );
    110     } while (storeFailed);
    111 
    112     return true;
    113 }
    114 
    115 bool atomicCmpXchg32bits(volatile uint32_t *word, uint32_t prevVal, uint32_t newVal)
    116 {
    117     uint32_t currVal, storeFailed;
    118 
    119     do {
    120         asm volatile(
    121             "ldrex %0,     [%1] \n"
    122             :"=r"(currVal), "=r"(word)
    123             :"1"(word)
    124             :"memory"
    125         );
    126 
    127         if (currVal != prevVal)
    128             return false;
    129 
    130         asm volatile(
    131             "strex %0, %1, [%2] \n"
    132             :"=r"(storeFailed), "=r"(newVal), "=r"(word)
    133             :"1"(newVal), "2"(word)
    134             :"memory"
    135         );
    136     } while (storeFailed);
    137 
    138     return true;
    139 }
    140