OpenBSD/sgi on octane2 - __cpu_simple_lock_tryのバグ

__cpu_simple_lock_try()でoldとnewが両方ともv0にコンパイルされちまってるよ、"=r"を"=&r"に書き換えると直るよ、とエラい人に教えてもらった。

まじかよ。

って事で早速ダンプを取ってみた。

__cpu_simple_lock_try()はinline関数だから、展開先を作ってあげると読みやすい。なので

#include <machine/lock.h>
__cpu_simple_lock_t lock;
static void locktest(void)
{
	__cpu_simple_lock_try(&lock);
}

という関数を定義して、これをobjdumpで覗いてみる。

a80000002013dbc0 <locktest>:
a80000002013dbc0:       67bdfff0        daddiu  sp,sp,-16
a80000002013dbc4:       24020001        li      v0,1
a80000002013dbc8:       afa20004        sw      v0,4(sp)
a80000002013dbcc:       3c03a800        lui     v1,0xa800
a80000002013dbd0:       3c01205c        lui     at,0x205c
a80000002013dbd4:       64630000        daddiu  v1,v1,0
a80000002013dbd8:       6421e5d0        daddiu  at,at,-6704
a80000002013dbdc:       0003183c        dsll32  v1,v1,0x0
a80000002013dbe0:       0061182d        daddu   v1,v1,at
a80000002013dbe4:       8fa20004        lw      v0,4(sp)
a80000002013dbe8:       c0620000        ll      v0,0(v1)
a80000002013dbec:       e0620000        sc      v0,0(v1)
a80000002013dbf0:       1040fffd        beqz    v0,a80000002013dbe8 <locktest+0x28>
a80000002013dbf4:       00000000        nop
a80000002013dbf8:       00000000        nop
a80000002013dbfc:       afa20000        sw      v0,0(sp)
a80000002013dc00:       8fa30000        lw      v1,0(sp)
a80000002013dc04:       8fa20000        lw      v0,0(sp)
a80000002013dc08:       03e00008        jr      ra
a80000002013dc0c:       67bd0010        daddiu  sp,sp,16

llとscに注目。
インラインアセンブリでは

	__asm__ __volatile__
	   ("1:\tll\t%0, %1\n" 
	    "\tsc\t%2, %1\n"
	    "\tbeqz\t%2, 1b\n"
	    "\t nop" : "=r" (old) : "m" (*l), "r" (new));

と定義されているので、llの一個目のオペランドとscの一個目のオペランドは異ならなければならない。
が、両方ともv0。
何のマジック?これ( Д ) ゚ ゚

で、"=r"を=&r"と書き換えると、きちんと別々のレジスタを使うようになる。

a80000002013dbc0 <locktest>:
a80000002013dbc0:       67bdfff0        daddiu  sp,sp,-16
a80000002013dbc4:       24020001        li      v0,1
a80000002013dbc8:       afa20004        sw      v0,4(sp)
a80000002013dbcc:       3c04a800        lui     a0,0xa800
a80000002013dbd0:       3c01205c        lui     at,0x205c
a80000002013dbd4:       64840000        daddiu  a0,a0,0
a80000002013dbd8:       6421e5d0        daddiu  at,at,-6704
a80000002013dbdc:       0004203c        dsll32  a0,a0,0x0
a80000002013dbe0:       0081202d        daddu   a0,a0,at
a80000002013dbe4:       8fa20004        lw      v0,4(sp)
a80000002013dbe8:       c0830000        ll      v1,0(a0)
a80000002013dbec:       e0820000        sc      v0,0(a0)
a80000002013dbf0:       1040fffd        beqz    v0,a80000002013dbe8 <locktest+0x28>
a80000002013dbf4:       00000000        nop
a80000002013dbf8:       00000000        nop
a80000002013dbfc:       afa30000        sw      v1,0(sp)
a80000002013dc00:       8fa20000        lw      v0,0(sp)
a80000002013dc04:       8fa30000        lw      v1,0(sp)
a80000002013dc08:       03e00008        jr      ra
a80000002013dc0c:       67bd0010        daddiu  sp,sp,16

うまくいっているようだが、なんだこれ。