fix(asm): carry the arm64 immediate to ZR through MOVZ
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
d786b90fa1
commit
a9b54b6868
2 files changed
+34
-2
No files matched your search
@@ -1820,7 +1820,10 @@ func encodeARM64LoadImm(rd int, v int64, mnem string) ([]byte, error) {
|
|||||||
// `MOVD $4096, R27` is ORR $4096, not MOVZ $(1<<12)
|
// `MOVD $4096, R27` is ORR $4096, not MOVZ $(1<<12)
|
||||||
// - outside that band: MOVZ/MOVN first (C_MOVCON before C_BITCON), and
|
// - outside that band: MOVZ/MOVN first (C_MOVCON before C_BITCON), and
|
||||||
// negative values reach MOVN before the bitmask test
|
// negative values reach MOVN before the bitmask test
|
||||||
tryBitmaskFirst := d > 0 && (d <= 0xFFF || (d&0xFFF == 0 && d <= 0xFFF000))
|
// The bitmask path exists only for a real register: omovconst guards it
|
||||||
|
// with rt != REGZERO, so an immediate to ZR always rides the MOVZ/MOVN
|
||||||
|
// sequence carrying the value.
|
||||||
|
tryBitmaskFirst := rd != 31 && d > 0 && (d <= 0xFFF || (d&0xFFF == 0 && d <= 0xFFF000))
|
||||||
|
|
||||||
if tryBitmaskFirst {
|
if tryBitmaskFirst {
|
||||||
// Addcon-band immediate: try bitmask first (Go uses ORR for values
|
// Addcon-band immediate: try bitmask first (Go uses ORR for values
|
||||||
@@ -1849,7 +1852,7 @@ func encodeARM64LoadImm(rd int, v int64, mnem string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For values outside the bitmask-first range that are not movcon: try bitmask.
|
// For values outside the bitmask-first range that are not movcon: try bitmask.
|
||||||
if !tryBitmaskFirst {
|
if !tryBitmaskFirst && rd != 31 {
|
||||||
N, immr, imms, ok := arm64Bitmask(uint64(d), int(sf))
|
N, immr, imms, ok := arm64Bitmask(uint64(d), int(sf))
|
||||||
if ok {
|
if ok {
|
||||||
return a64wordLE(sf<<31 | 1<<29 | 0x24<<23 | N<<22 | immr<<16 | imms<<10 | 31<<5 | uint32(rd)), nil
|
return a64wordLE(sf<<31 | 1<<29 | 0x24<<23 | N<<22 | immr<<16 | imms<<10 | 31<<5 | uint32(rd)), nil
|
||||||
|
|||||||
@@ -1979,6 +1979,35 @@ func TestArm64SimdArrangementRejections(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestArm64MovImmZR pins the immediate-to-ZR spellings against `go tool asm`
|
||||||
|
// words: omovconst takes the bitmask path only for a real register, so an
|
||||||
|
// immediate to ZR rides the MOVZ/MOVN sequence carrying the value.
|
||||||
|
func TestArm64MovImmZR(t *testing.T) {
|
||||||
|
got := arm64Words(t,
|
||||||
|
"\tMOVW $1, ZR\n"+
|
||||||
|
"\tMOVD $1, ZR\n"+
|
||||||
|
"\tMOVD $0x123456789, ZR\n"+
|
||||||
|
"\tMOVD $-1, ZR\n"+
|
||||||
|
"\tMOVD $0, ZR\n")
|
||||||
|
want := []uint32{
|
||||||
|
0x5280003f, // MOVZ W31, #1
|
||||||
|
0xd280003f, // MOVZ X31, #1
|
||||||
|
0xd28cf13f, // MOVZ X31, #26505
|
||||||
|
0xf2a468bf, // MOVK $(9029<<16), X31
|
||||||
|
0xf2c0003f, // MOVK $(1<<32), X31
|
||||||
|
0x9280001f, // MOVN X31, #0
|
||||||
|
0xaa1f03ff, // ORR X31, XZR, XZR
|
||||||
|
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])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestArm64ConRn pins the MOVD $con(Rn), Rd lowering against `go tool asm`
|
// TestArm64ConRn pins the MOVD $con(Rn), Rd lowering against `go tool asm`
|
||||||
// words: the single ADD/SUB inside the addcon band, the hi<<12 plus lo pair
|
// words: the single ADD/SUB inside the addcon band, the hi<<12 plus lo pair
|
||||||
|
|||||||
Reference in new issue
Block a user