feat(asm): materialise frame-relative addresses the way the toolchain does
Assisted-by: GLM 5.3 Flash
This commit is contained in:
1 parent
1120a52a54
commit
c1cef7b6e8
4 files changed
+399
-18
No files matched your search
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user