- fun stackpos (reg: int) = (reg - maxreg) * ~4 (* Stack position of some register number *)
-
- fun spill (X.TEMP temp, xreg: x86.reg) = (* Spill a register if need be. *)
- if (isspilled (X.TEMP temp))
- then [X.MOVL (X.REL (X.RSP, stackpos (temptonum temp)), X.REG xreg)]
- else nil
- | spill _ = nil (* Nothing else can be spilled. *)
- fun unspill (X.TEMP temp, xreg: x86.reg) = (* Unspill a register if need be. *)
- if (isspilled (X.TEMP temp))
- then [X.MOVL (X.REG xreg, X.REL (X.RSP, stackpos (temptonum temp)))]
- else nil
+
+ val stacksz = (nspilled + nsave) * 8
+ fun stackpos (reg: int) = stacksz - (reg - maxreg + nsave) * 8 (* Stack position of some register number *)
+
+ val prologue =
+ (X.SUB ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt stacksz), Tm.Quad))) ::
+ (ListPair.map
+ (fn (num, reg) =>
+ X.MOV ((X.REL ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt (stacksz - 8*(num+1))), Tm.Quad), 0w1), Tm.Quad), (reg, Tm.Quad)))
+ (List.tabulate (nsave, fn x => x), savelist))
+ val epilogue =
+ (ListPair.map
+ (fn (num, reg) =>
+ X.MOV ((reg, Tm.Quad), (X.REL ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt (stacksz - 8*(num+1))), Tm.Quad), 0w1), Tm.Quad)))
+ (List.tabulate (nsave, fn x => x), savelist)) @
+ [X.ADD ((X.REG X.RSP, Tm.Quad), (X.CONST (Word32.fromInt stacksz), Tm.Quad))]
+ val endlbl = Label.new()
+
+ fun spill ((X.TEMP temp, s), xreg: x86.reg) = (* Spill a register if need be. *)
+ let
+ val base = (X.REG X.RSP, Tm.Quad)
+ val offs = (X.CONST (Word32.fromInt (stackpos (temptonum temp))), Tm.Quad)
+ in
+ if (isspilled (X.TEMP temp, s))
+ then [X.MOV ((X.REL (base, offs, 0w1), Tm.Quad), (X.REG xreg, Tm.Quad))]
+ else nil
+ end
+ | spill ((X.STACKARG _, s), _) = raise ErrorMsg.InternalError "Cannot spill to a stack arg"
+ | spill ((a as X.REL _, s), xreg) = [X.MOV ((a,s), (X.REG xreg,s))]
+ | spill _ = nil (* Nothing else can be spilled. *)
+ fun unspill ((X.TEMP temp, s), xreg: x86.reg) = (* Unspill a register if need be. *)
+ let
+ val base = (X.REG X.RSP, Tm.Quad)
+ val offs = (X.CONST (Word32.fromInt (stackpos (temptonum temp))), Tm.Quad)
+ in
+ if (isspilled (X.TEMP temp, s))
+ then [X.MOV ((X.REG xreg, Tm.Quad), (X.REL (base, offs, 0w1), Tm.Quad))]
+ else nil
+ end
+ | unspill ((X.STACKARG arg, s), xreg) =
+ let
+ val base = (X.REG X.RSP, Tm.Quad)
+ val offs = (X.CONST (Word32.fromInt (stacksz + 8 + (arg * 8))), Tm.Quad)
+ in
+ [X.MOV ((X.REG xreg, s), (X.REL (base, offs, 0w1), s))]
+ end
+ | unspill ((a as X.REL _, s), xreg) = [X.MOV ((X.REG xreg, s), (a,s))]