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.

(* Specifications: *)
Lemma length_add_upto:
forall i r s,
length r = length s  ->
length (add_upto i r s) = length r.
Lemma force_lengthn_short:
forall {A} i (b: list A) v,
(i <= length b)%nat -> force_lengthn i b v = firstn i b.
Lemma add_upto_S:
forall (atoh regs : list int) (i : nat),
length atoh = 8%nat ->
length regs = 8%nat ->
(i < 8)%nat ->
map Vint (add_upto (S i) regs atoh) =
upd_Znth (Z.of_nat i) (map Vint (add_upto i regs atoh))
(Vint
(Int.add (nthi (add_upto i regs atoh) (Z.of_nat i))
(nthi atoh (Z.of_nat i)))).
Lemma upd_reptype_array_gso: (* perhaps move to floyd? *)
forall t (a: list (reptype t)) v i j,
0 <= j <= Zlength a ->
0 <= i < Zlength a ->
i<>j ->
Znth i (upd_Znth j a v) = Znth i a.
Lemma int_add_upto:
forall (regs atoh: list int),
Datatypes.length regs = 8%nat ->
Datatypes.length atoh = 8%nat ->
forall (j:nat)  (i:Z),
j = Z.to_nat i ->
0 <= i < 8 ->
is_int I32 Unsigned (Znth i (map Vint (add_upto j  regs atoh))).
Lemma add_s:
forall (regs atoh: list int),
Datatypes.length regs = 8%nat ->
Datatypes.length atoh = 8%nat ->
forall i i',
(i < 8)%nat ->
i' = Z.of_nat i ->
upd_Znth i' (map Vint (add_upto i regs atoh))
(Vint
(Int.add
(Znth i' (add_upto i regs atoh))
(nthi atoh i'))) =
map Vint (add_upto (S i) regs atoh).
Lemma add_upto_8:
forall (regs atoh: list int),
Datatypes.length regs = 8%nat ->
Datatypes.length atoh = 8%nat ->
add_upto 8 regs atoh = map2 Int.add regs atoh.
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))).