66// - ARMv4 and ARMv5 Differences
77// https://developer.arm.com/documentation/ddi0406/cb/Appendixes/ARMv4-and-ARMv5-Differences?lang=en
88//
9- // Generated asm:
9+ // Generated asm: TODO: update
1010// - armv5te https://godbolt.org/z/r61s7cnG8
1111// - armv4t https://godbolt.org/z/xrxfKx1rc
1212
@@ -19,7 +19,10 @@ use core::{
1919 sync:: atomic:: Ordering ,
2020} ;
2121
22- use crate :: raw:: { AtomicCompareExchange , AtomicLoad , AtomicStore , AtomicSwap } ;
22+ use crate :: {
23+ raw:: { AtomicCompareExchange , AtomicLoad , AtomicStore , AtomicSwap } ,
24+ utils:: MaybeUninit64 ,
25+ } ;
2326
2427type XSize = usize ;
2528
@@ -61,36 +64,29 @@ macro_rules! atomic_load_store {
6164 order: Ordering ,
6265 ) -> MaybeUninit <Self > {
6366 debug_assert!( src as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
64- let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
65- let out_ptr = out. as_mut_ptr( ) ;
67+ let mut out: MaybeUninit <Self >;
6668
6769 // SAFETY: the caller must uphold the safety contract.
6870 unsafe {
6971 match order {
7072 Ordering :: Relaxed => {
7173 asm!(
72- // (atomic) load from src to tmp
73- concat!( "ldr" , $asm_suffix, " {tmp}, [{src}]" ) ,
74- // store tmp to out
75- concat!( "str" , $asm_suffix, " {tmp}, [{out}]" ) ,
74+ // (atomic) load from src to out
75+ concat!( "ldr" , $asm_suffix, " {out}, [{src}]" ) ,
7676 src = in( reg) src,
77- out = inout( reg) out_ptr => _,
78- tmp = lateout( reg) _,
77+ out = lateout( reg) out,
7978 options( nostack, preserves_flags) ,
8079 ) ;
8180 }
8281 // Acquire and SeqCst loads are equivalent.
8382 Ordering :: Acquire | Ordering :: SeqCst => {
8483 debug_assert!( kuser_helper_version( ) >= 3 ) ;
8584 asm!(
86- // (atomic) load from src to tmp
87- concat!( "ldr" , $asm_suffix, " {tmp }, [{src}]" ) ,
85+ // (atomic) load from src to out
86+ concat!( "ldr" , $asm_suffix, " {out }, [{src}]" ) ,
8887 blx!( "{kuser_memory_barrier}" ) , // acquire fence
89- // store tmp to out
90- concat!( "str" , $asm_suffix, " {tmp}, [{out}]" ) ,
9188 src = in( reg) src,
92- out = inout( reg) out_ptr => _,
93- tmp = lateout( reg) _,
89+ out = lateout( reg) out,
9490 kuser_memory_barrier = inout( reg) KUSER_MEMORY_BARRIER => _,
9591 out( "lr" ) _,
9692 options( nostack, preserves_flags) ,
@@ -110,24 +106,20 @@ macro_rules! atomic_load_store {
110106 order: Ordering ,
111107 ) {
112108 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
113- let val = val. as_ptr( ) ;
114109
115110 // SAFETY: the caller must uphold the safety contract.
116111 unsafe {
117112 macro_rules! atomic_store_release {
118113 ( $acquire: expr) => { {
119114 debug_assert!( kuser_helper_version( ) >= 3 ) ;
120115 asm!(
121- // load from val to tmp
122- concat!( "ldr" , $asm_suffix, " {tmp}, [{val}]" ) ,
123- // (atomic) store tmp to dst
116+ // (atomic) store val to dst
124117 blx!( "{kuser_memory_barrier}" ) , // release fence
125- concat!( "str" , $asm_suffix, " {tmp }, [{dst}]" ) ,
118+ concat!( "str" , $asm_suffix, " {val }, [{dst}]" ) ,
126119 $acquire, // acquire fence
127- dst = inout ( reg) dst => _ ,
120+ dst = in ( reg) dst,
128121 val = in( reg) val,
129- tmp = lateout( reg) _,
130- kuser_memory_barrier = inout( reg) KUSER_MEMORY_BARRIER => _,
122+ kuser_memory_barrier = in( reg) KUSER_MEMORY_BARRIER ,
131123 out( "lr" ) _,
132124 options( nostack, preserves_flags) ,
133125 )
@@ -136,13 +128,10 @@ macro_rules! atomic_load_store {
136128 match order {
137129 Ordering :: Relaxed => {
138130 asm!(
139- // load from val to tmp
140- concat!( "ldr" , $asm_suffix, " {tmp}, [{val}]" ) ,
141- // (atomic) store tmp to dst
142- concat!( "str" , $asm_suffix, " {tmp}, [{dst}]" ) ,
143- dst = inout( reg) dst => _,
131+ // (atomic) store val to dst
132+ concat!( "str" , $asm_suffix, " {val}, [{dst}]" ) ,
133+ dst = in( reg) dst,
144134 val = in( reg) val,
145- tmp = lateout( reg) _,
146135 options( nostack, preserves_flags) ,
147136 ) ;
148137 }
@@ -168,26 +157,21 @@ macro_rules! atomic {
168157 ) -> MaybeUninit <Self > {
169158 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
170159 debug_assert!( kuser_helper_version( ) >= 2 ) ;
171- let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
172- let out_ptr = out. as_mut_ptr( ) ;
173- let val = val. as_ptr( ) ;
160+ let mut out: MaybeUninit <Self >;
174161
175162 // SAFETY: the caller must uphold the safety contract.
176163 unsafe {
177164 asm!(
178- "ldr r1, [r1]" , // new_val
179165 "2:" ,
180166 "ldr r0, [r2]" , // old_val
181- "mov {out_tmp }, r0" ,
167+ "mov {out }, r0" ,
182168 blx!( "{kuser_cmpxchg}" ) ,
183169 "cmp r0, #0" ,
184170 "bne 2b" ,
185- "str {out_tmp}, [{out}]" ,
186- out = in( reg) out_ptr,
187- out_tmp = out( reg) _,
171+ out = out( reg) out,
188172 kuser_cmpxchg = in( reg) KUSER_CMPXCHG ,
189173 out( "r0" ) _,
190- inout ( "r1" ) val => _ ,
174+ in ( "r1" ) val, // new_val
191175 in( "r2" ) dst, // ptr
192176 out( "r3" ) _,
193177 out( "ip" ) _,
@@ -210,20 +194,15 @@ macro_rules! atomic {
210194 ) -> ( MaybeUninit <Self >, bool ) {
211195 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
212196 debug_assert!( kuser_helper_version( ) >= 2 ) ;
213- let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
214- let out_ptr = out. as_mut_ptr( ) ;
215- let old = old. as_ptr( ) ;
216- let new = new. as_ptr( ) ;
197+ let mut out: MaybeUninit <Self >;
217198
218199 // SAFETY: the caller must uphold the safety contract.
219200 unsafe {
220201 let mut r: i32 ;
221202 asm!(
222- "ldr {old}, [{old}]" ,
223- "ldr {new}, [{new}]" ,
224203 "2:" ,
225204 "ldr r0, [r2]" , // old_val
226- "mov {out_tmp }, r0" ,
205+ "mov {out }, r0" ,
227206 "cmp r0, {old}" ,
228207 "bne 3f" ,
229208 "mov r1, {new}" , // new_val
@@ -239,11 +218,9 @@ macro_rules! atomic {
239218 "bne 2b" ,
240219 "mov r0, #1" ,
241220 "4:" ,
242- "str {out_tmp}, [{out}]" ,
243- old = inout( reg) old => _,
244- new = inout( reg) new => _,
245- out = in( reg) out_ptr,
246- out_tmp = out( reg) _,
221+ old = in( reg) old,
222+ new = in( reg) new,
223+ out = out( reg) out,
247224 kuser_cmpxchg = in( reg) KUSER_CMPXCHG ,
248225 out( "r0" ) r,
249226 out( "r1" ) _,
@@ -276,34 +253,29 @@ macro_rules! atomic_sub_word {
276253 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
277254 debug_assert!( kuser_helper_version( ) >= 2 ) ;
278255 let ( aligned_ptr, shift, mask) = partword:: create_mask_values( dst) ;
279- let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
280- let out_ptr = out. as_mut_ptr( ) ;
281- let val = val. as_ptr( ) ;
256+ let mut out: MaybeUninit <Self >;
282257
283258 // SAFETY: the caller must uphold the safety contract.
284259 unsafe {
285260 asm!(
286- concat!( "ldr" , $asm_suffix, " {val}, [{val}]" ) ,
287261 "lsl {mask}, {mask}, {shift}" ,
288262 "lsl {val}, {val}, {shift}" ,
289263 "and {val}, {val}, {mask}" ,
290264 "mvn {inv_mask}, {mask}" ,
291265 "2:" ,
292266 "ldr r0, [r2]" , // old_val
293- "mov {out_tmp }, r0" ,
267+ "mov {out }, r0" ,
294268 "and r1, r0, {inv_mask}" ,
295269 "orr r1, r1, {val}" , // new_val
296270 blx!( "{kuser_cmpxchg}" ) ,
297271 "cmp r0, #0" ,
298272 "bne 2b" ,
299- "lsr {out_tmp}, {out_tmp}, {shift}" ,
300- concat!( "str" , $asm_suffix, " {out_tmp}, [{out}]" ) ,
301- val = inout( reg) val => _,
302- out = in( reg) out_ptr,
273+ "lsr {out}, {out}, {shift}" ,
274+ val = inout( reg) crate :: utils:: zero_extend( val) => _,
275+ out = out( reg) out,
303276 shift = in( reg) shift,
304277 mask = inout( reg) mask => _,
305278 inv_mask = out( reg) _,
306- out_tmp = out( reg) _,
307279 kuser_cmpxchg = in( reg) KUSER_CMPXCHG ,
308280 out( "r0" ) _,
309281 out( "r1" ) _,
@@ -330,17 +302,12 @@ macro_rules! atomic_sub_word {
330302 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
331303 debug_assert!( kuser_helper_version( ) >= 2 ) ;
332304 let ( aligned_ptr, shift, mask) = partword:: create_mask_values( dst) ;
333- let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
334- let out_ptr = out. as_mut_ptr( ) ;
335- let old = old. as_ptr( ) ;
336- let new = new. as_ptr( ) ;
305+ let mut out: MaybeUninit <Self >;
337306
338307 // SAFETY: the caller must uphold the safety contract.
339308 unsafe {
340309 let mut r: i32 ;
341310 asm!(
342- concat!( "ldr" , $asm_suffix, " {old}, [{old}]" ) ,
343- concat!( "ldr" , $asm_suffix, " {new}, [{new}]" ) ,
344311 "lsl {mask}, {mask}, {shift}" ,
345312 "lsl {old}, {old}, {shift}" ,
346313 "lsl {new}, {new}, {shift}" ,
@@ -350,8 +317,8 @@ macro_rules! atomic_sub_word {
350317 // "mvn {inv_mask}, {mask}",
351318 "2:" ,
352319 "ldr r0, [r2]" , // old_val
353- "and {out_tmp }, r0, {mask}" ,
354- "cmp {out_tmp }, {old}" ,
320+ "and {out }, r0, {mask}" ,
321+ "cmp {out }, {old}" ,
355322 "bne 3f" ,
356323 "mvn r1, {mask}" ,
357324 "and r1, r0, r1" ,
@@ -368,14 +335,12 @@ macro_rules! atomic_sub_word {
368335 "bne 2b" ,
369336 "mov r0, #1" ,
370337 "4:" ,
371- "lsr {out_tmp}, {out_tmp}, {shift}" ,
372- concat!( "str" , $asm_suffix, " {out_tmp}, [{out}]" ) ,
373- old = inout( reg) old => _,
374- new = inout( reg) new => _,
375- out = in( reg) out_ptr,
338+ "lsr {out}, {out}, {shift}" ,
339+ old = inout( reg) crate :: utils:: zero_extend( old) => _,
340+ new = inout( reg) crate :: utils:: zero_extend( new) => _,
341+ out = out( reg) out,
376342 shift = in( reg) shift,
377343 mask = inout( reg) mask => _,
378- out_tmp = out( reg) _,
379344 kuser_cmpxchg = in( reg) KUSER_CMPXCHG ,
380345 out( "r0" ) r,
381346 out( "r1" ) _,
@@ -529,17 +494,15 @@ macro_rules! atomic64 {
529494 ) -> ( MaybeUninit <Self >, bool ) {
530495 debug_assert!( dst as usize % mem:: size_of:: <$int_type>( ) == 0 ) ;
531496 assert_has_kuser_cmpxchg64( ) ;
497+ let old = MaybeUninit64 { $int_type: old } ;
532498 let mut out: MaybeUninit <Self > = MaybeUninit :: uninit( ) ;
533499 let out_ptr = out. as_mut_ptr( ) ;
534- let old = old. as_ptr( ) ;
535500 let new = new. as_ptr( ) ;
536501
537502 // SAFETY: the caller must uphold the safety contract.
538503 unsafe {
539504 let mut r: i32 ;
540505 asm!(
541- "ldr {old_lo}, [{old_hi}]" ,
542- "ldr {old_hi}, [{old_hi}, #4]" ,
543506 "2:" ,
544507 "ldr r0, [r2]" ,
545508 "ldr r3, [r2, #4]" ,
@@ -566,8 +529,8 @@ macro_rules! atomic64 {
566529 "4:" ,
567530 new = in( reg) new,
568531 out_tmp = in( reg) out_ptr,
569- old_lo = out ( reg) _ ,
570- old_hi = inout ( reg) old => _ ,
532+ old_lo = in ( reg) old . pair . lo ,
533+ old_hi = in ( reg) old. pair . hi ,
571534 kuser_cmpxchg64 = in( reg) KUSER_CMPXCHG64 ,
572535 out( "r0" ) r,
573536 out( "r1" ) _,
0 commit comments