fix(arm64): encode shifts, divides and multiplies and align sizes with emission
Assisted-by: GLM 5.3
This commit is contained in:
+17
-6
@@ -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...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user