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.

(* Specifications: *)
(* 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.