Open Scope Z.
(* Note: x must be non-zero, y is allowed to be zero (because x is a constant in all usages, its non-zero-check seems to be removed by the parser). *)
Definition mul_with_table(x y: Z)(pow: list int)(log: list Z): int :=
if Int.eq (if Int.eq (Int.repr y) Int.zero then Int.zero else Int.one) Int.zero
then Int.zero
else Znth (Int.unsigned
(Int.mods (Int.repr (Znth x log + Znth y log))
(Int.repr 255))) pow.
Definition Z_to_val(x: Z): val := if zeq x (-1) then Vundef else Vint (Int.repr x).
(* Calls forward_if with the current precondition to which the provided conditions are added *)
(* QQQ TODO does this already exist? Add to library? *)
Ltac forward_if_diff add := match add with
| (PROPx ?P2 (LOCALx ?Q2 (SEPx ?R2))) => match goal with
| |- semax ?Delta (PROPx ?P1 (LOCALx ?Q1 (SEPx ?R1))) _ _ =>
let P3 := fresh "P3" in let Q3 := fresh "Q3" in let R3 := fresh "R3" in
pose (P3 := P1 ++ P2); pose (Q3 := Q1 ++ Q2); pose (R3 := R1 ++ R2);
simpl in P3, Q3, R3;
forward_if (PROPx P3 (LOCALx Q3 (SEPx R3)));
subst P3 Q3 R3
end
end.
Definition rcon_loop_inv00(i: Z)(v_pow v_log: val)(gv: globals)(frozen: list mpred) : environ -> mpred :=
PROP ( 0 <= i) (* note: the upper bound is added by the tactic, but the lower isn't! *)
LOCAL (temp _x (Vint (pow2 i));
lvar _log (tarray tint 256) v_log;
lvar _pow (tarray tint 256) v_pow;
gvars gv)
SEP (FRZL frozen;
field_at Ews t_struct_tables [StructField _RCON]
((map Vint (repeat_op_table i Int.one times2)) ++ (repeat_op_table (10-i) Vundef id))
(gv _tables)).
Definition rcon_loop_inv0(v_pow v_log: val)(gv: globals)(frozen: list mpred) :=  EX i: Z,
rcon_loop_inv00 i v_pow v_log gv frozen.
(* TODO floyd if I inline inv00 into inv0, why doesn't this typecheck? Definition rcon_loop_inv(v_pow v_log tables: val) := EX i: Z, PROP ( 0 <= i) (* note: the upper bound is added by the tactic, but the lower isn't! *)
LOCAL (temp _x (Vint (pow2 i));
lvar _log (tarray tint 256) v_log;
lvar _pow (tarray tint 256) v_pow;
gvar _tables tables)
SEP (field_at Ews t_struct_tables [StructField _RCON]
((map Vint (repeat_op_table i Int.one times2)) ++ (repeat_op_table (10-i) Vundef id))
tables).
*)
Definition gen_sbox_inv00 i v_pow v_log log pow gv frozen :=
PROP ( )
LOCAL (lvar _log (tarray tint 256) v_log;
lvar _pow (tarray tint 256) v_pow;
gvars gv)
SEP (FRZL frozen; data_at Tsh (tarray tint 256) log v_log; data_at Tsh (tarray tint 256) pow v_pow;
EX fsb : list val,
!!(Zlength fsb = 256) &&
!!(forall j, 0 <= j < i -> Znth j fsb = Vint (Znth j FSb)) &&
!!(Znth 0 fsb = Vint (Int.repr 99))
&& field_at Ews t_struct_tables [StructField _FSb] fsb (gv _tables);
EX rsb : list val,
!!(Zlength rsb = 256) &&
!!(forall j, 1 <= j < i ->
(Znth (Int.unsigned (Znth j FSb)) rsb) = Vint (Int.repr j)) &&
!!(Znth 99 rsb = Vint Int.zero)
&& field_at Ews t_struct_tables [StructField _RSb] rsb (gv _tables)).
Definition gen_sbox_inv0 v_pow v_log log pow gv frozen :=
EX i: Z, gen_sbox_inv00 i v_pow v_log log pow gv frozen.

(* TODO floyd put in sublist? *)
Lemma list_equiv: forall {T: Type}{d: Inhabitant T} (l1 l2: list T) (n: Z),
Zlength l1 = n ->
Zlength l2 = n ->
(forall j, 0 <= j < n -> Znth j l1 = Znth j l2) ->
l1 = l2.