Local Open Scope logic.
Definition load8 id ofs :=
(Sset id
(Ederef
(Ebinop Oadd
(Efield
(Ederef (Etempvar _ctx (tptr t_struct_SHA256state_st))
t_struct_SHA256state_st) _h (tarray tuint 8))
(Econst_int (Int.repr ofs) tint) (tptr tuint)) tuint)).
Definition get_h (n: Z) :=
Sset _t
(Ederef
(Ebinop Oadd
(Efield
(Ederef (Etempvar _ctx (tptr t_struct_SHA256state_st))
t_struct_SHA256state_st) _h (tarray tuint 8))
(Econst_int (Int.repr n) tint) (tptr tuint)) tuint).
Definition add_h (n: Z) (i: ident) :=
Sassign
(Ederef
(Ebinop Oadd
(Efield
(Ederef (Etempvar _ctx (tptr t_struct_SHA256state_st))
t_struct_SHA256state_st) _h (tarray tuint 8))
(Econst_int (Int.repr n) tint) (tptr tuint)) tuint)
(Ebinop Oadd (Etempvar _t tuint) (Etempvar i tuint) tuint).
Definition add_them_back :=
[get_h 0; add_h 0 _a;
get_h 1; add_h 1 _b;
get_h 2; add_h 2 _c;
get_h 3; add_h 3 _d;
get_h 4; add_h 4 _e;
get_h 5; add_h 5 _f;
get_h 6; add_h 6 _g;
get_h 7; add_h 7 _h].
Fixpoint add_upto (k: nat) (u v: list int) {struct k} :=
match k with
| O => u
| S k' => match u,v with
| u1::us, v1::vs => Int.add u1 v1 :: add_upto k' us vs
| _, _ => u
end
end.

Lemma add_them_back_proof:
forall (Espec : OracleKind)
(regs regs': list int) (ctx: val) gv (wsh: share) (Hwsh: writable_share wsh),
length regs = 8%nat ->
length regs' = 8%nat ->
semax  (func_tycontext f_sha256_block_data_order Vprog Gtot nil)
(PROP  ()
LOCAL  (temp _ctx ctx;
temp _a  (Vint (nthi regs' 0));
temp _b  (Vint (nthi regs' 1));
temp _c  (Vint (nthi regs' 2));
temp _d  (Vint (nthi regs' 3));
temp _e  (Vint (nthi regs' 4));
temp _f  (Vint (nthi regs' 5));
temp _g  (Vint (nthi regs' 6));
temp _h  (Vint (nthi regs' 7));
gvars gv)
SEP
(field_at wsh t_struct_SHA256state_st  [StructField _h] (map Vint regs) ctx))
(sequence add_them_back Sskip)
(normal_ret_assert
(PROP() LOCAL(temp _ctx ctx; gvars gv)
SEP (field_at wsh t_struct_SHA256state_st  [StructField _h]
(map Vint (map2 Int.add regs regs')) ctx))).