Update contrib.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\common\arm\atomic_8_16_v6.h
15 // 8 and 16 bit atomic operations on V6 processors using LDREX/STREX and shifts
16 // Must use these user side so that it will work with data paging.
20 #include "atomic_ops.h"
22 #if defined(__CPU_ARM_HAS_LDREX_STREX_V6K) || !defined(__CPU_ARM_HAS_LDREX_STREX)
23 #error 8/16 bit atomic operations using LDREX/STREX
26 #ifdef __BARRIERS_NEEDED__
27 #error Barriers not supported on V6/V5, only V6K/V7
30 #if __DATA_SIZE__!=8 && __DATA_SIZE__!=16
31 #error Unsupported data size
34 #if defined(__OP_LOAD__)
35 #error Load operation not defined
37 #elif defined(__OP_STORE__)
38 #error Store operation not defined
40 #elif defined(__OP_RMW1__)
41 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rel,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*v*/)
48 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rlx,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*v*/)
55 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,ord,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*v*/)
62 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,acq,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*v*/)
66 asm("bic r12, r0, #3 ");
67 asm("and r3, r0, #3 ");
68 asm("stmfd sp!, {r4-r5} ");
69 asm("movs r4, r3, lsl #3 "); // r4 = bit offset of data in word
71 asm("eor r4, r4, #16 "); // r4 = right rotate to take hword of interest to top (0->16, 2->0)
73 #elif __DATA_SIZE__==8
74 asm("add r4, r4, #8 ");
75 asm("and r4, r4, #31 "); // right rotate to take byte of interest to top byte (0->8, 1->16, 2->24, 3->0)
76 asm("rsb r5, r4, #32 ");
77 asm("and r5, r5, #31 "); // right rotate to take top byte to byte of interest (0->8, 1->16, 2->24, 3->0)
79 #if defined(__OP_AND__)
81 asm("mvn r1, r1, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // v in upper bits of r1, 1's in lower bits
85 asm("mov r0, r0, ror r4 "); // rotate so desired data is at top
86 #if defined(__OP_SWP__)
87 asm("orr r2, r1, r0, lsl #%a0" : : "i" (__DATA_SIZE__));
88 asm("mov r2, r2, ror #%a0" : : "i" (__DATA_SIZE__));
89 #elif defined(__OP_ADD__)
90 asm("add r2, r0, r1, lsl #%a0" : : "i" (32-__DATA_SIZE__));
91 #elif defined(__OP_AND__)
92 asm("and r2, r0, r1 ");
93 #elif defined(__OP_IOR__)
94 asm("orr r2, r0, r1, lsl #%a0" : : "i" (32-__DATA_SIZE__));
95 #elif defined(__OP_XOR__)
96 asm("eor r2, r0, r1, lsl #%a0" : : "i" (32-__DATA_SIZE__));
98 asm("mov r2, r2, ror r5 "); // rotate back
102 asm("mov r0, r0, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // shift return value so data is at bottom
103 asm("ldmfd sp!, {r4-r5} ");
108 #elif defined(__OP_CAS__)
109 extern "C" EXPORT_C __NAKED__ TBool __fname__(__OPERATION__,rel,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ * /*q*/, __TYPE__ /*v*/)
112 // return value in R0
116 extern "C" EXPORT_C __NAKED__ TBool __fname__(__OPERATION__,rlx,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ * /*q*/, __TYPE__ /*v*/)
119 // return value in R0
123 extern "C" EXPORT_C __NAKED__ TBool __fname__(__OPERATION__,ord,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ * /*q*/, __TYPE__ /*v*/)
126 // return value in R0
130 extern "C" EXPORT_C __NAKED__ TBool __fname__(__OPERATION__,acq,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ * /*q*/, __TYPE__ /*v*/)
133 // return value in R0
134 asm("bic r12, r0, #3 ");
135 asm("and r3, r0, #3 ");
136 asm("stmfd sp!, {r4-r6} ");
137 asm("movs r4, r3, lsl #3 "); // r4 = bit offset of data in word
138 __LDR_INST__( ," r6, [r1] "); // r6 = expected value
139 #if __DATA_SIZE__==16
140 asm("mov r5, r4 "); // r5 = right rotate to take bottom hword to hword of interest (0->0, 2->16)
141 asm("eor r4, r4, #16 "); // r4 = right rotate to take hword of interest to top (0->16, 2->0)
142 #elif __DATA_SIZE__==8
143 asm("rsb r5, r4, #32 ");
144 asm("and r5, r5, #31 "); // right rotate to take bottom byte to byte of interest (0->0, 1->24, 2->16, 3->8)
145 asm("add r4, r4, #8 ");
146 asm("and r4, r4, #31 "); // right rotate to take byte of interest to top byte (0->8, 1->16, 2->24, 3->0)
150 asm("mov r0, r0, ror r4 "); // rotate so desired data is at top
151 asm("cmp r6, r0, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // check desired data against expected value *q
152 asm("bne 2f "); // if no match, give up
153 asm("orr r0, r2, r0, lsl #%a0" : : "i" (__DATA_SIZE__)); // substitute value v into bottom bits of r0, replacing original
154 asm("mov r0, r0, ror r5 "); // rotate back (bottom byte/hword goes to byte/hword of interest)
159 asm("movne r0, r0, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // shift return value so data is at bottom
160 __STR_INST__(ne, "r0, [r1] "); // update *q with observed value
161 asm("ldmfd sp!, {r4-r6} ");
162 asm("movne r0, #0 "); // if *a not updated return FALSE
163 asm("moveq r0, #1 "); // if *a updated return TRUE
168 #elif defined(__OP_AXO__)
169 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rel,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
172 // return value in R0
176 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rlx,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
179 // return value in R0
183 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,ord,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
186 // return value in R0
190 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,acq,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
193 // return value in R0
194 asm("and r3, r0, #3 ");
195 asm("bic r12, r0, #3 ");
196 asm("stmfd sp!, {r4-r5} ");
197 asm("mvn r1, r1, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // ~u in upper bits of r1, 1's in lower bits
198 asm("movs r4, r3, lsl #3 "); // r4 = bit offset of data in word
199 asm("mov r1, r1, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // ~u in lower bits of r1, zero extended
202 asm("bic r5, r0, r1, lsl r4 "); // r5 = r0 & u in relevant bit positions, other bit positions unchanged
203 asm("eor r5, r5, r2, lsl r4 ");
207 asm("mov r0, r0, lsr r4 "); // shift original value so byte/hword of interest is at the bottom
208 asm("ldmfd sp!, {r4-r5} ");
209 #if __DATA_SIZE__==16
210 asm("bic r0, r0, #0xff000000 "); // mask upper 16 bits
211 asm("bic r0, r0, #0x00ff0000 ");
212 #elif __DATA_SIZE__==8
213 asm("and r0, r0, #0xff "); // mask upper 24 bits
219 #elif defined(__OP_RMW3__)
220 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rel,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*t*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
222 // R0=a, R1=t, R2=u, R3=v
223 // return value in R0
227 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,rlx,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*t*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
229 // R0=a, R1=t, R2=u, R3=v
230 // return value in R0
234 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,ord,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*t*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
236 // R0=a, R1=t, R2=u, R3=v
237 // return value in R0
241 extern "C" EXPORT_C __NAKED__ __TYPE__ __fname__(__OPERATION__,acq,__DATA_SIZE__)(volatile TAny* /*a*/, __TYPE__ /*t*/, __TYPE__ /*u*/, __TYPE__ /*v*/)
243 // R0=a, R1=t, R2=u, R3=v
244 // return value in R0
245 asm("bic r12, r0, #3 ");
246 asm("stmfd sp!, {r4-r7} ");
247 asm("and r4, r0, #3 ");
248 asm("movs r4, r4, lsl #3 "); // r4 = bit offset of data in word
249 #if __DATA_SIZE__==16
250 asm("eor r4, r4, #16 "); // r4 = right rotate to take hword of interest to top (0->16, 2->0)
251 asm("mov r5, r4 "); // r5 = right rotate to undo r4
252 #elif __DATA_SIZE__==8
253 asm("add r4, r4, #8 ");
254 asm("and r4, r4, #31 "); // right rotate to take byte of interest to top byte (0->8, 1->16, 2->24, 3->0)
255 asm("rsb r5, r4, #32 ");
256 asm("and r5, r5, #31 "); // right rotate to take top byte to byte of interest (0->8, 1->16, 2->24, 3->0)
260 asm("mov r0, r0, ror r4 "); // rotate so desired data is at top
261 #if defined(__OP_TAU__)
262 asm("cmp r1, r0, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // t - byte/hword of interest
263 asm("addls r6, r0, r2, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // if t<=*a add u
264 asm("addhi r6, r0, r3, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // if t>*a add v
265 #elif defined(__OP_TAS__)
266 asm("cmp r1, r0, asr #%a0" : : "i" (32-__DATA_SIZE__)); // t - byte/hword of interest
267 asm("addle r6, r0, r2, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // if t<=*a add u
268 asm("addgt r6, r0, r3, lsl #%a0" : : "i" (32-__DATA_SIZE__)); // if t>*a add v
270 asm("mov r6, r6, ror r5 "); // rotate back
274 asm("ldmfd sp!, {r4-r7} ");
275 #if defined(__OP_TAU__)
276 asm("mov r0, r0, lsr #%a0" : : "i" (32-__DATA_SIZE__)); // shift return value so data is at bottom
277 #elif defined(__OP_TAS__)
278 asm("mov r0, r0, asr #%a0" : : "i" (32-__DATA_SIZE__)); // shift return value so data is at bottom
285 // Second inclusion undefines temporaries
286 #include "atomic_ops.h"