atomic 5.69 KB
Newer Older
Ben Avison's avatar
Ben Avison committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
;
; Copyright (c) 2012, Ben Avison
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;     * Redistributions of source code must retain the above copyright
;       notice, this list of conditions and the following disclaimer.
;     * Redistributions in binary form must reproduce the above copyright
;       notice, this list of conditions and the following disclaimer in the
;       documentation and/or other materials provided with the distribution.
;     * Neither the name of the copyright holder nor the names of their
;       contributors may be used to endorse or promote products derived from
;       this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;

        GET     ListOpts
        GET     Macros
        GET     System
        GET     CPU/Arch
        GET     APCS/$APCS
33 34
        GET     ./init.hdr
        GET     ./vars.hdr
Ben Avison's avatar
Ben Avison committed
35 36 37 38 39 40

Strex_Succeeded *       0
Strex_Failed    *       1

        AREA    |Asm$$Code|, CODE, READONLY

41
        IF (SupportARMv6 :LAND: NoARMv6) :LOR: (SupportARMK :LAND: NoARMK) ; i.e. run-time detection is required
Ben Avison's avatar
Ben Avison committed
42 43 44 45 46
        EXPORT  atomic_init
atomic_init ROUT
      [ zM
        StaticBaseFromSL a4
      ]
47
      [ SupportARMv6 :LAND: NoARMv6
Ben Avison's avatar
Ben Avison committed
48 49 50 51 52 53 54
        ADR     a2, atomic_update_uniproc
        ADR     a3, atomic_process_uniproc
        TST     a1, #CPU_Exclusive
        ADRNE   a2, atomic_update_smp
        ADRNE   a3, atomic_process_smp
        Store   a2, a4, update_fn, ip
        Store   a3, a4, process_fn, ip
55 56 57 58 59 60 61
      ]
      [ SupportARMK :LAND: NoARMK
        ADR     a2, atomic_update_byte_uniproc
        TST     a1, #CPU_ExclusiveB
        ADRNE   a2, atomic_update_byte_smp
        Store   a2, a4, update_byte_fn, ip
      ]
Ben Avison's avatar
Ben Avison committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
        Return  , LinkNotStacked
        ENDIF


        IF :LNOT: SupportARMv6
atomic_update * atomic_update_uniproc
atomic_process * atomic_process_uniproc
        ELIF :LNOT: NoARMv6
atomic_update * atomic_update_smp
atomic_process * atomic_process_smp
        ELSE
atomic_update ROUT
      [ zM
        StaticBaseFromSL a4
      ]
        Load    pc, a4, update_fn, ip
atomic_process ROUT
      [ zM
        StaticBaseFromSL a4
      ]
        Load    pc, a4, process_fn, ip
        ENDIF

85 86 87 88 89 90 91 92 93 94 95 96
        IF :LNOT: SupportARMK
atomic_update_byte * atomic_update_byte_uniproc
        ELIF :LNOT: NoARMv6
atomic_update_byte * atomic_update_byte_smp
        ELSE
atomic_update_byte ROUT
      [ zM
        StaticBaseFromSL a4
      ]
        Load    pc, a4, update_byte_fn, ip
        ENDIF

Ben Avison's avatar
Ben Avison committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

        IF NoARMv6

atomic_update_uniproc ROUT
        ; Let's not worry about ARM2 support
        SWP     a1, a1, [a2]
        Return  , LinkNotStacked

atomic_process_uniproc ROUT
        FunctionEntry "v1-v3"
        MOV     ip, a1
        MOV     v1, a3
        MRS     v2, CPSR
        ORR     a4, v2, #I32_bit
        MSR     CPSR_c, a4 ; IRQs now disabled
        LDR     a1, [a3]
        MOV     v3, a1
        MOV     lr, pc
        MOV     pc, ip
        STR     a1, [v1]
        MSR     CPSR_c, v2
        MOV     a1, v3
        Return  "v1-v3"

        ENDIF

123 124 125 126 127 128 129 130 131
        IF NoARMK

atomic_update_byte_uniproc ROUT
        ; Let's not worry about ARM2 support
        SWPB    a1, a1, [a2]
        Return  , LinkNotStacked

        ENDIF

Ben Avison's avatar
Ben Avison committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147

        IF SupportARMv6

atomic_update_smp ROUT
        MOV     a3, a1
01      LDREX   a1, [a2]
        STREX   a4, a3, [a2]
        TEQ     a4, #Strex_Failed
        BEQ     %B01 ; another exclusive access happened between LDREX and STREX
        Return  , LinkNotStacked

atomic_process_smp ROUT
        FunctionEntry "v1-v4"
        MOV     v3, a3
        MOV     v2, a2
        MOV     v1, a1
148 149 150 151
        ; The process function may affect the state of the exclusive monitor,
        ; so we must perform the LDREX-STREX in one go afterwards (manually
        ; checking [v3] for any changes that happened during the function call)
01      LDR     a1, [v3]
Ben Avison's avatar
Ben Avison committed
152 153 154
        MOV     a2, v2
        MOV     v4, a1
        BLX     v1 ; any CPU that has LDREX will have BLX too
155 156 157 158 159
        LDREX   a2, [v3]
        TEQ     a2, v4
        STREXEQ ip, a1, [v3]
        TEQEQ   ip, #Strex_Succeeded
        BNE     %B01 ; another exclusive access happened between LDR and STREX
Ben Avison's avatar
Ben Avison committed
160 161 162 163 164
        MOV     a1, v4
        Return  "v1-v4"

        ENDIF

165 166 167 168 169 170 171 172 173 174 175 176
        IF SupportARMK

atomic_update_byte_smp ROUT
        MOV     a3, a1
01      LDREXB  a1, [a2]
        STREXB  a4, a3, [a2]
        TEQ     a4, #Strex_Failed
        BEQ     %B01 ; another exclusive access happened between LDREXB and STREXB
        Return  , LinkNotStacked

        ENDIF

Ben Avison's avatar
Ben Avison committed
177

178
        IF (SupportARMv6 :LAND: NoARMv6) :LOR: (SupportARMK :LAND: NoARMK)
Ben Avison's avatar
Ben Avison committed
179 180 181

        AREA    |Asm$$Data|, DATA

182
      [ SupportARMv6 :LAND: NoARMv6
Ben Avison's avatar
Ben Avison committed
183 184 185 186
update_fn
        DCD     0
process_fn
        DCD     0
187 188 189 190 191
      ]
      [ SupportARMK :LAND: NoARMK
update_byte_fn
        DCD     0
      ]
Ben Avison's avatar
Ben Avison committed
192 193 194 195 196

        ENDIF


        EXPORT  atomic_update
197
        EXPORT  atomic_update_byte
Ben Avison's avatar
Ben Avison committed
198 199 200 201
        EXPORT  atomic_process


        END