Definition OutLen h := if Int.eq (Int.repr h) Int.zero then 64 else 32.
Definition fcorePOST_SEP h data d l out :=
CoreInSEP data d *
data_at Tsh (tarray tuchar (OutLen h)) l out.
Definition f_core_POST d out h (data: SixteenByte * SixteenByte * (SixteenByte * SixteenByte) ) :=
EX l:_,
PROP (fcore_result h data l)
LOCAL ()
SEP (fcorePOST_SEP h data d l out).
Definition core_spec :=
DECLARE _core
WITH c : val, k:val, h:Z,
nonce:val, out:val, OUT:list val,
data : SixteenByte * SixteenByte * (SixteenByte * SixteenByte)
PRE [ _out OF tptr tuchar,
_in OF tptr tuchar,
_k OF tptr tuchar,
_c OF tptr tuchar,
_h OF tint ]
PROP ()
LOCAL (temp _in nonce; temp _out out;
temp _c c; temp _k k; temp _h (Vint (Int.repr h)))
SEP (CoreInSEP data (nonce, c, k);
data_at Tsh (tarray tuchar (OutLen h)) OUT out)
POST [ tvoid ] (f_core_POST (nonce, c, k) out h data).
Definition ld32_spec :=
DECLARE _ld32
WITH x : val, B:QuadByte
PRE [ _x OF tptr tuchar ]
PROP ()
LOCAL (temp _x x)
SEP (data_at Tsh (tarray tuchar 4) (QuadByte2ValList B) x)
POST [ tuint ]
PROP ()
LOCAL (temp ret_temp (Vint (littleendian B)))
SEP (QByte B x).
Definition st32_spec :=
DECLARE _st32
WITH x : val, u:int
PRE [ _x OF tptr tuchar, _u OF tuint ]
PROP ()
LOCAL (temp _x x; temp _u (Vint u))
SEP (data_at_ Tsh (tarray tuchar 4) x)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (QByte (littleendian_invert u) x).
Definition L32_spec :=
DECLARE _L32
WITH x : int, c: int
PRE [ _x OF tuint, _c OF tint ]
PROP (0 < Int.signed c < 32) (*yes, c=Int.zero needs to be ruled out - it leads to undefined behaviour in the shift-right operation*)
LOCAL (temp _x (Vint x); temp _c (Vint c))
SEP ()
POST [ tuint ]
PROP ()
LOCAL (temp ret_temp (Vint (Int.rol x c)))
SEP ().
Definition bigendian64 (b c:QuadByte): int64 :=
match b, c with (b0, b1, b2, b3), (c0, c1, c2, c3) =>
Int64.repr
(       Byte.unsigned c3 +
2^8  * Byte.unsigned c2 +
2^16 * Byte.unsigned c1 +
2^24 * Byte.unsigned c0 +
2^32 * Byte.unsigned b3 +
2^40 * Byte.unsigned b2 +
2^48 * Byte.unsigned b1 +
2^56 * Byte.unsigned b0
)
end.
Definition dl64_spec :=
DECLARE _dl64
WITH x : val, B:QuadByte, C: QuadByte
PRE [ _x OF tptr tuchar ]
PROP ()
LOCAL (temp _x x)
SEP (data_at Tsh (tarray tuchar 8) (QuadByte2ValList B++QuadByte2ValList C) x)
POST [ tulong ]
PROP ()
LOCAL (temp ret_temp (Vlong (bigendian64 B C)))
SEP (data_at Tsh (tarray tuchar 8) (QuadByte2ValList B++QuadByte2ValList C) x).
Definition bigendian64_invert (w:int64) : QuadByte * QuadByte:=
let w3 := Int64.unsigned w in
let b3 := w3 / (2^56) in
let w2 := Z.modulo w3 (2^56) in
let b2 := w2 / (2^48) in
let w1 := Z.modulo w2 (2^48) in
let b1 := w1 / (2^40) in
let w0 := Z.modulo w1 (2^40) in
let b0 := w0 / (2^32) in
let u3 := Z.modulo w0 (2^32) in
let c3 := u3 / (2^24) in
let u2 := Z.modulo u3 (2^24) in
let c2 := u2 / (2^16) in
let u1 := Z.modulo u2 (2^16) in
let c1 := u1 / (2^8) in
let c0 := Z.modulo u1 (2^8) in
((Byte.repr b3, Byte.repr b2, Byte.repr b1, Byte.repr b0),
(Byte.repr c3, Byte.repr c2, Byte.repr c1, Byte.repr c0)).

Lemma bigendian64_inv: forall b c: QuadByte, bigendian64_invert (bigendian64 b c) = (b,c).
Definition ts64_spec :=
DECLARE _ts64
WITH x : val, u:int64
PRE [ _x OF tptr tuchar, _u OF tulong ]
PROP ()
LOCAL (temp _x x; temp _u (Vlong u))
SEP (data_at_ Tsh (tarray tuchar 8) x)
POST [ tvoid ]
PROP ()
LOCAL ()
SEP (let (B, C) := bigendian64_invert u in
data_at Tsh (tarray tuchar 8) (QuadByte2ValList B++QuadByte2ValList C) x).