]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/apr/atomic/unix/ppc.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / apr / atomic / unix / ppc.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  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 "apr_arch_atomic.h"
18
19 #ifdef USE_ATOMICS_PPC
20
21 #ifdef PPC405_ERRATA
22 #   define PPC405_ERR77_SYNC   "    sync\n"
23 #else
24 #   define PPC405_ERR77_SYNC
25 #endif
26
27 APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p)
28 {
29     return APR_SUCCESS;
30 }
31
32 APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem)
33 {
34     return *mem;
35 }
36
37 APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val)
38 {
39     *mem = val;
40 }
41
42 APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
43 {
44     apr_uint32_t prev, temp;
45
46     asm volatile ("1:\n"                       /* lost reservation     */
47                   "    lwarx   %0,0,%3\n"      /* load and reserve     */
48                   "    add     %1,%0,%4\n"     /* add val and prev     */
49                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
50                   "    stwcx.  %1,0,%3\n"      /* store new value      */
51                   "    bne-    1b\n"           /* loop if lost         */
52                   : "=&r" (prev), "=&r" (temp), "=m" (*mem)
53                   : "b" (mem), "r" (val)
54                   : "cc", "memory");
55
56     return prev;
57 }
58
59 APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val)
60 {
61     apr_uint32_t temp;
62
63     asm volatile ("1:\n"                       /* lost reservation     */
64                   "    lwarx   %0,0,%2\n"      /* load and reserve     */
65                   "    subf    %0,%3,%0\n"     /* subtract val         */
66                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
67                   "    stwcx.  %0,0,%2\n"      /* store new value      */
68                   "    bne-    1b\n"           /* loop if lost         */
69                   : "=&r" (temp), "=m" (*mem)
70                   : "b" (mem), "r" (val)
71                   : "cc", "memory");
72 }
73
74 APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem)
75 {
76     apr_uint32_t prev;
77
78     asm volatile ("1:\n"                       /* lost reservation     */
79                   "    lwarx   %0,0,%2\n"      /* load and reserve     */
80                   "    addi    %0,%0,1\n"      /* add immediate        */
81                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
82                   "    stwcx.  %0,0,%2\n"      /* store new value      */
83                   "    bne-    1b\n"           /* loop if lost         */
84                   "    subi    %0,%0,1\n"      /* return old value     */
85                   : "=&b" (prev), "=m" (*mem)
86                   : "b" (mem), "m" (*mem)
87                   : "cc", "memory");
88
89     return prev;
90 }
91
92 APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem)
93 {
94     apr_uint32_t prev;
95
96     asm volatile ("1:\n"                       /* lost reservation     */
97                   "    lwarx   %0,0,%2\n"      /* load and reserve     */
98                   "    subi    %0,%0,1\n"      /* subtract immediate   */
99                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
100                   "    stwcx.  %0,0,%2\n"      /* store new value      */
101                   "    bne-    1b\n"           /* loop if lost         */
102                   : "=&b" (prev), "=m" (*mem)
103                   : "b" (mem), "m" (*mem)
104                   : "cc", "memory");
105
106     return prev;
107 }
108
109 APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,
110                                            apr_uint32_t cmp)
111 {
112     apr_uint32_t prev;
113
114     asm volatile ("1:\n"                       /* lost reservation     */
115                   "    lwarx   %0,0,%1\n"      /* load and reserve     */
116                   "    cmpw    %0,%3\n"        /* compare operands     */
117                   "    bne-    exit_%=\n"      /* skip if not equal    */
118                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
119                   "    stwcx.  %2,0,%1\n"      /* store new value      */
120                   "    bne-    1b\n"           /* loop if lost         */
121                   "exit_%=:\n"                 /* not equal            */
122                   : "=&r" (prev)
123                   : "b" (mem), "r" (with), "r" (cmp)
124                   : "cc", "memory");
125
126     return prev;
127 }
128
129 APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val)
130 {
131     apr_uint32_t prev;
132
133     asm volatile ("1:\n"                       /* lost reservation     */
134                   "    lwarx   %0,0,%1\n"      /* load and reserve     */
135                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
136                   "    stwcx.  %2,0,%1\n"      /* store new value      */
137                   "    bne-    1b"             /* loop if lost         */
138                   : "=&r" (prev)
139                   : "b" (mem), "r" (val)
140                   : "cc", "memory");
141
142     return prev;
143 }
144
145 APR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp)
146 {
147     void *prev;
148 #if APR_SIZEOF_VOIDP == 4
149     asm volatile ("1:\n"                       /* lost reservation     */
150                   "    lwarx   %0,0,%1\n"      /* load and reserve     */
151                   "    cmpw    %0,%3\n"        /* compare operands     */
152                   "    bne-    2f\n"           /* skip if not equal    */
153                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
154                   "    stwcx.  %2,0,%1\n"      /* store new value      */
155                   "    bne-    1b\n"           /* loop if lost         */
156                   "2:\n"                       /* not equal            */
157                   : "=&r" (prev)
158                   : "b" (mem), "r" (with), "r" (cmp)
159                   : "cc", "memory");
160 #elif APR_SIZEOF_VOIDP == 8
161     asm volatile ("1:\n"                       /* lost reservation     */
162                   "    ldarx   %0,0,%1\n"      /* load and reserve     */
163                   "    cmpd    %0,%3\n"        /* compare operands     */
164                   "    bne-    2f\n"           /* skip if not equal    */
165                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
166                   "    stdcx.  %2,0,%1\n"      /* store new value      */
167                   "    bne-    1b\n"           /* loop if lost         */
168                   "2:\n"                       /* not equal            */
169                   : "=&r" (prev)
170                   : "b" (mem), "r" (with), "r" (cmp)
171                   : "cc", "memory");
172 #else
173 #error APR_SIZEOF_VOIDP value not supported
174 #endif
175     return prev;
176 }
177
178 APR_DECLARE(void*) apr_atomic_xchgptr(volatile void **mem, void *with)
179 {
180     void *prev;
181 #if APR_SIZEOF_VOIDP == 4
182     asm volatile ("1:\n"                       /* lost reservation     */
183                   "    lwarx   %0,0,%1\n"      /* load and reserve     */
184                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
185                   "    stwcx.  %2,0,%1\n"      /* store new value      */
186                   "    bne-    1b\n"           /* loop if lost         */
187                   "    isync\n"                /* memory barrier       */
188                   : "=&r" (prev)
189                   : "b" (mem), "r" (with)
190                   : "cc", "memory");
191 #elif APR_SIZEOF_VOIDP == 8
192     asm volatile ("1:\n"                       /* lost reservation     */
193                   "    ldarx   %0,0,%1\n"      /* load and reserve     */
194                   PPC405_ERR77_SYNC            /* ppc405 Erratum 77    */
195                   "    stdcx.  %2,0,%1\n"      /* store new value      */
196                   "    bne-    1b\n"           /* loop if lost         */
197                   "    isync\n"                /* memory barrier       */
198                   : "=&r" (prev)
199                   : "b" (mem), "r" (with)
200                   : "cc", "memory");
201 #else
202 #error APR_SIZEOF_VOIDP value not supported
203 #endif
204     return prev;
205 }
206
207 #endif /* USE_ATOMICS_PPC */