fix(arm64): encode shifts, divides and multiplies and align sizes with emission

Assisted-by: GLM 5.3
This commit is contained in:
2026-09-19 23:49:07 +02:00
parent 4258131a3a
commit 401386956c
8 changed files with 742 additions and 160 deletions
+17 -6
View File
@@ -258,22 +258,30 @@ func arm64PrologueSpadjPC(fi arm64FrameInfo) int {
if fi.autosize <= 0xf0 {
return 4 // MOVD.W instruction decrements SP
}
return 8 // SUB + STP + MOVD (3 instructions, SP updated at the MOVD)
// Large frame: [SUB words][STP][ADD R20, SP]; SP moves at the ADD, whose
// position depends on how many words the SUB itself took (immediate,
// shifted immediate, or a materialised REGTMP sequence).
return 4 * (len(arm64SubImmWords(uint32(fi.autosize), 20)) + 1)
}
// arm64ReturnEpilogueLen returns the byte length of the RET's epilogue up to
// (but not including) the final RET instruction.
// (but not including) the final RET instruction. The ADD sequences share the
// prologue's immediate ladder, so their length is read from the same helper
// rather than assumed: a materialised autosize costs its MOV words plus the
// ADD itself.
func arm64ReturnEpilogueLen(fi arm64FrameInfo) int {
if fi.autosize == 0 {
return 0
}
if fi.leaf {
return 8 // ADD + ADD
return 4 * (len(arm64AddImmWords(uint32(fi.autosize-8), 29)) +
len(arm64AddImmWords(uint32(fi.autosize), 31)))
}
if fi.autosize <= 0xf0 {
return 8 // LDR + LDR.P
}
return 8 // LDP + ADD
// LDP + the ADD ladder that deallocates the frame.
return 4 + 4*len(arm64AddImmWords(uint32(fi.autosize), 31))
}
// arm64ResolvePseudo translates a pseudo-register memory reference into a
@@ -382,9 +390,12 @@ func arm64GuardBytes(fi arm64FrameInfo, blockStart int) []byte {
ws = append(ws, wordsOf(mov)...)
ml := len(mov) / 4
ws = append(ws, arm64DPExtWords(arm64OpSubs, 27, 31, 17)) // SUBS R17, RSP, R27
ws = append(ws, br(8+ml, a64CondLO))
// The branches sit at fixed byte offsets in the guard prefix: after
// the LDR (4), the ml MOV words (4*ml) and the SUBS (4) for B.LO,
// then a further B.LO word and the CMP for B.LS.
ws = append(ws, br(8+4*ml, a64CondLO))
ws = append(ws, arm64DPSRWords(arm64OpSubs, 16, 17, 31)) // CMP R16, R17
ws = append(ws, br(8+ml+8, a64CondLS))
ws = append(ws, br(16+4*ml, a64CondLS))
}
return a64WordsLE(ws...)
}