[A64] Fix RESERVED_STORE LSE path leaving labels unbound

The LSE paths in RESERVED_STORE_I32/I64 returned early from Emit,
leaving forward-referenced no_reserve/done labels unbound. Xbyak
encodes these as offset-zero branches (branch-to-self), causing
infinite loops when the reservation check fails on LSE hardware.

Replace early return with branch-to-done inside an if/else so
labels are always bound regardless of the LSE path taken.

Adds tests for RESERVED_STORE I64 success path and I32/I64
no-reservation failure path with timeout-based hang detection.
This commit is contained in:
Herman S.
2026-03-29 17:39:29 +09:00
parent d3d0478403
commit 904c6c8b1c
2 changed files with 152 additions and 30 deletions

View File

@@ -1199,23 +1199,23 @@ struct RESERVED_STORE_I32
e.casal(e.w5, e.w6, ptr(e.x4));
e.cmp(e.w5, e.w0);
e.cset(i.dest, Xbyak_aarch64::EQ);
return;
e.b(done);
} else {
// LDXR/STXR loop.
auto& cas_loop = e.NewCachedLabel();
auto& cas_fail = e.NewCachedLabel();
e.L(cas_loop);
e.ldaxr(e.w7, ptr(e.x4));
e.cmp(e.w7, e.w5);
e.b(Xbyak_aarch64::NE, cas_fail);
e.stlxr(e.w7, e.w6, ptr(e.x4));
e.cbnz(e.w7, cas_loop);
// Success.
e.mov(i.dest, 1);
e.b(done);
e.L(cas_fail);
e.clrex(15);
}
// LDXR/STXR loop.
auto& cas_loop = e.NewCachedLabel();
auto& cas_fail = e.NewCachedLabel();
e.L(cas_loop);
e.ldaxr(e.w7, ptr(e.x4));
e.cmp(e.w7, e.w5);
e.b(Xbyak_aarch64::NE, cas_fail);
e.stlxr(e.w7, e.w6, ptr(e.x4));
e.cbnz(e.w7, cas_loop);
// Success.
e.mov(i.dest, 1);
e.b(done);
e.L(cas_fail);
e.clrex(15);
e.L(no_reserve);
e.mov(i.dest, 0);
e.L(done);
@@ -1256,21 +1256,21 @@ struct RESERVED_STORE_I64
e.casal(e.x5, e.x6, ptr(e.x4));
e.cmp(e.x5, e.x0);
e.cset(i.dest, Xbyak_aarch64::EQ);
return;
e.b(done);
} else {
auto& cas_loop = e.NewCachedLabel();
auto& cas_fail = e.NewCachedLabel();
e.L(cas_loop);
e.ldaxr(e.x7, ptr(e.x4));
e.cmp(e.x7, e.x5);
e.b(Xbyak_aarch64::NE, cas_fail);
e.stlxr(e.w7, e.x6, ptr(e.x4));
e.cbnz(e.w7, cas_loop);
e.mov(i.dest, 1);
e.b(done);
e.L(cas_fail);
e.clrex(15);
}
auto& cas_loop = e.NewCachedLabel();
auto& cas_fail = e.NewCachedLabel();
e.L(cas_loop);
e.ldaxr(e.x7, ptr(e.x4));
e.cmp(e.x7, e.x5);
e.b(Xbyak_aarch64::NE, cas_fail);
e.stlxr(e.w7, e.x6, ptr(e.x4));
e.cbnz(e.w7, cas_loop);
e.mov(i.dest, 1);
e.b(done);
e.L(cas_fail);
e.clrex(15);
e.L(no_reserve);
e.mov(i.dest, 0);
e.L(done);