feat(asm): encode the arm64 register-offset addressing forms

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 02:36:24 +02:00
1 parent a344399b81
commit 458cdd2066
4 files changed
+221 -1

No files matched your search

+69
View File
@@ -1825,3 +1825,72 @@ func TestArm64SplitFrameSpadj(t *testing.T) {
}
}
}
// TestArm64RegOffsetEncodings pins the register-offset addressing forms of
// the MOV family against `go tool asm` words (Go 1.27, arm64): the LSL,
// UXTW, SXTW and SXTX options, the shift amount equal to the access size's
// log2, and the rejections the toolchain raises for the other spellings.
func TestArm64RegOffsetEncodings(t *testing.T) {
got := arm64Words(t,
"\tMOVD (R2)(R6.SXTW), R4\n"+
"\tMOVD (R3)(R6), R5\n"+
"\tMOVD (R2)(R6<<3), R4\n"+
"\tMOVWU (R5)(R4.UXTW), R10\n"+
"\tMOVW (R9)(R8.SXTW<<2), R19\n"+
"\tMOVD (R3)(R7.SXTX<<3), R8\n"+
"\tMOVBU (R10)(R6), R15\n"+
"\tFMOVS (R2)(R6<<2), F4\n"+
"\tFMOVD (R2)(R6), F4\n"+
"\tMOVD R5, (R2)(R6<<3)\n"+
"\tMOVW R7, (R3)(R4.SXTW)\n"+
"\tMOVD ZR, (R6)(R7.SXTX<<3)\n")
want := []uint32{
0xf866c844, // MOVD (R2)(R6.SXTW), R4
0xf8666865, // MOVD (R3)(R6), R5
0xf8667844, // MOVD (R2)(R6<<3), R4
0xb86448aa, // MOVWU (R5)(R4.UXTW), R10
0xb8a8d933, // MOVW (R9)(R8.SXTW<<2), R19
0xf867f868, // MOVD (R3)(R7.SXTX<<3), R8
0x3866694f, // MOVBU (R10)(R6), R15
0xbc667844, // FMOVS (R2)(R6<<2), F4
0xfc666844, // FMOVD (R2)(R6), F4
0xf8267845, // MOVD R5, (R2)(R6<<3)
0xb824c867, // MOVW R7, (R3)(R4.SXTW)
0xf827f8df, // MOVD ZR, (R6)(R7.SXTX<<3)
0xd65f03c0, // RET
}
if len(got) != len(want) {
t.Fatalf("word count = %d, want %d", len(got), len(want))
}
for i := range want {
if got[i] != want[i] {
t.Errorf("word %d = %08x, want %08x", i, got[i], want[i])
}
}
}
// TestArm64RegOffsetRejections pins the spellings the toolchain refuses for
// the register-offset addressing: the UXTX/UXTB/SXTH extend names, a shift
// amount outside {0, log2(access)}, the scaled *k index, writeback with an
// index, and the FMOVQ form the toolchain rejects outright.
func TestArm64RegOffsetRejections(t *testing.T) {
for _, src := range []string{
"\tMOVD\t(R2)(R3.UXTX), R1\n",
"\tMOVD\t(R2)(R3.UXTB), R1\n",
"\tMOVD\t(R2)(R3.SXTH), R1\n",
"\tMOVD\t(R2)(R3<<1), R1\n",
"\tMOVD\t(R2)(R3<<2), R1\n",
"\tMOVBU\t(R1)(R2<<1), R3\n",
"\tMOVD\t(R2)(R3*8), R1\n",
"\tMOVD.P\tR5, (R2)(R3)\n",
"\tFMOVQ\t(R2)(R6), F4\n",
} {
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))
}
}
}