fix(arm64): store-exclusive operand order and large-frame parity
Assisted-by: GLM 5.3
This commit is contained in:
@@ -820,15 +820,28 @@ func TestArm64ExclOffsetErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64ExclNoOffset pins the plain (Rn) forms. gasm parses the store
|
||||
// with the status register first (ARM ARM order); go tool asm parses the
|
||||
// same text with the data register first, so the two spellings differ and
|
||||
// the store word below is gasm's own.
|
||||
// TestArm64ExclNoOffset pins the plain (Rn) forms, byte-for-byte against
|
||||
// go tool asm. The toolchain parses the FIRST register of a store as the
|
||||
// data register and the LAST as the status register (asm7.go case 59), and
|
||||
// the pair forms as (Rt1, Rt2) (case 58/59):
|
||||
//
|
||||
// STXR R3, (R1), R4 → c8047c23 (Rt=3, Rn=1, Rs=4)
|
||||
// STXP (R3, R4), (R1), R5 → c8251023 (Rt=3, Rt2=4, Rn=1, Rs=5)
|
||||
// LDXP (R1), (R3, R4) → c87f1023 (Rn=1, Rt=3, Rt2=4)
|
||||
func TestArm64ExclNoOffset(t *testing.T) {
|
||||
got := arm64Words(t, "\tLDXR (R1), R2\n\tSTXR R3, (R1), R4\n")
|
||||
got := arm64Words(t, "\tLDXR (R1), R2\n\tSTXR R3, (R1), R4\n"+
|
||||
"\tSTXP (R3, R4), (R1), R5\n\tSTXPW (R3, R4), (R1), R5\n"+
|
||||
"\tLDXP (R1), (R3, R4)\n\tLDXPW (R1), (R3, R4)\n"+
|
||||
"\tSTXR R3, (RSP), R4\n\tLDXR (RSP), R2\n")
|
||||
want := []uint32{
|
||||
0xc85f7c22, // LDXR X2, [X1]
|
||||
0xc8037c24, // STXR W3, X4, [X1] with Rs = R3, Rt = R4
|
||||
0xc8047c23, // STXR W3, [X1], W4 with Rt = R3, Rs = R4
|
||||
0xc8251023, // STXP (R3, R4), [X1], R5
|
||||
0x88251023, // STXPW (R3, R4), [X1], R5
|
||||
0xc87f1023, // LDXP [X1], (R3, R4)
|
||||
0x887f1023, // LDXPW [X1], (R3, R4)
|
||||
0xc8047fe3, // STXR R3, [SP], R4
|
||||
0xc85f7fe2, // LDXR [SP], R2
|
||||
0xd65f03c0, // RET
|
||||
}
|
||||
for i := range want {
|
||||
@@ -920,3 +933,58 @@ func TestArm64LargeFrameSpadj(t *testing.T) {
|
||||
t.Errorf("final RET word at byte 60 = %08x, want d65f03c0", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64SplitFrameSpadj pins the addcon2 band, where neither imm12 form
|
||||
// nor a single MOVZ carries the autosize and the toolchain splits the
|
||||
// prologue SUB into two imm12 instructions (asm7.go case 48) while the
|
||||
// non-leaf RET still materialises the value into REGTMP (obj7.go ARET,
|
||||
// issue 73259). $65664 rounds the autosize to 65680 = 144 + 16<<12:
|
||||
//
|
||||
// [SUB $144, RSP, R20][SUB $(16<<12), R20, R20][STP][MOVD R20, SP][SUB $8]
|
||||
// [CALL]
|
||||
// [LDP][MOVD $144, R27][MOVK $(1<<16), R27][ADD R27, RSP, RSP][RET]
|
||||
//
|
||||
// SP moves at the fourth word (byte 12) and returns to zero at the final
|
||||
// RET (byte 40); the words are go tool asm's own for the same source.
|
||||
func TestArm64SplitFrameSpadj(t *testing.T) {
|
||||
f, errs := parser.Parse("frame_arm64.s", "#include \"textflag.h\"\n\nTEXT ·framed(SB), NOSPLIT, $65664-0\n\tCALL ·other(SB)\n\tRET\n\nTEXT ·other(SB), NOSPLIT, $0\n\tRET\n")
|
||||
if len(errs) > 0 {
|
||||
t.Fatalf("parse: %v", errs)
|
||||
}
|
||||
img, err := AssembleFileARM64(f)
|
||||
if err != nil {
|
||||
t.Fatalf("AssembleFileARM64: %v", err)
|
||||
}
|
||||
fn := img.Funcs[0]
|
||||
wantSpadj := []SpadjStep{{PC: 12, Value: 65680}, {PC: 40, Value: 0}}
|
||||
if len(fn.Spadj) != len(wantSpadj) {
|
||||
t.Fatalf("spadj = %v, want %v", fn.Spadj, wantSpadj)
|
||||
}
|
||||
for i := range wantSpadj {
|
||||
if fn.Spadj[i] != wantSpadj[i] {
|
||||
t.Errorf("spadj[%d] = %v, want %v", i, fn.Spadj[i], wantSpadj[i])
|
||||
}
|
||||
}
|
||||
want := []uint32{
|
||||
0xd10243f4, // SUB $144, RSP, R20
|
||||
0xd1404294, // SUB $(16<<12), R20, R20
|
||||
0xa93ffa9d, // STP (R29, R30), -8(R20)
|
||||
0x9100029f, // MOVD R20, RSP
|
||||
0xd10023fd, // SUB $8, RSP, R29
|
||||
0x94000000, // CALL (relocation masked at link time)
|
||||
0xa97ffbfd, // LDP -8(RSP), (R29, R30)
|
||||
0xd280121b, // MOVD $144, R27
|
||||
0xf2a0003b, // MOVK $(1<<16), R27
|
||||
0x8b3b63ff, // ADD R27, RSP, RSP
|
||||
0xd65f03c0, // RET
|
||||
}
|
||||
words := leWords(img.Code[fn.Offset : fn.Offset+fn.Size])
|
||||
if len(words) != len(want) {
|
||||
t.Fatalf("framed = %d words, want %d", len(words), len(want))
|
||||
}
|
||||
for i, w := range want {
|
||||
if words[i] != w {
|
||||
t.Errorf("word %d = %08x, want %08x", i, words[i], w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user