NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: port-sh3/60773: sh3 __sync_val_compare_and_swap_1 test failures



The following reply was made to PR toolchain/60773; it has been noted by GNATS.

From: Valery Ushakov <uwe%stderr.spb.ru@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: Taylor R Campbell <riastradh%NetBSD.org@localhost>,
	Nick Hudson <skrll%NetBSD.org@localhost>
Subject: Re: port-sh3/60773: sh3 __sync_val_compare_and_swap_1 test failures
Date: Fri, 25 Sep 2026 19:32:04 +0300

 On Fri, Sep 25, 2026 at 14:41:44 +0000, Taylor R Campbell wrote:
 
 > 00000078 <main_s8>:
 > ...
 >   82:	d0 08       	mov.l	a4 <main_s8+0x2c>,r0	! 0 <main__>
 >   84:	e6 f0       	mov	#-16,r6
 >   86:	e5 88       	mov	#-120,r5
 >   88:	40 0b       	jsr	@r0
 >   8a:	74 03       	add	#3,r4
 >   8c:	66 0c       	extu.b	r0,r6
 [...]
 >
 > Note that main_s8 has an additional extu.b instruction in it!  I'm
 > guessing this means `extend unsigned byte', i.e., zero-extend result
 > in r0 to printf argument in r6.  So it looks like gcc treats
 > __sync_val_compare_and_swap_1 as if it has the signed prototype:
 > main__ matches main_u8, not main_s8.
 
 You are right.  sh3 psABI specifies that unsigned char is returned in
 the LSB of r0 and is zero-extended, while signed char is returned
 sign-extended.  So that extu.b does the coercion of res to its
 declared uint8_t type and it can be elided for main_u8, b/c ABI
 already requires r0 to be zero-extended.
 
 
 
 > If I disassemble t___sync_compare_and_swap.o, I see there's also an
 > extu.b instruction:
 > 
 > 000009b8 <atfu___sync_val_compare_and_swap_1_body>:
 > ...
 > 
 > 	// Load expval 0xf0 into r11, which is callee-saves so
 > 	// __sync_val_compare_and_swap_1 should preserve it:
 >      9d0:       9b 52           mov.w   a78 <atfu___sync_val_compare_and_swap_1_body+0xc0>,r11  ! f0
 > ...
 > 	// Load expres 0x88 into r10, which is also callee-saves so
 > 	// __sync_val_compare_and_swap_1 should preserve it:
 >      9d4:       9a 51           mov.w   a7a <atfu___sync_val_compare_and_swap_1_body+0xc2>,r10  ! 88
 > ...
 
 Side note, there's no mov.b variant for pc-relative load.  mov.w
 sign-extends, but 0x0088 is positive, so we get the the right uint8_t
 value in r10.
 
 
 > 	// Load __sync_val_compare_and_swap_1 function into r1 to
 > 	// call:
 >      9d8:       d1 2a           mov.l   a84 <atfu___sync_val_compare_and_swap_1_body+0xcc>,r1   ! 98
 > ...
 >      9e8:       01 03           bsrf    r1
 >      9ea:       64 d3           mov     r13,r4
 > 	// res in r0.  Move res to r9, reuse r0 for the stored val,
 > 	// move stored val to r6, and check whether the stored val is
 > 	// what we expect:
 >      9ec:       69 03           mov     r0,r9
 >      9ee:       84 8f           mov.b   @(15,r8),r0
 >      9f0:       66 0c           extu.b  r0,r6
 
 Side note - on sh3 mov.b from memory (and mov.w) can only load to R0,
 hence the extra song and dance.  Both implicitly sign-extend R0.
 
 > 	// val == expval?
 >      9f2:       36 b0           cmp/eq  r11,r6
 >      9f4:       8d 0b           bt.s    a0e <atfu___sync_val_compare_and_swap_1_body+0x56>
 > 	// res == expres?
 >      9f6:       39 a0           cmp/eq  r10,r9
 > ...
 
 Right, and r10 is (uint8_t)0x88, and r9 (returned as uint8_t) is
 expected to be zero-extended b/c the ABI.
 
 As we know from the observation - it's not, b/c the actual function
 was defined as returning int8_t and hence it retutned sign-extended
 value, but the caller expects otherwise.
 
 
 > Now I'm a little lost with the sh3 branch delay slot shenanigans (is
 > that two comparisons fed into a single conditional branch with a
 > delay slot??),
 
 We do the first comparison and branch on its result.  We do the second
 comarison in the delay slot of that branch to not waste a perfectly
 good clock cycle, the value of that comparison will be used later.
 
 
 > but what I see here is that the _stored_ val is zero-extended
 > with extu.b, but the _returned_ res is not!  That's in stark contrast
 > to the attached program I examined, where the returned result _is_
 > zero-extended with extu.b.
 
 As I mentioned above, the loaded value must be zero-extended b/c the
 instruction sign-extends it on load.
 
 
 
 -uwe
 



Home | Main Index | Thread Index | Old Index