Definition rot8(i: int): int := 
  Int.or (Int.and (Int.shl i (Int.repr 8)) (Int.repr (-1))) (Int.shru i (Int.repr 24)).Definition rotl1(b: int): int :=
  Int.and (Int.or (Int.shl b (Int.repr 1)) (Int.shr b (Int.repr 7))) (Int.repr 255).Definition FSb := map Int.repr sbox.Definition RSb := map Int.repr inv_sbox.Definition calc_FT0(i: Z): int :=
  (Int.xor (Int.xor (Int.xor 
     (times2 (Znth i FSb)) 
     (Int.shl (Znth i FSb) (Int.repr 8)))
     (Int.shl (Znth i FSb) (Int.repr 16)))
     (Int.shl (Int.and (Int.xor (times2 (Znth i FSb)) (Znth i FSb))
                       (Int.repr 255))
              (Int.repr 24))).Definition calc_FT1(i: Z): int := rot8 (calc_FT0 i).Definition calc_FT2(i: Z): int := rot8 (calc_FT1 i).Definition calc_FT3(i: Z): int := rot8 (calc_FT2 i).Definition calc_RT0(i: Z): int :=
  Int.xor (Int.xor (Int.xor
           (mul (Int.repr 14) (Int.repr (Int.unsigned (Znth i RSb))))
  (Int.shl (mul (Int.repr  9) (Int.repr (Int.unsigned (Znth i RSb)))) (Int.repr  8)))
  (Int.shl (mul (Int.repr 13) (Int.repr (Int.unsigned (Znth i RSb)))) (Int.repr 16)))
  (Int.shl (mul (Int.repr 11) (Int.repr (Int.unsigned (Znth i RSb)))) (Int.repr 24)).Definition calc_RT1(i: Z): int := rot8 (calc_RT0 i).Definition calc_RT2(i: Z): int := rot8 (calc_RT1 i).Definition calc_RT3(i: Z): int := rot8 (calc_RT2 i).Definition FT0 := fill_list 256 calc_FT0.Definition FT1 := fill_list 256 calc_FT1.Definition FT2 := fill_list 256 calc_FT2.Definition FT3 := fill_list 256 calc_FT3.Definition RT0 := fill_list 256 calc_RT0.Definition RT1 := fill_list 256 calc_RT1.Definition RT2 := fill_list 256 calc_RT2.Definition RT3 := fill_list 256 calc_RT3.Definition RCON := repeat_op_table 10 Int.one times2.(* TODO Can we achieve the same with "Arguments"?
   "Arguments FSb : simpl never." (etc) does not seem to work *)

(* Instead of looking up the S-box values in a predefined list of constants, gen_tables actually
   calculates it using the following function (for i <> 0): *)
Definition calc_FSb_nonzero(i: Z): int :=
  let x := pow3 (255 - log3 (Int.repr i)) in
  (Int.xor (Int.xor (Int.xor (Int.xor        x 
                                      (rotl1 x))
                               (rotl1 (rotl1 x)))
                        (rotl1 (rotl1 (rotl1 x))))
        (Int.xor (rotl1 (rotl1 (rotl1 (rotl1 x)))) (Int.repr 99))).

(* Specifications: *)
Lemma FSb_equiv: forall i, 1 <= i < 256 -> calc_FSb_nonzero i = Znth i FSb.