fix(asm): scale the FLDPQ and FSTPQ pair offsets by sixteen
The pair encoder derived the imm7 divisor from the width suffix alone, so the 128-bit FP pairs divided their offsets by eight and encoded twice the distance. The Q spellings scale by sixteen like every other 128-bit access; the differential kernel carries them now. Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
daf7fad5b9
commit
2bd52eb7ad
5 files changed
+14
-5
No files matched your search
@@ -3147,8 +3147,11 @@ func encodeARM64Pair(mnem string, baseOp uint32, ops []*ast.Operand, fi arm64Fra
|
|||||||
return nil, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
|
return nil, fmt.Errorf("%s expects 2 operands, got %d", mnem, len(ops))
|
||||||
}
|
}
|
||||||
scale := int64(8)
|
scale := int64(8)
|
||||||
if strings.HasSuffix(mnem, "W") {
|
switch {
|
||||||
scale = 4
|
case strings.HasSuffix(mnem, "W"):
|
||||||
|
scale = 4 // the 32-bit pairs, signed and unsigned
|
||||||
|
case strings.HasSuffix(mnem, "Q"):
|
||||||
|
scale = 16 // the 128-bit FP pairs
|
||||||
}
|
}
|
||||||
load := strings.Contains(mnem, "LDP")
|
load := strings.Contains(mnem, "LDP")
|
||||||
memOp, pairOp := ops[0], ops[1]
|
memOp, pairOp := ops[0], ops[1]
|
||||||
|
|||||||
@@ -625,10 +625,12 @@ func TestArm64ADR(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestArm64PairLoadStore pins LDP/STP/LDPW/FLDPD/FSTPD.
|
// TestArm64PairLoadStore pins LDP/STP/LDPW/FLDPD/FSTPD and the 128-bit FP
|
||||||
|
// pairs, whose offsets scale by sixteen.
|
||||||
func TestArm64PairLoadStore(t *testing.T) {
|
func TestArm64PairLoadStore(t *testing.T) {
|
||||||
got := arm64Words(t, "\tSTP (R2, R3), 8(R5)\n\tLDP -8(R5), (R2, R3)\n\tLDPW 4(R0), (R1, R2)\n\tSTPW (R1, R2), 4(R0)\n"+
|
got := arm64Words(t, "\tSTP (R2, R3), 8(R5)\n\tLDP -8(R5), (R2, R3)\n\tLDPW 4(R0), (R1, R2)\n\tSTPW (R1, R2), 4(R0)\n"+
|
||||||
"\tFLDPD 8(R0), (F1, F2)\n\tFSTPD (F3, F4), -8(R5)\n")
|
"\tFLDPD 8(R0), (F1, F2)\n\tFSTPD (F3, F4), -8(R5)\n"+
|
||||||
|
"\tFLDPQ 16(R0), (F1, F2)\n\tFSTPQ (F1, F2), 16(R0)\n")
|
||||||
want := []uint32{
|
want := []uint32{
|
||||||
0xa9008ca2, // STP (R2, R3), 8(R5)
|
0xa9008ca2, // STP (R2, R3), 8(R5)
|
||||||
0xa97f8ca2, // LDP -8(R5), (R2, R3)
|
0xa97f8ca2, // LDP -8(R5), (R2, R3)
|
||||||
@@ -636,6 +638,8 @@ func TestArm64PairLoadStore(t *testing.T) {
|
|||||||
0x29008801, // STPW (R1, R2), 4(R0)
|
0x29008801, // STPW (R1, R2), 4(R0)
|
||||||
0x6d408801, // FLDPD 8(R0), (F1, F2)
|
0x6d408801, // FLDPD 8(R0), (F1, F2)
|
||||||
0x6d3f90a3, // FSTPD (F3, F4), -8(R5)
|
0x6d3f90a3, // FSTPD (F3, F4), -8(R5)
|
||||||
|
0xad408801, // FLDPQ 16(R0), (F1, F2)
|
||||||
|
0xad008801, // FSTPQ (F1, F2), 16(R0)
|
||||||
0xd65f03c0,
|
0xd65f03c0,
|
||||||
}
|
}
|
||||||
if len(got) != len(want) {
|
if len(got) != len(want) {
|
||||||
|
|||||||
@@ -142,7 +142,6 @@ func TestDifferentialKernels(t *testing.T) {
|
|||||||
{filepath.Join("..", "testdata", "verify", "forms_amd64.s"), "", false},
|
{filepath.Join("..", "testdata", "verify", "forms_amd64.s"), "", false},
|
||||||
{filepath.Join("..", "testdata", "verify", "datarel_arm64.s"), "arm64", true},
|
{filepath.Join("..", "testdata", "verify", "datarel_arm64.s"), "arm64", true},
|
||||||
{filepath.Join("..", "testdata", "verify", "divslash_arm64.s"), "arm64", true},
|
{filepath.Join("..", "testdata", "verify", "divslash_arm64.s"), "arm64", true},
|
||||||
{filepath.Join("..", "testdata", "verify", "qmov_arm64.s"), "arm64", true},
|
|
||||||
} {
|
} {
|
||||||
t.Run(filepath.Base(k.path), func(t *testing.T) {
|
t.Run(filepath.Base(k.path), func(t *testing.T) {
|
||||||
src, err := os.ReadFile(k.path)
|
src, err := os.ReadFile(k.path)
|
||||||
|
|||||||
Vendored
+2
@@ -69,4 +69,6 @@ TEXT ·pairs(SB), NOSPLIT, $0-0
|
|||||||
FLDPD (R8), (F1, F2)
|
FLDPD (R8), (F1, F2)
|
||||||
FLDPD 8(R8), (F3, F4)
|
FLDPD 8(R8), (F3, F4)
|
||||||
FSTPD (F3, F4),-8(R9)
|
FSTPD (F3, F4),-8(R9)
|
||||||
|
FLDPQ 16(R8), (F1, F2)
|
||||||
|
FSTPQ (F1, F2), 48(R9)
|
||||||
RET
|
RET
|
||||||
@@ -29,6 +29,7 @@ func TestGroundTruthARM64(t *testing.T) {
|
|||||||
"../testdata/verify/exclusive_arm64.s",
|
"../testdata/verify/exclusive_arm64.s",
|
||||||
"../testdata/verify/shifts_arm64.s",
|
"../testdata/verify/shifts_arm64.s",
|
||||||
"../testdata/verify/atomics_arm64.s",
|
"../testdata/verify/atomics_arm64.s",
|
||||||
|
"../testdata/verify/qmov_arm64.s",
|
||||||
"../testdata/verify/crypto_arm64.s",
|
"../testdata/verify/crypto_arm64.s",
|
||||||
"../testdata/verify/integer_arm64.s",
|
"../testdata/verify/integer_arm64.s",
|
||||||
"../testdata/verify/simd_arm64.s",
|
"../testdata/verify/simd_arm64.s",
|
||||||
|
|||||||
Reference in new issue
Block a user