Section RESTORE_CALLEE_SAVE.
Variable j: meminj.
Variable cs: list stackframe.
Variable fb: block.
Variable sp: block.
Variable ls0: locset.
Variable m: mem.
Definition agree_unused (ls0: locset) (rs: regset) : Prop :=
forall r, ~(mreg_within_bounds b r) -> Val.inject j (ls0 (R r)) (rs r).
End RESTORE_CALLEE_SAVE.
(** As a corollary, we obtain the following correctness result for the execution of a function epilogue (reloading of used callee-save registers + reloading of the link and return address + freeing of the frame). *)

Lemma function_epilogue_correct:
forall m' j sp' ls ls0 pa ra P m rs sp m1 k cs fb,
m' |= frame_contents j sp' ls ls0 pa ra ** minjection j m ** P ->
agree_regs j ls rs ->
agree_locs ls ls0 ->
j sp = Some(sp', fe.(fe_stack_data)) ->
Mem.free m sp 0 f.(Linear.fn_stacksize) = Some m1 ->
exists rs1, exists m1',
load_stack m' (Vptr sp' Ptrofs.zero) Tptr tf.(fn_link_ofs) = Some pa
/\ load_stack m' (Vptr sp' Ptrofs.zero) Tptr tf.(fn_retaddr_ofs) = Some ra
/\ Mem.free m' sp' 0 tf.(fn_stacksize) = Some m1'
/\ star step tge
(State cs fb (Vptr sp' Ptrofs.zero) (restore_callee_save fe k) rs m')
E0 (State cs fb (Vptr sp' Ptrofs.zero) k rs1 m')
/\ agree_regs j (return_regs ls0 ls) rs1
/\ agree_callee_save (return_regs ls0 ls) ls0
/\ m1' |= minjection j m1 ** P.