feat(asm): materialise frame-relative addresses the way the toolchain does

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 21:34:30 +02:00
1 parent 1120a52a54
commit c1cef7b6e8
4 files changed
+399 -18

No files matched your search

+53
View File
@@ -403,6 +403,59 @@ func arm64ResolvePseudo(sym *ast.Symbol, fi arm64FrameInfo) (base int, off int32
return -1, 0
}
// arm64FrameAddrValue returns the SP-relative displacement a $sym+off(FP)
// or $sym+off(SP) immediate-address operand stands for, the toolchain's
// aclass arithmetic (asm7.go): a parameter reference sits autosize+8 above
// the hardware SP, and a pseudo-SP reference sits frame+8 above it, the
// alignment padding cancelling out of the autosize.
func arm64FrameAddrValue(sym *ast.Symbol, fi arm64FrameInfo) int64 {
switch sym.Pseudo {
case "FP":
return sym.Offset + int64(fi.autosize) + 8
default: // SP
return sym.Offset + int64(fi.frame) + 8
}
}
// arm64IsAddcon reports whether v is an addcon value (asm7.go isaddcon): an
// unsigned imm12, or a multiple of 4096 whose shifted form fits imm12.
func arm64IsAddcon(v int64) bool {
if v < 0 {
return false
}
if v&0xFFF == 0 {
v >>= 12
}
return v <= 0xFFF
}
// arm64FrameAddrWords returns the word sequence of the toolchain's optab
// case 4 for a frame-relative address (the C_AACON and C_AACON2 rows): one
// ADD/SUB imm12 word inside the addcon band, SUB carrying a negative
// displacement, and otherwise the hi<<12 word from SP followed by the low
// word added in place. The 24-bit band never reaches the REGTMP
// materialisation the ADD/SUB immediate ladder uses: aclass classifies the
// address straight into C_AACON2.
func arm64FrameAddrWords(v int64, rd int) []uint32 {
word := func(v int64, rn int) uint32 {
op := uint32(0) // ADD
if v < 0 {
op = 1 // SUB
v = -v
}
sh := uint32(0)
if v&0xFFF000 != 0 { // asm7.go oaddi: the shift form when low 12 bits are clear
sh = 1
v >>= 12
}
return a64AddSub(1, op, 0, sh, uint32(v), uint32(rn), uint32(rd))
}
if arm64IsAddcon(v) || arm64IsAddcon(-v) {
return []uint32{word(v, 31)}
}
return []uint32{word(v&^int64(0xFFF), 31), word(v&0xFFF, rd)}
}
// arm64PreStoreImm encodes a pre-index store (STR with writeback):
// size<<30 | 7<<27 | V<<26 | opc<<22 | 1<<11 | 1<<10 | imm9<<12 | Rn<<5 | Rt.
func arm64PreStoreImm(size, V int, imm9 int32, rn, rt int) uint32 {