source: src/ASM/ASMCosts.ma @ 1669

Last change on this file since 1669 was 1669, checked in by mulligan, 8 years ago

Commit for claudio

File size: 61.4 KB
Line 
1include "ASM/ASM.ma".
2include "ASM/Arithmetic.ma".
3include "ASM/Fetch.ma".
4include "ASM/Interpret.ma".
5include "common/StructuredTraces.ma".
6
7let rec fetch_program_counter_n
8  (n: nat) (code_memory: BitVectorTrie Byte 16) (program_counter: Word)
9    on n: option Word ≝
10  match n with
11  [ O ⇒ Some … program_counter
12  | S n ⇒
13    match fetch_program_counter_n n code_memory program_counter with
14    [ None ⇒ None …
15    | Some tail_pc ⇒
16      let 〈instr, program_counter, ticks〉 ≝ fetch code_memory tail_pc in
17        if ltb (nat_of_bitvector … tail_pc) (nat_of_bitvector … program_counter) then
18          Some … program_counter
19        else
20          None Word (* XXX: overflow! *)
21    ]
22  ].
23   
24definition reachable_program_counter: BitVectorTrie Byte 16 → nat → Word → Prop ≝
25  λcode_memory: BitVectorTrie Byte 16.
26  λprogram_size: nat.
27  λprogram_counter: Word.
28    (∃n: nat. Some … program_counter = fetch_program_counter_n n code_memory (zero 16)) ∧
29        nat_of_bitvector 16 program_counter < program_size.
30   
31definition good_program: ∀code_memory: BitVectorTrie Byte 16. ∀total_program_size: nat. Prop ≝
32  λcode_memory: BitVectorTrie Byte 16.
33  λtotal_program_size: nat.
34  ∀program_counter: Word.
35  ∀good_program_counter_witness: reachable_program_counter code_memory total_program_size program_counter.
36  let 〈instruction, program_counter', ticks〉 ≝ fetch code_memory program_counter in
37    match instruction with
38    [ RealInstruction instr ⇒
39      match instr with
40      [ RET                    ⇒ True
41      | JC   relative          ⇒ True (* XXX: see below *)
42      | JNC  relative          ⇒ True (* XXX: see below *)
43      | JB   bit_addr relative ⇒ True
44      | JNB  bit_addr relative ⇒ True
45      | JBC  bit_addr relative ⇒ True
46      | JZ   relative          ⇒ True
47      | JNZ  relative          ⇒ True
48      | CJNE src_trgt relative ⇒ True
49      | DJNZ src_trgt relative ⇒ True
50      | _                      ⇒
51        nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' ∧
52          nat_of_bitvector … program_counter' < total_program_size
53      ]
54    | LCALL addr         ⇒
55      match addr return λx. bool_to_Prop (is_in … [[ addr16 ]] x) → Prop with
56      [ ADDR16 addr ⇒ λaddr16: True.
57          reachable_program_counter code_memory total_program_size addr ∧
58            nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' ∧
59              nat_of_bitvector … program_counter' < total_program_size
60      | _ ⇒ λother: False. ⊥
61      ] (subaddressing_modein … addr)
62    | ACALL addr         ⇒
63      match addr return λx. bool_to_Prop (is_in … [[ addr11 ]] x) → Prop with
64      [ ADDR11 addr ⇒ λaddr11: True.
65        let 〈pc_bu, pc_bl〉 ≝ split … 8 8 program_counter' in
66        let 〈thr, eig〉 ≝ split … 3 8 addr in
67        let 〈fiv, thr'〉 ≝ split … 5 3 pc_bu in
68        let new_program_counter ≝ (fiv @@ thr) @@ pc_bl in
69          reachable_program_counter code_memory total_program_size new_program_counter ∧
70            nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' ∧
71              nat_of_bitvector … program_counter' < total_program_size
72      | _ ⇒ λother: False. ⊥
73      ] (subaddressing_modein … addr)
74    | AJMP  addr         ⇒
75      match addr return λx. bool_to_Prop (is_in … [[ addr11 ]] x) → Prop with
76      [ ADDR11 addr ⇒ λaddr11: True.
77        let 〈pc_bu, pc_bl〉 ≝ split … 8 8 program_counter' in
78        let 〈nu, nl〉 ≝ split … 4 4 pc_bu in
79        let bit ≝ get_index' … O ? nl in
80        let 〈relevant1, relevant2〉 ≝ split … 3 8 addr in
81        let new_addr ≝ (nu @@ (bit ::: relevant1)) @@ relevant2 in
82        let 〈carry, new_program_counter〉 ≝ half_add 16 program_counter new_addr in
83          reachable_program_counter code_memory total_program_size new_program_counter
84      | _ ⇒ λother: False. ⊥
85      ] (subaddressing_modein … addr)
86    | LJMP  addr         ⇒
87      match addr return λx. bool_to_Prop (is_in … [[ addr16 ]] x) → Prop with
88      [ ADDR16 addr ⇒ λaddr16: True.
89          reachable_program_counter code_memory total_program_size addr
90      | _ ⇒ λother: False. ⊥
91      ] (subaddressing_modein … addr)
92    | SJMP  addr     ⇒
93      match addr return λx. bool_to_Prop (is_in … [[ relative ]] x) → Prop with
94      [ RELATIVE addr ⇒ λrelative: True.
95        let 〈carry, new_program_counter〉 ≝ half_add … program_counter' (sign_extension addr) in
96          reachable_program_counter code_memory total_program_size new_program_counter
97      | _ ⇒ λother: False. ⊥
98      ] (subaddressing_modein … addr)
99    | JMP   addr     ⇒ (* XXX: JMP is used for fptrs and unconstrained *)
100      nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' ∧
101        nat_of_bitvector … program_counter' < total_program_size
102    | MOVC  src trgt ⇒
103        nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' ∧
104          nat_of_bitvector … program_counter' < total_program_size
105    ].
106  cases other
107qed.
108       
109lemma is_a_decidable:
110  ∀hd.
111  ∀element.
112    is_a hd element = true ∨ is_a hd element = false.
113  #hd #element //
114qed.
115
116lemma mem_decidable:
117  ∀n: nat.
118  ∀v: Vector addressing_mode_tag n.
119  ∀element: addressing_mode_tag.
120    mem … eq_a n v element = true ∨
121      mem … eq_a … v element = false.
122  #n #v #element //
123qed.
124
125lemma eq_a_elim:
126  ∀tag.
127  ∀hd.
128  ∀P: bool → Prop.
129    (tag = hd → P (true)) →
130      (tag ≠ hd → P (false)) →
131        P (eq_a tag hd).
132  #tag #hd #P
133  cases tag
134  cases hd
135  #true_hyp #false_hyp
136  try @false_hyp
137  try @true_hyp
138  try %
139  #absurd destruct(absurd)
140qed.
141 
142lemma is_a_true_to_is_in:
143  ∀n: nat.
144  ∀x: addressing_mode.
145  ∀tag: addressing_mode_tag.
146  ∀supervector: Vector addressing_mode_tag n.
147  mem addressing_mode_tag eq_a n supervector tag →
148    is_a tag x = true →
149      is_in … supervector x.
150  #n #x #tag #supervector
151  elim supervector
152  [1:
153    #absurd cases absurd
154  |2:
155    #n' #hd #tl #inductive_hypothesis
156    whd in match (mem … eq_a (S n') (hd:::tl) tag);
157    @eq_a_elim normalize nodelta
158    [1:
159      #tag_hd_eq #irrelevant
160      whd in match (is_in (S n') (hd:::tl) x);
161      <tag_hd_eq #is_a_hyp >is_a_hyp normalize nodelta
162      @I
163    |2:
164      #tag_hd_neq
165      whd in match (is_in (S n') (hd:::tl) x);
166      change with (
167        mem … eq_a n' tl tag)
168          in match (fold_right … n' ? false tl);
169      #mem_hyp #is_a_hyp
170      cases(is_a hd x)
171      [1:
172        normalize nodelta //
173      |2:
174        normalize nodelta
175        @inductive_hypothesis assumption
176      ]
177    ]
178  ]
179qed.
180
181lemma is_in_subvector_is_in_supervector:
182  ∀m, n: nat.
183  ∀subvector: Vector addressing_mode_tag m.
184  ∀supervector: Vector addressing_mode_tag n.
185  ∀element: addressing_mode.
186    subvector_with … eq_a subvector supervector →
187      is_in m subvector element → is_in n supervector element.
188  #m #n #subvector #supervector #element
189  elim subvector
190  [1:
191    #subvector_with_proof #is_in_proof
192    cases is_in_proof
193  |2:
194    #n' #hd' #tl' #inductive_hypothesis #subvector_with_proof
195    whd in match (is_in … (hd':::tl') element);
196    cases (is_a_decidable hd' element)
197    [1:
198      #is_a_true >is_a_true
199      #irrelevant
200      whd in match (subvector_with … eq_a (hd':::tl') supervector) in subvector_with_proof;
201      @(is_a_true_to_is_in … is_a_true)
202      lapply(subvector_with_proof)
203      cases(mem … eq_a n supervector hd') //
204    |2:
205      #is_a_false >is_a_false normalize nodelta
206      #assm
207      @inductive_hypothesis
208      [1:
209        generalize in match subvector_with_proof;
210        whd in match (subvector_with … eq_a (hd':::tl') supervector);
211        cases(mem_decidable n supervector hd')
212        [1:
213          #mem_true >mem_true normalize nodelta
214          #assm assumption
215        |2:
216          #mem_false >mem_false #absurd
217          cases absurd
218        ]
219      |2:
220        assumption
221      ]
222    ]
223  ]
224qed.
225
226let rec member_addressing_mode_tag
227  (n: nat) (v: Vector addressing_mode_tag n) (a: addressing_mode_tag)
228    on v: Prop ≝
229  match v with
230  [ VEmpty ⇒ False
231  | VCons n' hd tl ⇒
232      bool_to_Prop (eq_a hd a) ∨ member_addressing_mode_tag n' tl a
233  ].
234 
235let rec subaddressing_mode_elim_type
236  (T: Type[2]) (m: nat) (fixed_v: Vector addressing_mode_tag m)
237    (Q: addressing_mode → T → Prop)
238      (p_addr11:            ∀w: Word11.      is_in m fixed_v (ADDR11 w)        → T)
239      (p_addr16:            ∀w: Word.        is_in m fixed_v (ADDR16 w)        → T)
240      (p_direct:            ∀w: Byte.        is_in m fixed_v (DIRECT w)        → T)
241      (p_indirect:          ∀w: Bit.         is_in m fixed_v (INDIRECT w)      → T)
242      (p_ext_indirect:      ∀w: Bit.         is_in m fixed_v (EXT_INDIRECT w)  → T)
243      (p_acc_a:                              is_in m fixed_v ACC_A             → T)
244      (p_register:          ∀w: BitVector 3. is_in m fixed_v (REGISTER w)      → T)
245      (p_acc_b:                              is_in m fixed_v ACC_B             → T)
246      (p_dptr:                               is_in m fixed_v DPTR              → T)
247      (p_data:              ∀w: Byte.        is_in m fixed_v (DATA w)          → T)
248      (p_data16:            ∀w: Word.        is_in m fixed_v (DATA16 w)        → T)
249      (p_acc_dptr:                           is_in m fixed_v ACC_DPTR          → T)
250      (p_acc_pc:                             is_in m fixed_v ACC_PC            → T)
251      (p_ext_indirect_dptr:                  is_in m fixed_v EXT_INDIRECT_DPTR → T)
252      (p_indirect_dptr:                      is_in m fixed_v INDIRECT_DPTR     → T)
253      (p_carry:                              is_in m fixed_v CARRY             → T)
254      (p_bit_addr:          ∀w: Byte.        is_in m fixed_v (BIT_ADDR w)      → T)
255      (p_n_bit_addr:        ∀w: Byte.        is_in m fixed_v (N_BIT_ADDR w)    → T)
256      (p_relative:          ∀w: Byte.        is_in m fixed_v (RELATIVE w)      → T)
257        (n: nat) (v: Vector addressing_mode_tag n) (proof: subvector_with … eq_a v fixed_v)
258      on v: Prop ≝
259  match v return λo: nat. λv': Vector addressing_mode_tag o. o = n → v ≃ v' → ? with
260  [ VEmpty         ⇒ λm_refl. λv_refl.
261      ∀addr: addressing_mode. ∀p: is_in m fixed_v addr.
262        Q addr (
263        match addr return λx: addressing_mode. is_in … fixed_v x → T with 
264        [ ADDR11 x          ⇒ p_addr11 x
265        | ADDR16 x          ⇒ p_addr16 x
266        | DIRECT x          ⇒ p_direct x
267        | INDIRECT x        ⇒ p_indirect x
268        | EXT_INDIRECT x    ⇒ p_ext_indirect x
269        | ACC_A             ⇒ p_acc_a
270        | REGISTER x        ⇒ p_register x
271        | ACC_B             ⇒ p_acc_b
272        | DPTR              ⇒ p_dptr
273        | DATA x            ⇒ p_data x
274        | DATA16 x          ⇒ p_data16 x
275        | ACC_DPTR          ⇒ p_acc_dptr
276        | ACC_PC            ⇒ p_acc_pc
277        | EXT_INDIRECT_DPTR ⇒ p_ext_indirect_dptr
278        | INDIRECT_DPTR     ⇒ p_indirect_dptr
279        | CARRY             ⇒ p_carry
280        | BIT_ADDR x        ⇒ p_bit_addr x
281        | N_BIT_ADDR x      ⇒ p_n_bit_addr x
282        | RELATIVE x        ⇒ p_relative x
283        ] p)
284  | VCons n' hd tl ⇒ λm_refl. λv_refl.
285    let tail_call ≝ subaddressing_mode_elim_type T m fixed_v Q p_addr11
286      p_addr16 p_direct p_indirect p_ext_indirect p_acc_a
287        p_register p_acc_b p_dptr p_data p_data16 p_acc_dptr
288          p_acc_pc p_ext_indirect_dptr p_indirect_dptr p_carry
289            p_bit_addr p_n_bit_addr p_relative n' tl ?
290    in
291    match hd return λa: addressing_mode_tag. a = hd → ? with
292    [ addr11            ⇒ λhd_refl. (∀w. Q (ADDR11 w) (p_addr11 w ?)) → tail_call
293    | addr16            ⇒ λhd_refl. (∀w. Q (ADDR16 w) (p_addr16 w ?)) → tail_call
294    | direct            ⇒ λhd_refl. (∀w. Q (DIRECT w) (p_direct w ?)) → tail_call
295    | indirect          ⇒ λhd_refl. (∀w. Q (INDIRECT w) (p_indirect w ?)) → tail_call
296    | ext_indirect      ⇒ λhd_refl. (∀w. Q (EXT_INDIRECT w) (p_ext_indirect w ?)) → tail_call
297    | acc_a             ⇒ λhd_refl. (Q ACC_A (p_acc_a ?)) → tail_call
298    | registr           ⇒ λhd_refl. (∀w. Q (REGISTER w) (p_register w ?)) → tail_call
299    | acc_b             ⇒ λhd_refl. (Q ACC_A (p_acc_b ?)) → tail_call
300    | dptr              ⇒ λhd_refl. (Q DPTR (p_dptr ?)) → tail_call
301    | data              ⇒ λhd_refl. (∀w. Q (DATA w) (p_data w ?)) → tail_call
302    | data16            ⇒ λhd_refl. (∀w. Q (DATA16 w) (p_data16 w ?)) → tail_call
303    | acc_dptr          ⇒ λhd_refl. (Q ACC_DPTR (p_acc_dptr ?)) → tail_call
304    | acc_pc            ⇒ λhd_refl. (Q ACC_PC (p_acc_pc ?)) → tail_call
305    | ext_indirect_dptr ⇒ λhd_refl. (Q EXT_INDIRECT_DPTR (p_ext_indirect_dptr ?)) → tail_call
306    | indirect_dptr     ⇒ λhd_refl. (Q INDIRECT_DPTR (p_indirect_dptr ?)) → tail_call
307    | carry             ⇒ λhd_refl. (Q CARRY (p_carry ?)) → tail_call
308    | bit_addr          ⇒ λhd_refl. (∀w. Q (BIT_ADDR w) (p_bit_addr w ?)) → tail_call
309    | n_bit_addr        ⇒ λhd_refl. (∀w. Q (N_BIT_ADDR w) (p_n_bit_addr w ?)) → tail_call
310    | relative          ⇒ λhd_refl. (∀w. Q (RELATIVE w) (p_relative w ?)) → tail_call
311    ] (refl … hd)
312  ] (refl … n) (refl_jmeq … v).
313  [20:
314    generalize in match proof; destruct
315    whd in match (subvector_with … eq_a (hd:::tl) fixed_v);
316    cases (mem … eq_a m fixed_v hd) normalize nodelta
317    [1:
318      whd in match (subvector_with … eq_a tl fixed_v);
319      #assm assumption
320    |2:
321      normalize in ⊢ (% → ?);
322      #absurd cases absurd
323    ]
324  ]
325  @(is_in_subvector_is_in_supervector … proof)
326  destruct @I
327qed.
328
329lemma subaddressing_mode_elim':
330  ∀T: Type[2].
331  ∀n: nat.
332  ∀o: nat.
333  ∀Q: addressing_mode → T → Prop.
334  ∀fixed_v: Vector addressing_mode_tag (n + o).
335  ∀P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,P19.
336  ∀v1: Vector addressing_mode_tag n.
337  ∀v2: Vector addressing_mode_tag o.
338  ∀fixed_v_proof: fixed_v = v1 @@ v2.
339  ∀subaddressing_mode_proof.
340    subaddressing_mode_elim_type T (n + o) fixed_v Q P1 P2 P3 P4 P5 P6 P7
341      P8 P9 P10 P11 P12 P13 P14 P15 P16 P17 P18 P19 (n + o) (v1 @@ v2) subaddressing_mode_proof.
342  #T #n #o #Q #fixed_v #P1 #P2 #P3 #P4 #P5 #P6 #P7 #P8 #P9 #P10
343  #P11 #P12 #P13 #P14 #P15 #P16 #P17 #P18 #P19 #v1 #v2 #fixed_v_proof
344  cases daemon
345qed.
346
347axiom subaddressing_mode_elim:
348  ∀T: Type[2].
349  ∀m: nat.
350  ∀n: nat.
351  ∀Q: addressing_mode → T → Prop.
352  ∀fixed_v: Vector addressing_mode_tag m.
353  ∀P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15,P16,P17,P18,P19.
354  ∀v: Vector addressing_mode_tag n.
355  ∀proof.
356    subaddressing_mode_elim_type T m fixed_v Q P1 P2 P3 P4 P5 P6 P7
357      P8 P9 P10 P11 P12 P13 P14 P15 P16 P17 P18 P19 n v proof.
358
359definition current_instruction0 ≝
360  λcode_memory: BitVectorTrie Byte 16.
361  λprogram_counter: Word.
362    \fst (\fst (fetch … code_memory program_counter)).
363
364definition current_instruction ≝
365  λcode_memory.
366  λs: Status code_memory.
367    current_instruction0 code_memory (program_counter … s).
368
369definition ASM_classify0: instruction → status_class ≝
370  λi: instruction.
371  match i with
372   [ RealInstruction pre ⇒
373     match pre with
374      [ RET ⇒ cl_return
375      | JZ _ ⇒ cl_jump
376      | JNZ _ ⇒ cl_jump
377      | JC _ ⇒ cl_jump
378      | JNC _ ⇒ cl_jump
379      | JB _ _ ⇒ cl_jump
380      | JNB _ _ ⇒ cl_jump
381      | JBC _ _ ⇒ cl_jump
382      | CJNE _ _ ⇒ cl_jump
383      | DJNZ _ _ ⇒ cl_jump
384      | _ ⇒ cl_other
385      ]
386   | ACALL _ ⇒ cl_call
387   | LCALL _ ⇒ cl_call
388   | JMP _ ⇒ cl_call
389   | AJMP _ ⇒ cl_jump
390   | LJMP _ ⇒ cl_jump
391   | SJMP _ ⇒ cl_jump
392   | _ ⇒ cl_other
393   ].
394
395definition ASM_classify: ∀code_memory. Status code_memory → status_class ≝
396  λcode_memory.
397  λs: Status code_memory.
398    ASM_classify0 (current_instruction … s).
399
400definition current_instruction_is_labelled ≝
401  λcode_memory.
402  λcost_labels: BitVectorTrie costlabel 16.
403  λs: Status code_memory.
404  let pc ≝ program_counter … code_memory s in
405    match lookup_opt … pc cost_labels with
406    [ None ⇒ False
407    | _    ⇒ True
408    ].
409
410definition next_instruction_properly_relates_program_counters ≝
411  λcode_memory.
412  λbefore: Status code_memory.
413  λafter : Status code_memory.
414  let size ≝ current_instruction_cost code_memory before in
415  let pc_before ≝ program_counter … code_memory before in
416  let pc_after ≝ program_counter … code_memory after in
417  let sum ≝ \snd (half_add … pc_before (bitvector_of_nat … size)) in
418    sum = pc_after.
419
420definition ASM_abstract_status: ∀code_memory. BitVectorTrie costlabel 16 → abstract_status ≝
421  λcode_memory.
422  λcost_labels.
423    mk_abstract_status
424      (Status code_memory)
425      (λs,s'. (execute_1 … s) = s')
426      (λs,class. ASM_classify … s = class)
427      (current_instruction_is_labelled … cost_labels)
428      (next_instruction_properly_relates_program_counters code_memory).
429
430let rec trace_any_label_length
431  (code_memory: BitVectorTrie Byte 16) (cost_labels: BitVectorTrie costlabel 16)
432    (trace_ends_flag: trace_ends_with_ret) (start_status: Status code_memory)
433      (final_status: Status code_memory)
434      (the_trace: trace_any_label (ASM_abstract_status code_memory cost_labels) trace_ends_flag start_status final_status)
435        on the_trace: nat ≝
436  match the_trace with
437  [ tal_base_not_return the_status _ _ _ _ ⇒ 0
438  | tal_base_call pre_fun_call start_fun_call final _ _ _ call_trace _ ⇒ 0
439  | tal_base_return the_status _ _ _ ⇒ 0
440  | tal_step_call end_flag pre_fun_call start_fun_call after_fun_call final _ _ _ call_trace _ final_trace ⇒
441      let tail_length ≝ trace_any_label_length … final_trace in
442      let pc_difference ≝ nat_of_bitvector … (program_counter … after_fun_call) - nat_of_bitvector … (program_counter … pre_fun_call) in       
443        pc_difference + tail_length
444  | tal_step_default end_flag status_pre status_init status_end _ tail_trace _ _ ⇒
445      let tail_length ≝ trace_any_label_length … tail_trace in
446      let pc_difference ≝ nat_of_bitvector … (program_counter … status_init) - nat_of_bitvector … (program_counter … status_pre) in
447        pc_difference + tail_length       
448  ].
449
450let rec compute_paid_trace_any_label
451  (code_memory: BitVectorTrie Byte 16) (cost_labels: BitVectorTrie costlabel 16)
452    (trace_ends_flag: trace_ends_with_ret) (start_status: Status code_memory)
453      (final_status: Status code_memory)
454        (the_trace: trace_any_label (ASM_abstract_status code_memory cost_labels) trace_ends_flag start_status final_status)
455       on the_trace: nat ≝
456  match the_trace with
457  [ tal_base_not_return the_status _ _ _ _ ⇒ current_instruction_cost … the_status
458  | tal_base_return the_status _ _ _ ⇒ current_instruction_cost … the_status
459  | tal_base_call pre_fun_call start_fun_call final _ _ _ call_trace _ ⇒ current_instruction_cost … pre_fun_call
460  | tal_step_call end_flag pre_fun_call start_fun_call after_fun_call final
461     _ _ _ call_trace _ final_trace ⇒
462      let current_instruction_cost ≝ current_instruction_cost … pre_fun_call in
463      let final_trace_cost ≝ compute_paid_trace_any_label … cost_labels end_flag … final_trace in
464        current_instruction_cost + final_trace_cost
465  | tal_step_default end_flag status_pre status_init status_end _ tail_trace _ _ ⇒
466      let current_instruction_cost ≝ current_instruction_cost … status_pre in
467      let tail_trace_cost ≝
468       compute_paid_trace_any_label … cost_labels end_flag
469        status_init status_end tail_trace
470      in
471        current_instruction_cost + tail_trace_cost
472  ].
473
474definition compute_paid_trace_label_label ≝
475  λcode_memory: BitVectorTrie Byte 16.
476  λcost_labels: BitVectorTrie costlabel 16.
477  λtrace_ends_flag: trace_ends_with_ret.
478  λstart_status: Status code_memory.
479  λfinal_status: Status code_memory.
480  λthe_trace: trace_label_label (ASM_abstract_status … cost_labels) trace_ends_flag start_status final_status.
481  match the_trace with
482  [ tll_base ends_flag initial final given_trace labelled_proof ⇒
483      compute_paid_trace_any_label … given_trace
484  ].
485
486include alias "arithmetics/nat.ma".
487include alias "basics/logic.ma".
488
489lemma plus_right_monotone:
490  ∀m, n, o: nat.
491    m = n → m + o = n + o.
492  #m #n #o #refl >refl %
493qed.
494
495(* XXX: indexing bug re-emerges! *)
496example fetch_half_add:
497  ∀code_memory: BitVectorTrie Byte 16.
498  ∀cost_labels: BitVectorTrie costlabel 16.
499  ∀the_status : ASM_abstract_status code_memory cost_labels.
500    \snd (\fst (fetch code_memory (program_counter … the_status))) =
501      \snd (half_add 16 (program_counter … the_status)
502        (bitvector_of_nat … (\snd (fetch code_memory (program_counter … the_status))))).
503  cases daemon
504qed.
505
506axiom half_add_minus_right:
507  ∀size : nat.
508  ∀left : BitVector size.
509  ∀right: nat.
510  nat_of_bitvector … (\snd (half_add … left (bitvector_of_nat … right))) -
511    nat_of_bitvector … left = right.
512
513lemma minus_plus_cancel:
514  ∀m, n : nat.
515  ∀proof: n ≤ m.
516    (m - n) + n = m.
517  #m #n #proof /2 by plus_minus/
518qed.
519
520(* XXX: indexing bug *)
521example fetch_twice_fetch_execute_1:
522  ∀code_memory: BitVectorTrie Byte 16.
523  ∀start_status: Status code_memory.
524    \snd (\fst (fetch code_memory (program_counter … start_status))) =
525      program_counter … (execute_1 … start_status).
526  cases daemon
527qed. (*
528  #code_memory #start_status
529  whd in match (execute_1 code_memory start_status);
530  whd in match (execute_1' code_memory start_status); normalize nodelta
531  cases (fetch code_memory (program_counter … start_status)) #instruction_pc #ticks
532  cases instruction_pc #instruction #pc normalize nodelta *)
533
534lemma blah:
535  ∀code_memory' : (BitVectorTrie Byte 16).
536  ∀program_counter' : Word.
537  ∀total_program_size : ℕ.
538  ∀cost_labels : (BitVectorTrie costlabel 16).
539  ∀reachable_program_counter_witness : (reachable_program_counter code_memory' total_program_size program_counter').
540  ∀good_program_witness : (good_program code_memory' total_program_size).
541  ∀program_size' : ℕ.
542  ∀recursive_case : (total_program_size≤S program_size'+nat_of_bitvector 16 program_counter').
543  ∀ticks : ℕ.
544  ∀instruction : instruction.
545  ∀program_counter'' : Word.
546  ∀FETCH : (〈instruction,program_counter'',ticks〉=fetch code_memory' program_counter').
547  ∀real_instruction : (preinstruction [[relative]]).
548  ∀real_instruction_refl : (RealInstruction … real_instruction = instruction).
549  ∀start_status : (Status code_memory').
550  ∀final_status : (Status code_memory').
551  ∀trace_ends_flag : trace_ends_with_ret.
552  ∀the_trace : (trace_any_label (ASM_abstract_status code_memory' cost_labels) trace_ends_flag start_status final_status).
553  ∀program_counter_refl : (program_counter' = program_counter (BitVectorTrie Byte 16) code_memory' start_status).
554  ∀classify_assm: ASM_classify0 instruction = cl_other.
555  ∀pi1 : ℕ.
556   (if match lookup_opt costlabel 16 program_counter'' cost_labels with 
557         [None ⇒ true
558         |Some _ ⇒ false
559         ] 
560    then
561      ∀start_status0:Status code_memory'.
562      ∀final_status0:Status code_memory'.
563      ∀trace_ends_flag0:trace_ends_with_ret.
564      ∀the_trace0:trace_any_label (ASM_abstract_status code_memory' cost_labels) trace_ends_flag0 start_status0 final_status0.
565        program_counter'' = program_counter (BitVectorTrie Byte 16) code_memory' start_status0 →
566        (∃n:ℕ
567                    .trace_any_label_length code_memory' cost_labels
568                     trace_ends_flag0 start_status0 final_status0 the_trace0
569                     +S n
570                     =total_program_size)
571                   ∧pi1
572                    =compute_paid_trace_any_label code_memory' cost_labels
573                     trace_ends_flag0 start_status0 final_status0 the_trace0
574    else (pi1=O) )
575   →(∃n:ℕ
576     .trace_any_label_length code_memory' cost_labels trace_ends_flag
577      start_status final_status the_trace
578      +S n
579      =total_program_size)
580    ∧ticks+pi1
581     =compute_paid_trace_any_label code_memory' cost_labels trace_ends_flag
582      start_status final_status the_trace.
583  #code_memory' #program_counter' #total_program_size #cost_labels
584  #reachable_program_counter_witness #good_program_witness
585  #program_size' #recursive_case #ticks #instruction #program_counter'' #FETCH
586  #real_instruction #real_instruction_refl #start_status #final_status
587  #trace_ends_flag #the_trace #program_counter_refl #classify_assm #recursive_block_cost
588  #recursive_assm @(trace_any_label_inv_ind … the_trace)
589    [5:
590      #end_flag #status_pre #status_init #status_end #execute_assm #trace_any_label
591      #classifier_assm #costed_assm #trace_ends_refl #start_status_refl #final_status_refl
592      #the_trace_refl
593      destruct
594      whd in match (trace_any_label_length … (tal_step_default …));
595      whd in match (compute_paid_trace_any_label … (tal_step_default …));
596      whd in costed_assm:(?%);
597      generalize in match costed_assm;
598      generalize in match (refl … (lookup_opt … (program_counter … (execute_1 … status_pre)) cost_labels));
599      generalize in match (lookup_opt … (program_counter … (execute_1 … status_pre)) cost_labels)
600        in ⊢ (??%? → ?(match % with [ _ ⇒ ? | _ ⇒ ? ]) → ?);
601      #lookup_assm cases lookup_assm
602      [1:
603        #None_lookup_opt_assm normalize nodelta #ignore
604        generalize in match recursive_assm;
605        cut(program_counter'' = (program_counter (BitVectorTrie Byte 16) code_memory' (execute_1 code_memory' status_pre)))
606        [1:
607          <fetch_twice_fetch_execute_1 <FETCH %
608        |2:
609          #program_counter_assm >program_counter_assm <None_lookup_opt_assm
610          normalize nodelta #new_recursive_assm
611          cases(new_recursive_assm (execute_1 code_memory' status_pre) status_end
612            end_flag trace_any_label ?) [2: % ]
613          #exists_assm #recursive_block_cost_assm %
614          [1:
615            cases exists_assm #exists_n #total_program_size_refl
616            <total_program_size_refl
617            %{(exists_n - current_instruction_cost … status_pre)}
618          |2:
619            >recursive_block_cost_assm
620            whd in match (current_instruction_cost … status_pre);
621            cut(ticks = \snd (fetch code_memory'
622               (program_counter (BitVectorTrie Byte 16) code_memory' status_pre)))
623            [1:
624              <FETCH %
625            |2:
626              #ticks_refl_assm >ticks_refl_assm %
627            ]
628          ]
629        ]
630      |2:
631        #costlabel #Some_lookup_opt_assm <Some_lookup_opt_assm normalize nodelta
632        #absurd cases absurd #absurd cases(absurd I)
633      ]
634    |1:
635      #status_start #status_final #execute_assm #classifier_assm #costed_assm
636      #trace_ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
637      destruct
638      whd in match (trace_any_label_length … (tal_base_not_return …));
639      whd in match (compute_paid_trace_any_label … (tal_base_not_return …));
640      whd in costed_assm;
641      generalize in match costed_assm;
642      generalize in match (refl … (lookup_opt … (program_counter … (execute_1 … status_start)) cost_labels));
643      generalize in match (lookup_opt … (program_counter … (execute_1 code_memory' status_start)) cost_labels)
644        in ⊢ (??%? → (match % with [ _ ⇒ ? | _ ⇒ ? ]) → ?);
645      #lookup_assm cases lookup_assm
646      [1:
647        #None_lookup_opt_assm normalize nodelta >None_lookup_opt_assm
648        #absurd cases absurd
649      |2:
650        #costlabel #Some_lookup_opt_assm normalize nodelta #ignore
651        generalize in match recursive_assm;
652        cut(program_counter'' = (program_counter (BitVectorTrie Byte 16) code_memory' (execute_1 … status_start)))
653        [1:
654          <fetch_twice_fetch_execute_1 <FETCH %
655        |2:
656          #program_counter_assm >program_counter_assm <Some_lookup_opt_assm
657          normalize nodelta #new_recursive_assm >new_recursive_assm %
658          [1:
659            %{(pred total_program_size)} whd in ⊢ (??%?);
660            @S_pred
661            generalize in match good_program_witness;
662            whd in match (good_program … total_program_size);
663            #good_program_hyp
664            lapply(good_program_hyp (program_counter … status_start) reachable_program_counter_witness)
665            <FETCH normalize nodelta -good_program_hyp (* XXX: Claudio here *)
666          |2:
667            cut(ticks = \snd (fetch code_memory'
668               (program_counter (BitVectorTrie Byte 16) code_memory' status_start)))
669            [1:
670              <FETCH %
671            |2:
672              #ticks_refl_assm >ticks_refl_assm
673              <plus_n_O %
674            ]
675          ]
676        ]
677      |2:
678        #costlabel #Some_lookup_opt_assm <Some_lookup_opt_assm normalize nodelta
679        #absurd cases absurd #absurd cases(absurd I)
680      ]
681    |2:
682      #start_status' #final_status' #execute_assm #classifier_assm #trace_ends_assm
683      #start_status_refl #final_status_refl #the_trace_assm destruct @⊥
684    |3:
685      #status_pre_fun_call #status_start_fun_call #status_final #execute_assm
686      #classifier_assm #after_return_assm #trace_label_return #costed_assm
687      #ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
688      destruct @⊥
689    ]
690      change with (
691        ASM_classify0 ? = ?) in classifier_assm;
692      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
693      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
694      <FETCH in classifier_assm; >classify_assm #absurd destruct(absurd)
695qed.
696
697let rec block_cost'
698  (code_memory': BitVectorTrie Byte 16) (program_counter': Word)
699    (program_size: nat) (total_program_size: nat) (cost_labels: BitVectorTrie costlabel 16)
700      (reachable_program_counter_witness: reachable_program_counter code_memory' total_program_size program_counter')
701        (good_program_witness: good_program code_memory' total_program_size) (first_time_around: bool)
702          on program_size:
703          total_program_size ≤ program_size + nat_of_bitvector … program_counter' →
704          Σcost_of_block: nat.
705          if (match lookup_opt … program_counter' cost_labels with [ None ⇒ true | _ ⇒ first_time_around ]) then
706            ∀start_status: Status code_memory'.
707            ∀final_status: Status code_memory'.
708            ∀trace_ends_flag.
709            ∀the_trace: trace_any_label (ASM_abstract_status … cost_labels) trace_ends_flag start_status final_status.
710              program_counter' = program_counter … start_status →
711                (∃n: nat. trace_any_label_length … the_trace + (S n) = total_program_size) ∧
712                  cost_of_block = compute_paid_trace_any_label code_memory' cost_labels trace_ends_flag start_status final_status the_trace
713          else
714            (cost_of_block = 0) ≝
715  match program_size return λprogram_size: nat. total_program_size ≤ program_size + nat_of_bitvector … program_counter' → ? with
716  [ O ⇒ λbase_case. ⊥
717  | S program_size' ⇒ λrecursive_case.
718    let 〈instruction, program_counter'', ticks〉 as FETCH ≝ fetch code_memory' program_counter' in
719    let to_continue ≝
720      match lookup_opt … program_counter' cost_labels with
721      [ None ⇒ true
722      | Some _ ⇒ first_time_around
723      ]
724    in
725      ((if to_continue then
726       pi1 … (match instruction return λx. x = instruction → ? with
727        [ RealInstruction real_instruction ⇒ λreal_instruction_refl.
728          match real_instruction return λx. x = real_instruction →
729          Σcost_of_block: nat.
730            ∀start_status: Status code_memory'.
731            ∀final_status: Status code_memory'.
732            ∀trace_ends_flag.
733            ∀the_trace: trace_any_label (ASM_abstract_status code_memory' cost_labels) trace_ends_flag start_status final_status.
734              program_counter' = program_counter … start_status →
735                (∃n: nat. trace_any_label_length … the_trace + (S n) = total_program_size) ∧
736                  cost_of_block = compute_paid_trace_any_label code_memory' cost_labels trace_ends_flag start_status final_status the_trace with
737          [ RET                    ⇒ λinstr. ticks
738          | JC   relative          ⇒ λinstr. ticks
739          | JNC  relative          ⇒ λinstr. ticks
740          | JB   bit_addr relative ⇒ λinstr. ticks
741          | JNB  bit_addr relative ⇒ λinstr. ticks
742          | JBC  bit_addr relative ⇒ λinstr. ticks
743          | JZ   relative          ⇒ λinstr. ticks
744          | JNZ  relative          ⇒ λinstr. ticks
745          | CJNE src_trgt relative ⇒ λinstr. ticks
746          | DJNZ src_trgt relative ⇒ λinstr. ticks
747          | _                      ⇒ λinstr.
748         
749              ticks + block_cost' code_memory' program_counter'' program_size' total_program_size cost_labels ? good_program_witness false ?
750          ] (refl …)
751        | ACALL addr     ⇒ λinstr.
752            ticks + block_cost' code_memory' program_counter'' program_size' total_program_size cost_labels ? good_program_witness false ?
753        | AJMP  addr     ⇒ λinstr. ticks
754        | LCALL addr     ⇒ λinstr.
755            ticks + block_cost' code_memory' program_counter'' program_size' total_program_size cost_labels ? good_program_witness false ?
756        | LJMP  addr     ⇒ λinstr. ticks
757        | SJMP  addr     ⇒ λinstr. ticks
758        | JMP   addr     ⇒ λinstr. (* XXX: actually a call due to use with fptrs *)
759            ticks + block_cost' code_memory' program_counter'' program_size' total_program_size cost_labels ? good_program_witness false ?
760        | MOVC  src trgt ⇒ λinstr.
761            ticks + block_cost' code_memory' program_counter'' program_size' total_program_size cost_labels ? good_program_witness false ?
762        ] (refl …))
763      else
764        0)
765      : Σcost_of_block: nat.
766          match (match lookup_opt … program_counter' cost_labels with [ None ⇒ true | _ ⇒ first_time_around ]) with
767          [ true ⇒
768            ∀start_status: Status code_memory'.
769            ∀final_status: Status code_memory'.
770            ∀trace_ends_flag.
771            ∀the_trace: trace_any_label (ASM_abstract_status … cost_labels) trace_ends_flag start_status final_status.
772              program_counter' = program_counter … start_status →
773                (∃n: nat. trace_any_label_length … the_trace + (S n) = total_program_size) ∧
774                  cost_of_block = compute_paid_trace_any_label code_memory' cost_labels trace_ends_flag start_status final_status the_trace
775          | false ⇒
776            (cost_of_block = 0)
777          ])
778  ].
779  [1:
780    cases reachable_program_counter_witness #_ #hyp
781    @(absurd (total_program_size < total_program_size) … (not_le_Sn_n …))
782    @(le_to_lt_to_lt … base_case hyp)
783  |2:
784      change with (
785        if to_continue then
786          ?
787        else
788          (? = 0)) >p in ⊢ (match % return ? with [ _ ⇒ ? | _ ⇒ ? ]); normalize nodelta
789       @pi2
790  |3:
791    change with (
792      if to_continue then
793        ?
794      else
795        (0 = 0)) >p normalize nodelta %
796  |4:
797    #start_status #final_status #trace_ends_flag #the_trace #program_counter_refl
798    cases(block_cost' ?????????) -block_cost'
799    @(blah … reachable_program_counter_witness good_program_witness … recursive_case … FETCH … real_instruction_refl … the_trace program_counter_refl …)
800    destruct %
801  |4:
802    #start_status #final_status #trace_ends_flag #the_trace #program_counter_refl
803    cases(block_cost' ?????????) -block_cost'
804    #recursive_block_cost #recursive_assm
805    @(trace_any_label_inv_ind … the_trace)
806    [1:
807      #status_start #status_final #execute_assm #classifier_assm #costed_assm
808      #trace_ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
809      destruct
810      whd in match (trace_any_label_length … (tal_base_not_return …));
811      whd in match (compute_paid_trace_any_label … (tal_base_not_return …));
812      whd in costed_assm;
813    |2:
814      #start_status' #final_status' #execute_assm #classifier_assm #trace_ends_assm
815      #start_status_refl #final_status_refl #the_trace_assm destruct
816      whd in classifier_assm;
817      whd in classifier_assm:(??%?);
818      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
819      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
820      @⊥ <FETCH in classifier_assm; normalize nodelta
821      #absurd destruct(absurd)
822    |3:
823      #status_pre_fun_call #status_start_fun_call #status_final #execute_assm
824      #classifier_assm #after_return_assm #trace_label_return #costed_assm
825      #ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
826      destruct
827      whd in classifier_assm;
828      whd in classifier_assm:(??%?);
829      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
830      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
831      @⊥ <FETCH in classifier_assm; normalize nodelta
832      #absurd destruct(absurd)
833    |4:
834      #end_flag #status_pre_fun_call #status_start_fun_call #status_after_fun_call
835      #status_final #execute_assm #classifier_assm #after_return_assm
836      #trace_label_return #costed_assm #trace_any_label #ends_flag_refl
837      #start_status_refl #final_status_refl #the_trace_refl
838      destruct
839      whd in classifier_assm;
840      whd in classifier_assm:(??%?);
841      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
842      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
843      @⊥ <FETCH in classifier_assm; normalize nodelta
844      #absurd destruct(absurd)
845    |5:
846    ]
847   
848   
849   
850   
851   
852   
853   
854   
855   
856   
857   
858   
859   
860   
861   
862   
863   
864   
865   
866   
867   
868   
869   
870   
871   
872   
873   
874   
875   
876    |3:
877      #status_pre_fun_call #status_start_fun_call #status_final #execute_assm
878      #classifier_assm #after_return_assm #trace_label_return #costed_assm
879      #trace_ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
880      destruct
881      whd in match (compute_paid_trace_any_label … (tal_base_call …));
882      whd in match (trace_any_label_length … (tal_base_call …));
883      cases(recursive_assm …
884        (tal_base_call (ASM_abstract_status code_memory' cost_labels)
885         status_pre_fun_call (execute_1 … status_pre_fun_call) status_final (refl …)
886         classifier_assm after_return_assm trace_label_return costed_assm) ?)
887      [1:
888        * #recursive_n #recursive_trace_total #recursive_block_cost_assm %
889        [1:
890          %{(pred total_program_size)}
891          whd in ⊢ (??%?);
892          >S_pred [1: % ]
893          <recursive_trace_total
894          @lt_O_S
895        |2:
896          >recursive_block_cost_assm
897          whd in ⊢ (??(??%)?); <FETCH
898          (* XXX: ??? *)
899        ]
900      |2:
901        cut(program_counter'' = \snd (\fst (fetch code_memory' (program_counter … status_pre_fun_call))))
902        [1:
903          cases FETCH %
904        |2:
905          #program_counter_hyp'' >program_counter_hyp''
906          whd in after_return_assm; <after_return_assm
907          whd in match (current_instruction_cost status_pre_fun_call);
908          @fetch_half_add
909        ]
910      ]
911    |4:
912      #end_flag #status_pre_fun_call #status_start_fun_call #status_after_fun_call
913      #status_final #execute_assm #classifier_assm #after_return_assm #trace_label_return
914      #costed_assm #trace_any_label #trace_ends_flag_refl #start_status_refl
915      #final_status_refl #the_trace_refl
916      generalize in match execute_assm; destruct #execute_assm
917      whd in match (compute_paid_trace_any_label … (tal_step_call …));
918      whd in match (trace_any_label_length … (tal_step_call …));
919      cases(recursive_assm status_after_fun_call status_final end_flag trace_any_label ? ?)
920      [1:
921        * #recursive_n #recursive_trace_total #recursive_block_cost_assm %
922        [1:
923          <recursive_trace_total %
924          [1:
925            @(recursive_n - (current_instruction_cost status_pre_fun_call))
926          |2:
927            whd in after_return_assm; cases after_return_assm
928            >half_add_minus_right in ⊢ (??%?);
929            >commutative_plus in ⊢ (???%);
930            >commutative_plus in ⊢ (??%?);
931            <associative_plus in ⊢ (??%?);
932            @plus_right_monotone
933            cut(current_instruction_cost status_pre_fun_call ≤ recursive_n)
934            [1:
935              (* XXX: ??? *)
936            |2:
937              #current_instruction_cost_assm
938              <minus_Sn_m in ⊢ (??%?); [2: assumption ]
939              >minus_plus_cancel [1: % ]
940              @le_S assumption
941            ]
942          ]
943        |2:
944          >recursive_block_cost_assm
945          @plus_right_monotone
946          whd in match (current_instruction_cost status_pre_fun_call);
947          <FETCH %
948        ]
949     
950      |2:
951        lapply (trace_label_return_preserves_code_memory … (execute_1 status_pre_fun_call) status_after_fun_call)
952        #hyp cases (hyp trace_label_return)
953        @as_execute_preserves_code_memory whd %
954      |3:
955        cut(program_counter'' = \snd (\fst (fetch (code_memory … status_pre_fun_call) (program_counter … status_pre_fun_call))))
956        [1:
957          cases FETCH %
958        |2:
959          #program_counter_hyp'' >program_counter_hyp''
960          whd in after_return_assm; <after_return_assm
961          whd in match (current_instruction_cost status_pre_fun_call);
962          @fetch_half_add
963        ]
964      ]
965    |5:
966      #end_flag #status_pre #status_init #status_end #execute_assm #the_trace'
967      #classifier_assm #costed_assm #trace_ends_flag_refl #start_status_refl
968      #final_status_refl #trace_refl
969      generalize in match the_trace; destruct #the_trace
970      whd in classifier_assm;
971      whd in classifier_assm:(??%?);
972      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
973      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
974      @⊥ <FETCH in classifier_assm; normalize nodelta
975      #absurd destruct(absurd)
976    ]
977  |7,8,9,10,13,16,19,22,25,28,31,34,37,40,41,42,43,44,45,46,47,48,49,52,55,58,61,
978    64,67,70,73,76,79,82,85,88,91,94,97,100,101,104,108,107:
979    cases daemon (* XXX: massive terms *)
980  |2:
981    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
982    lapply(good_program_witness program_counter' reachable_program_counter_witness)
983    <FETCH normalize nodelta <instr normalize nodelta
984    @(subaddressing_mode_elim … [[addr11]] … [[addr11]]) [1: // ] #new_addr
985    cases (split … 8 8 program_counter'') #pc_bu #pc_bl normalize nodelta
986    cases (split … 3 8 new_addr) #thr #eig normalize nodelta
987    cases (split … 5 3 pc_bu) #fiv #thr' normalize nodelta * * * * #n'
988    #_ #_ #program_counter_lt' #program_counter_lt_tps'     
989    @(transitive_le
990      total_program_size
991      ((S program_size') + nat_of_bitvector … program_counter')
992      (program_size' + nat_of_bitvector … program_counter'') recursive_case)
993    normalize in match (S program_size' + nat_of_bitvector … program_counter');
994    >plus_n_Sm
995    @monotonic_le_plus_r
996    change with (
997      nat_of_bitvector … program_counter' <
998        nat_of_bitvector … program_counter'')
999    assumption
1000  |3:
1001    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1002    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1003    <FETCH normalize nodelta <instr normalize nodelta
1004    @(subaddressing_mode_elim … [[addr11]] … [[addr11]]) [1: // ] #new_addr
1005    cases (split … 8 8 program_counter'') #pc_bu #pc_bl normalize nodelta
1006    cases (split … 3 8 new_addr) #thr #eig normalize nodelta
1007    cases (split … 5 3 pc_bu) #fiv #thr' normalize nodelta * * * * #n'
1008    #_ #_ #program_counter_lt' #program_counter_lt_tps'
1009    %
1010    [1:
1011      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1012      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1013      >(le_to_leb_true … program_counter_lt') %
1014    |2:
1015      assumption
1016    ]
1017  |5:
1018    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1019    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1020      <FETCH normalize nodelta <instr normalize nodelta
1021    @(subaddressing_mode_elim … [[addr16]] … [[addr16]]) [1: // ] #new_addr
1022    * * * * #n'
1023    #_ #_ #program_counter_lt' #program_counter_lt_tps'     
1024    @(transitive_le
1025      total_program_size
1026      ((S program_size') + nat_of_bitvector … program_counter')
1027      (program_size' + nat_of_bitvector … program_counter'') recursive_case)
1028    normalize in match (S program_size' + nat_of_bitvector … program_counter');
1029    >plus_n_Sm
1030    @monotonic_le_plus_r
1031    change with (
1032      nat_of_bitvector … program_counter' <
1033        nat_of_bitvector … program_counter'')
1034    assumption
1035  |6:
1036    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1037    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1038      <FETCH normalize nodelta <instr normalize nodelta
1039    @(subaddressing_mode_elim … [[addr16]] … [[addr16]]) [1: // ] #new_addr
1040    * * * * #n'
1041    #_ #_ #program_counter_lt' #program_counter_lt_tps'
1042    %
1043    [1:
1044      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1045      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1046      >(le_to_leb_true … program_counter_lt') %
1047    |2:
1048      assumption
1049    ]
1050  |11,14: (* JMP and MOVC *)
1051    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1052    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1053    <FETCH normalize nodelta <instr normalize nodelta
1054    try(<real_instruction_refl <instr normalize nodelta) *
1055    #pc_pc_lt_hyp' #pc_tps_lt_hyp'
1056    @(transitive_le
1057      total_program_size
1058      ((S program_size') + nat_of_bitvector … program_counter')
1059      (program_size' + nat_of_bitvector … program_counter'') recursive_case)
1060    normalize in match (S program_size' + nat_of_bitvector … program_counter');
1061    >plus_n_Sm
1062    @monotonic_le_plus_r
1063    change with (
1064      nat_of_bitvector … program_counter' <
1065        nat_of_bitvector … program_counter'')
1066    assumption
1067  |12,15:
1068    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1069    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1070    <FETCH normalize nodelta <instr normalize nodelta *
1071    #program_counter_lt' #program_counter_lt_tps' %
1072    [1,3:
1073      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1074      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1075      >(le_to_leb_true … program_counter_lt') %
1076    |2,4:
1077      assumption
1078    ]
1079  |17,20,23,26,29,32,35,38,50,53,56,59,62,65,68,71,74,77,80,83,86,89,92,95,98,
1080   102,105:
1081    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1082    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1083    <FETCH normalize nodelta
1084    <real_instruction_refl <instr normalize nodelta *
1085    #pc_pc_lt_hyp' #pc_tps_lt_hyp'
1086    @(transitive_le
1087      total_program_size
1088      ((S program_size') + nat_of_bitvector … program_counter')
1089      (program_size' + nat_of_bitvector … program_counter'') recursive_case)
1090    normalize in match (S program_size' + nat_of_bitvector … program_counter');
1091    >plus_n_Sm
1092    @monotonic_le_plus_r
1093    change with (
1094      nat_of_bitvector … program_counter' <
1095        nat_of_bitvector … program_counter'')
1096    assumption
1097  |18,21,24,27,30,33,36,39,51,54,57,60,63,66,69,72,75,78,
1098    81,84,87,90,93,96,99,103,106:
1099    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1100    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1101    <FETCH normalize nodelta <real_instruction_refl <instr normalize nodelta *
1102    #program_counter_lt' #program_counter_lt_tps' %
1103    try assumption
1104    [*:
1105      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1106      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1107      >(le_to_leb_true … program_counter_lt') %
1108    ]
1109  [1:
1110    #start_status #final_status #trace_ends_flag #the_trace #code_memory_refl #program_counter_refl
1111    cases(block_cost' ?????? ?? ?) -block_cost'
1112    #recursive_block_cost #recursive_assm
1113    @(trace_any_label_inv_ind … the_trace)
1114    [1:
1115      #start_status' #final_status' #execute_assm #classifier_assm #costed_assm
1116      #ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl destruct
1117      cases classifier_assm
1118      whd in match (as_classifier ? ? ?);
1119      whd in ⊢ (??%? → ?);
1120      whd in match current_instruction; normalize nodelta
1121      whd in match current_instruction0; normalize nodelta
1122      #absurd @⊥ >p1 in absurd; normalize nodelta
1123      #absurd destruct(absurd)
1124    |2:
1125      #start_status' #final_status' #execute_assm #classifier_assm #trace_ends_assm
1126      #start_status_refl #final_status_refl #the_trace_assm destruct
1127      whd in classifier_assm;
1128      whd in classifier_assm:(??%?);
1129      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
1130      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
1131      @⊥
1132      >p1 in classifier_assm; normalize nodelta
1133      #absurd destruct(absurd)
1134    |3:
1135      #status_pre_fun_call #status_start_fun_call #status_final #execute_assm
1136      #classifier_assm #after_return_assm #trace_label_return #costed_assm
1137      #trace_ends_flag_refl #start_status_refl #final_status_refl #the_trace_refl
1138      destruct
1139      cases(recursive_assm status_pre_fun_call status_final doesnt_end_with_ret
1140        (tal_base_call (ASM_abstract_status cost_labels) status_pre_fun_call
1141          (execute_1 status_pre_fun_call) status_final
1142          (refl Status (execute_1 status_pre_fun_call)) classifier_assm
1143          after_return_assm trace_label_return costed_assm) ? ?)
1144      [2: %
1145      |3:
1146      |1:
1147      ]
1148    |4:
1149      #end_flag #status_pre_fun_call #status_start_fun_call #status_after_fun_call
1150      #status_final #execute_assm #classifier_assm #after_return_assm #trace_label_return
1151      #costed_assm #trace_any_label #trace_ends_refl #start_status_refl #final_status_refl
1152      #the_trace_refl destruct whd in ⊢ (??(???%)); whd in match (trace_any_label_length … (tal_step_call … trace_any_label));
1153    |5:
1154      #end_flag #status_pre #status_init #status_end #execute_assm #the_trace
1155      #classifier_assm #costed_assm #ends_flag_refl #start_status_refl #final_status_refl
1156      #the_trace_refl -the_trace_refl destruct
1157      whd in classifier_assm;
1158      whd in classifier_assm:(??%?);
1159      whd in match current_instruction in classifier_assm; normalize nodelta in classifier_assm;
1160      whd in match current_instruction0 in classifier_assm; normalize nodelta in classifier_assm;
1161      @⊥ >p1 in classifier_assm; normalize nodelta
1162      #absurd destruct(absurd)
1163    ]
1164  [1:
1165    #start_status #final_status #trace_ends_flag #the_trace
1166    #code_memory_refl #program_counter_refl
1167    cases(block_cost' ?????? ?? ?) -block_cost'
1168    #recursive_block_cost #recursive_assm
1169    @(trace_any_label_inv_ind … the_trace)
1170    [1:
1171      #start_status' #final_status' #execute_assm #not_return_assm
1172      #costed_assm #trace_ends_flag_assm #start_status_assm #final_status_assm
1173      #the_trace_assm
1174      cases daemon (* XXX: bug in notion of traces here *)
1175    |2:
1176
1177    |3:
1178      cases daemon (* XXX *)
1179    |4:
1180    ]
1181  |108:
1182    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1183    lapply(good_program_witness program_counter' reachable_program_counter_witness)
1184    <FETCH normalize nodelta <real_instruction_refl <instr normalize nodelta *
1185    #program_counter_lt' #program_counter_lt_tps' %
1186    try assumption
1187    [*:
1188      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1189      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1190      >(le_to_leb_true … program_counter_lt') %
1191    ]
1192  [1:
1193    cases reachable_program_counter_witness #_ #hyp
1194    @(absurd (total_program_size < total_program_size) … (not_le_Sn_n …))
1195    @(le_to_lt_to_lt … base_case hyp)
1196  |2:
1197    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1198    lapply(good_program_witness program_counter reachable_program_counter_witness)
1199      <FETCH normalize nodelta <instr normalize nodelta
1200    @(subaddressing_mode_elim … [[addr11]] … [[addr11]]) [1: // ] #new_addr
1201    cases (split … 8 8 program_counter') #pc_bu #pc_bl normalize nodelta
1202    cases (split … 3 8 new_addr) #thr #eig normalize nodelta
1203    cases (split … 5 3 pc_bu) #fiv #thr' normalize nodelta * * * * #n'
1204    #_ #_ #program_counter_lt' #program_counter_lt_tps'     
1205    @(transitive_le
1206      total_program_size
1207      ((S program_size') + nat_of_bitvector … program_counter)
1208      (program_size' + nat_of_bitvector … program_counter') recursive_case)
1209    normalize in match (S program_size' + nat_of_bitvector … program_counter);
1210    >plus_n_Sm
1211    @monotonic_le_plus_r
1212    change with (
1213      nat_of_bitvector … program_counter <
1214        nat_of_bitvector … program_counter')
1215    assumption
1216  |3:
1217    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1218    lapply(good_program_witness program_counter reachable_program_counter_witness)
1219      <FETCH normalize nodelta <instr normalize nodelta
1220    @(subaddressing_mode_elim … [[addr11]] … [[addr11]]) [1: // ] #new_addr
1221    cases (split … 8 8 program_counter') #pc_bu #pc_bl normalize nodelta
1222    cases (split … 3 8 new_addr) #thr #eig normalize nodelta
1223    cases (split … 5 3 pc_bu) #fiv #thr' normalize nodelta * * * * #n'
1224    #_ #_ #program_counter_lt' #program_counter_lt_tps'
1225    %
1226    [1:
1227      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1228      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1229      >(le_to_leb_true … program_counter_lt') %
1230    |2:
1231      assumption
1232    ]
1233  |4:
1234    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1235    lapply(good_program_witness program_counter reachable_program_counter_witness)
1236      <FETCH normalize nodelta <instr normalize nodelta
1237    @(subaddressing_mode_elim … [[addr16]] … [[addr16]]) [1: // ] #new_addr
1238    * * * * #n'
1239    #_ #_ #program_counter_lt' #program_counter_lt_tps'     
1240    @(transitive_le
1241      total_program_size
1242      ((S program_size') + nat_of_bitvector … program_counter)
1243      (program_size' + nat_of_bitvector … program_counter') recursive_case)
1244    normalize in match (S program_size' + nat_of_bitvector … program_counter);
1245    >plus_n_Sm
1246    @monotonic_le_plus_r
1247    change with (
1248      nat_of_bitvector … program_counter <
1249        nat_of_bitvector … program_counter')
1250    assumption
1251  |5:
1252    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1253    lapply(good_program_witness program_counter reachable_program_counter_witness)
1254      <FETCH normalize nodelta <instr normalize nodelta
1255    @(subaddressing_mode_elim … [[addr16]] … [[addr16]]) [1: // ] #new_addr
1256    * * * * #n'
1257    #_ #_ #program_counter_lt' #program_counter_lt_tps'
1258    %
1259    [1:
1260      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1261      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1262      >(le_to_leb_true … program_counter_lt') %
1263    |2:
1264      assumption
1265    ]
1266  |6,8: (* JMP and MOVC *)
1267    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1268    lapply(good_program_witness program_counter reachable_program_counter_witness)
1269    <FETCH normalize nodelta <instr normalize nodelta
1270    try(<real_instruction_refl <instr normalize nodelta) *
1271    #pc_pc_lt_hyp' #pc_tps_lt_hyp'
1272    @(transitive_le
1273      total_program_size
1274      ((S program_size') + nat_of_bitvector … program_counter)
1275      (program_size' + nat_of_bitvector … program_counter') recursive_case)
1276    normalize in match (S program_size' + nat_of_bitvector … program_counter);
1277    >plus_n_Sm
1278    @monotonic_le_plus_r
1279    change with (
1280      nat_of_bitvector … program_counter <
1281        nat_of_bitvector … program_counter')
1282    assumption
1283  |7,9:
1284    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1285    lapply(good_program_witness program_counter reachable_program_counter_witness)
1286    <FETCH normalize nodelta <instr normalize nodelta *
1287    #program_counter_lt' #program_counter_lt_tps' %
1288    [1,3:
1289      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1290      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1291      >(le_to_leb_true … program_counter_lt') %
1292    |2,4:
1293      assumption
1294    ]
1295  |11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,
1296    55,57,59,61,63:
1297    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1298    lapply(good_program_witness program_counter reachable_program_counter_witness)
1299    <FETCH normalize nodelta <real_instruction_refl <instr normalize nodelta *
1300    #program_counter_lt' #program_counter_lt_tps' %
1301    try assumption
1302    [*:
1303      %{(S n)} whd in ⊢ (???%); <fetch_n_hyp normalize nodelta
1304      <FETCH normalize nodelta whd in match ltb; normalize nodelta
1305      >(le_to_leb_true … program_counter_lt') %
1306    ]
1307  |10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,
1308    54,56,58,60,62:
1309    cases reachable_program_counter_witness * #n #fetch_n_hyp #lt_hyp
1310    lapply(good_program_witness program_counter reachable_program_counter_witness)
1311    <FETCH normalize nodelta
1312    <real_instruction_refl <instr normalize nodelta *
1313    #pc_pc_lt_hyp' #pc_tps_lt_hyp'
1314    @(transitive_le
1315      total_program_size
1316      ((S program_size') + nat_of_bitvector … program_counter)
1317      (program_size' + nat_of_bitvector … program_counter') recursive_case)
1318    normalize in match (S program_size' + nat_of_bitvector … program_counter);
1319    >plus_n_Sm
1320    @monotonic_le_plus_r
1321    change with (
1322      nat_of_bitvector … program_counter <
1323        nat_of_bitvector … program_counter')
1324    assumption
1325  ]
1326qed.
1327
1328definition block_cost ≝
1329  λcode_memory: BitVectorTrie Byte 16.
1330  λprogram_counter: Word.
1331  λtotal_program_size: nat.
1332  λcost_labels: BitVectorTrie costlabel 16.
1333  λreachable_program_counter_witness: reachable_program_counter code_memory total_program_size program_counter.
1334  λgood_program_witness: good_program code_memory total_program_size.
1335    block_cost' code_memory program_counter total_program_size total_program_size cost_labels
1336      reachable_program_counter_witness good_program_witness true ?.
1337  @le_plus_n_r
1338qed.
1339
1340lemma fetch_program_counter_n_Sn:
1341  ∀instruction: instruction.
1342  ∀program_counter, program_counter': Word.
1343  ∀ticks, n: nat.
1344  ∀code_memory: BitVectorTrie Byte 16.
1345    Some … program_counter = fetch_program_counter_n n code_memory (zero 16) →
1346      〈instruction,program_counter',ticks〉 = fetch code_memory program_counter →
1347        nat_of_bitvector … program_counter < nat_of_bitvector … program_counter' →
1348          Some … program_counter' = fetch_program_counter_n (S n) code_memory (zero …).
1349  #instruction #program_counter #program_counter' #ticks #n #code_memory
1350  #fetch_program_counter_n_hyp #fetch_hyp #lt_hyp
1351  whd in match (fetch_program_counter_n (S n) code_memory (zero …));
1352  <fetch_program_counter_n_hyp normalize nodelta
1353  <fetch_hyp normalize nodelta
1354  change with (
1355    leb (S (nat_of_bitvector … program_counter)) (nat_of_bitvector … program_counter')
1356  ) in match (ltb (nat_of_bitvector … program_counter) (nat_of_bitvector … program_counter'));
1357  >(le_to_leb_true … lt_hyp) %
1358qed.
1359
1360let rec traverse_code_internal
1361  (code_memory: BitVectorTrie Byte 16) (cost_labels: BitVectorTrie costlabel 16)
1362    (program_counter: Word) (fixed_program_size: nat) (program_size: nat)
1363      (reachable_program_counter_witness:
1364          ∀lbl: costlabel.
1365          ∀program_counter: Word. Some … lbl = lookup_opt … program_counter cost_labels →
1366            reachable_program_counter code_memory fixed_program_size program_counter)
1367        (good_program_witness: good_program code_memory fixed_program_size)
1368        on program_size: identifier_map CostTag nat ≝
1369  match program_size with
1370  [ O ⇒ empty_map …
1371  | S program_size ⇒
1372    let 〈instruction, new_program_counter, ticks〉 as FETCH ≝ fetch … code_memory program_counter in
1373    let cost_mapping ≝ traverse_code_internal code_memory cost_labels new_program_counter fixed_program_size program_size ? good_program_witness in
1374    match lookup_opt … program_counter cost_labels return λx. x = lookup_opt … program_counter cost_labels → ? with
1375    [ None ⇒ λlookup_refl. cost_mapping
1376    | Some lbl ⇒ λlookup_refl.
1377      let cost ≝ block_cost code_memory program_counter fixed_program_size cost_labels ? good_program_witness in
1378        add … cost_mapping lbl cost
1379    ] (refl … (lookup_opt … program_counter cost_labels))
1380  ].
1381  [1:
1382    @(reachable_program_counter_witness lbl)
1383    assumption
1384  |2:
1385    assumption
1386  ]
1387qed.
1388
1389definition traverse_code ≝
1390  λcode_memory: BitVectorTrie Byte 16.
1391  λcost_labels: BitVectorTrie costlabel 16.
1392  λprogram_size: nat.
1393  λreachable_program_counter_witness:
1394          ∀lbl: costlabel.
1395          ∀program_counter: Word. Some … lbl = lookup_opt … program_counter cost_labels →
1396            reachable_program_counter code_memory program_size program_counter.
1397  λgood_program_witness: good_program code_memory program_size.
1398    traverse_code_internal code_memory cost_labels (zero …) program_size program_size reachable_program_counter_witness good_program_witness.
1399 
1400definition compute_costs ≝
1401  λprogram: list Byte.
1402  λcost_labels: BitVectorTrie costlabel 16.
1403  λreachable_program_witness.
1404  λgood_program_witness: good_program (load_code_memory program) (|program| + 1).
1405    let program_size ≝ |program| + 1 in
1406    let code_memory ≝ load_code_memory program in
1407      traverse_code code_memory cost_labels program_size reachable_program_witness ?.
1408  @good_program_witness
1409qed.
Note: See TracBrowser for help on using the repository browser.