fix(asm): enforce the arm64 VLD/VST post-index contract
Assisted-by: GLM 5.3
This commit is contained in:
1 parent
7bc80ccb54
commit
2385bb7069
3 files changed
+83
-12
No files matched your search
@@ -2267,6 +2267,56 @@ func TestArm64NoopVsNop(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64VLDSTPostIndexContract pins the structure-load post-index rules
|
||||
// against `go tool asm` (Go 1.27, arm64): the implicit by-size increment of
|
||||
// an unspelled or zero offset (both load and replicate forms, the words
|
||||
// taken from the toolchain's own listing), the register post-index that
|
||||
// takes a bare register only, and the spelled immediate that must match the
|
||||
// transferred bytes.
|
||||
func TestArm64VLDSTPostIndexContract(t *testing.T) {
|
||||
got := arm64Words(t,
|
||||
"\tVLD1.P (R3), [V31.H8, V0.H8]\n"+ // implicit 2*16
|
||||
"\tVLD1R.P (R1), [V9.B8]\n"+ // implicit 1*1
|
||||
"\tVLD3R.P 6(R15), [V15.H4,V16.H4,V17.H4]\n"+ // 3*2 spelled
|
||||
"\tVLD1.P (R8)(R20), [V21.B16, V22.B16]\n") // register post-index
|
||||
want := []uint32{
|
||||
0x4cdfa47f, // VLD1.P (R3), [V31.H8, V0.H8]
|
||||
0x0ddfc029, // VLD1R.P (R1), [V9.B8]
|
||||
0x0ddfe5ef, // VLD3R.P 6(R15), [V15.H4,V16.H4,V17.H4]
|
||||
0x4cd4a115, // VLD1.P (R8)(R20), [V21.B16, V22.B16]
|
||||
0xd65f03c0, // RET
|
||||
}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("word count = %d, want %d (got %08x)", len(got), len(want), got)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Errorf("word %d = %08x, want %08x", i, got[i], want[i])
|
||||
}
|
||||
}
|
||||
reject := []string{
|
||||
"\tVLD1\t(R8)(R13), [V2.B16]\n", // register index without .P
|
||||
"\tVLD1\t8(R9), [V2.B16]\n", // offset without .P
|
||||
"\tVLD1.P\t8(R8)(R13), [V2.B16]\n", // offset beside the register index
|
||||
"\tVLD1.P\t(R8)(R9.UXTW), [V2.B16]\n", // extended post-index register
|
||||
"\tVLD1.P\t(R8)(R9<<2), [V2.B16]\n", // shifted post-index register
|
||||
"\tVST1.P\t[V1.B16], (R8)(R9.UXTW)\n", // extended, store side
|
||||
"\tVLD1.P\t17(R1), [V2.B16]\n", // 16 bytes transferred
|
||||
"\tVLD1.P\t-16(R1), [V2.B16]\n", // negative increment
|
||||
"\tVST1.P\t[V4.S4,V5.S4], 48(R1)\n", // 2*16, not 48
|
||||
"\tVLD3R.P\t24(R15), [V15.H4,V16.H4,V17.H4]\n", // 3*2, not 24
|
||||
}
|
||||
for _, src := range reject {
|
||||
f, errs := parser.Parse("test_arm64.s", "#include \"textflag.h\"\n\nTEXT ·f(SB), NOSPLIT, $0-0\n"+src+"\tRET\n")
|
||||
if len(errs) > 0 {
|
||||
continue // a parse rejection is a rejection
|
||||
}
|
||||
if _, err := AssembleFileARM64(f); err == nil {
|
||||
t.Errorf("expected rejection for %q, got nil", strings.TrimSpace(src))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestArm64FPImmediate pins the FP immediate moves against `go tool asm`
|
||||
// words: the FMOV (immediate) instruction for the 8-bit encodable values and
|
||||
// the FMOV-from-ZR move for zero, plus the rejections the toolchain raises
|
||||
|
||||
Reference in new issue
Block a user