-
Notifications
You must be signed in to change notification settings - Fork 40
/
x86.mm0
1651 lines (1446 loc) · 71.1 KB
/
x86.mm0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
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
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import "peano_hex.mm0";
def consBit (b: wff) (n: nat): nat = $ if b (b1 n) (b0 n) $;
def bit (n i: nat): nat = $ nat (i e. n) $;
theorem bitT (n i: nat): $ bool (bit n i) $;
def bitAnd (a b: nat): nat;
theorem bitAndEq (a b: nat): $ bitAnd a b == a i^i b $;
def bitOr (a b: nat): nat;
theorem bitOrEq (a b: nat): $ bitOr a b == a u. b $;
def bitDif (a b: nat): nat;
theorem bitDifEq (a b: nat): $ bitDif a b == a i^i Compl b $;
def bitXor (a b: nat): nat;
theorem bitXor_mem (a b i: nat): $ i e. bitXor a b <-> ~(i e. a <-> i e. b) $;
def d32: nat = $ 2 ^ 5 $; prefix d32: $32$ prec max;
def d64: nat = $ 2 ^ 6 $; prefix d64: $64$ prec max;
def d256: nat = $ 2 ^ 8 $; prefix d256: $256$ prec max;
def Bits (k: nat): nat = $ upto (2 ^ k) $;
def u8: nat = $ Bits 8 $;
def u16: nat = $ Bits 16 $;
def u32: nat = $ Bits 32 $;
def u64: nat = $ Bits 64 $;
--| Get the lower bits of a number
def chop (k n: nat): nat = $ n % 2 ^ k $;
theorem chopT (k n: nat): $ chop k n e. Bits k $;
def bitsMSB (k n: nat): wff = $ 0 < k /\ k - 1 e. n $;
--| Sign extend `(v: bitvec m)` to length `n`
def sExt (m n v: nat): nat = $ if (bitsMSB m v) (2 ^ n - 2 ^ m + v) v $;
def sExtq (n v: nat): nat = $ sExt n 64 v $;
theorem sExtT (m n v: nat): $ m <= n /\ v e. Bits m -> sExt m n v e. Bits n $;
theorem sExtqT (n v: nat): $ n <= 64 /\ v e. Bits n -> sExtq n v e. u64 $;
--| Write `a e. Bits m` to bits `k` thru `k+m-1` of `n`
def bitsUpdate (k m a n: nat): nat = $ bitDif n (shl (upto m) k) + shl a k $;
theorem bitsUpdateT (k m l a n: nat):
$ k + m <= l /\ a e. Bits m /\ n e. Bits l -> bitsUpdate k m a n e. Bits l $;
def bitsNot (k n: nat): nat = $ bitDif (upto k) n $;
theorem bitsNot_mem (k n i: nat): $ i e. bitsNot k n <-> i < k /\ ~i e. n $;
theorem bitsNotT (k n: nat): $ bitsNot k n e. Bits k $;
def bitsAdd (k a b: nat): nat = $ chop k (a + b) $;
theorem bitsAddT (k a b: nat): $ bitsAdd k a b e. Bits k $;
def bitsNeg (k n: nat): nat = $ bitsAdd k (bitsNot k n) 1 $;
theorem bitsNegT (k n: nat): $ bitsNeg k n e. Bits k $;
def bitsSub (k a b: nat): nat = $ bitsAdd k a (bitsNeg k b) $;
theorem bitsSubT (k a b: nat): $ bitsSub k a b e. Bits k $;
def bitsSar (k a b: nat): nat =
$ nat (bitsMSB k a) * (upto k - upto (k - b)) + shr a b $;
theorem bitsSarT (k a b: nat):
$ a e. Bits k /\ b <= k -> bitsSar k a b e. Bits k $;
def add64 (a b: nat): nat = $ bitsAdd 64 a b $; infixl add64: $+_64$ prec 65;
theorem add64T (a b: nat): $ a +_64 b e. u64 $;
def sub64 (a b: nat): nat = $ bitsSub 64 a b $; infixl sub64: $-_64$ prec 65;
theorem sub64T (a b: nat): $ a -_64 b e. u64 $;
--| Little endian encoding
def toBytes (k n: nat): nat;
theorem toBytes0 (n: nat): $ toBytes 0 n = 0 $;
theorem toBytesS (k n: nat):
$ toBytes (suc k) n = (n % 256) : toBytes k (n // 256) $;
theorem toBytesT (k n: nat): $ toBytes k n e. Array u8 k $;
def u16Bytes (n: nat): nat = $ toBytes 2 n $;
def u32Bytes (n: nat): nat = $ toBytes 4 n $;
def u64Bytes (n: nat): nat = $ toBytes 8 n $;
def Bitvec {.n: nat}: set = $ {n | snd n < 2 ^ fst n} $;
def bvSize (bs: nat): nat;
theorem bvSize0: $ bvSize 0 = 0 $;
theorem bvSizeS (k n bs: nat): $ bvSize ((k, n) : bs) = k + bvSize bs $;
def isBitvecs (bs k: nat): wff = $ bs e. List Bitvec /\ bvSize bs = k $;
def ofBits (n: nat): nat;
theorem ofBits0: $ ofBits 0 = 0 $;
theorem ofBitsS (k n bs: nat): $ ofBits ((k, n) : bs) = n + shl (ofBits bs) k $;
theorem ofBits0T: $ ofBits 0 e. Bits 0 $;
theorem ofBitsST (k n bs m: nat):
$ n e. Bits k /\ ofBits bs e. Bits m ->
ofBits ((k, n) : bs) e. Bits (k + m) $;
def splitBits (bs n: nat): wff = $ bs e. List Bitvec /\ ofBits bs = n $;
theorem splitBitsT (bs n k: nat):
$ isBitvecs bs k /\ splitBits bs n -> n e. Bits k $;
----------------------------------------
-- x86-64 machine code decoding
----------------------------------------
def Regs: nat = $ Bits 4 $;
def RAX: nat = $ 0 $; theorem RAX_T: $ RAX e. Regs $;
def RCX: nat = $ 1 $; theorem RCX_T: $ RCX e. Regs $;
def RDX: nat = $ 2 $; theorem RDX_T: $ RDX e. Regs $;
def RBX: nat = $ 3 $; theorem RBX_T: $ RBX e. Regs $;
def RSP: nat = $ 4 $; theorem RSP_T: $ RSP e. Regs $;
def RBP: nat = $ 5 $; theorem RBP_T: $ RBP e. Regs $;
def RSI: nat = $ 6 $; theorem RSI_T: $ RSI e. Regs $;
def RDI: nat = $ 7 $; theorem RDI_T: $ RDI e. Regs $;
def REX: set = $ Option (Bits 4) $;
def REX_val (r: nat): nat = $ r - 1 $;
def REX_W (r: nat): nat = $ bit (REX_val r) 3 $;
def REX_R (r: nat): nat = $ bit (REX_val r) 2 $;
def REX_X (r: nat): nat = $ bit (REX_val r) 1 $;
def REX_B (r: nat): nat = $ bit (REX_val r) 0 $;
theorem REX_valT (r: nat): $ r e. REX -> REX_val r e. Bits 4 $;
theorem REX_W_T (r: nat): $ bool (REX_W r) $;
theorem REX_R_T (r: nat): $ bool (REX_R r) $;
theorem REX_X_T (r: nat): $ bool (REX_X r) $;
theorem REX_B_T (r: nat): $ bool (REX_B r) $;
def rex_reg (b r: nat): nat = $ shl b 3 + r $;
theorem rex_regT (b r: nat): $ bool b /\ r e. Bits 3 -> rex_reg b r e. Regs $;
def Base: set = $ Option (Option Regs) $;
def base_RIP: nat = $ suc 0 $;
def base_reg (r: nat): nat = $ suc (suc r) $;
theorem base0T: $ 0 e. Base $;
theorem base_RIP_T: $ base_RIP e. Base $;
theorem base_regT (r: nat): $ base_reg r e. Base <-> r e. Regs $;
def ScaleIndex: set = $ Xp (Bits 2) Regs $;
def RM: set = $ Sum Regs (Xp (Option ScaleIndex) (Xp Base u64)) $;
def RM_reg (r: nat): nat = $ b0 r $;
def RM_mem (si base q: nat): nat = $ b1 (si, base, q) $;
theorem RM_regT (r: nat): $ RM_reg r e. RM <-> r e. Regs $;
theorem RM_memT (si base q: nat):
$ RM_mem si base q e. RM <->
si e. Option ScaleIndex /\ base e. Base /\ q e. u64 $;
def RM_isMem (rm: nat): wff = $ odd rm $;
def readDisplacement (mod q l .b .w: nat): wff =
$ mod = 0 /\ q = 0 /\ l = 0 \/
E. b (b e. u8 /\ mod = 1 /\ q = sExtq 8 b /\ l = b : 0) \/
E. w (w e. u32 /\ mod = 2 /\ q = sExtq 32 w /\ l = u32Bytes w) $;
theorem readDisplacementT (mod q l: nat):
$ readDisplacement mod q l ->
mod e. Bits 2 /\ mod != 3 /\ q e. u64 /\ l e. List u8 $;
def readSIBDisplacement (mod bbase q base l .w: nat): wff =
$ ifp (bbase = RBP /\ mod = 0)
(E. w (w e. u32 /\ q = sExtq 32 w /\ base = 0 /\ l = u32Bytes w))
(readDisplacement mod q l /\ base = base_reg bbase) $;
theorem readSIBDisplacementT (mod bbase q base l: nat):
$ bbase e. Regs /\ readSIBDisplacement mod bbase q base l ->
mod e. Bits 2 /\ mod != 3 /\ q e. u64 /\ base e. Base /\ l e. List u8 $;
def readSIB (rex mod rm l .b .l2 .bs .ix .sc .disp .bbase .index: nat): wff =
$ E. b E. l2 E. bs E. ix E. sc E. disp E. bbase E. index (
splitBits ((3, bs) : (3, ix) : (2, sc) : 0) b /\
index = rex_reg (REX_X rex) ix /\
readSIBDisplacement mod (rex_reg (REX_B rex) bs) disp bbase l2 /\
rm = RM_mem (if (index = RSP) 0 (suc (sc, index))) bbase disp /\
l = b : l2) $;
theorem readSIB_T (rex mod rm l: nat):
$ readSIB rex mod rm l ->
mod e. Bits 2 /\ mod != 3 /\ rm e. RM /\ l e. List u8 $;
def readModRM (rex rn rm l .b .rm2 .opc .mod .i .l2 .disp: nat): wff =
$ E. b E. rm2 E. opc E. mod (
splitBits ((3, rm2) : (3, opc) : (2, mod) : 0) b /\
rn = rex_reg (REX_R rex) opc /\
ifp (mod = 3)
(rm = RM_reg (rex_reg (REX_B rex) rm2) /\
l = b : 0)
(ifp (rm2 = 5 /\ mod = 0)
(E. i (i e. u32 /\
rm = RM_mem 0 base_RIP (sExtq 32 i) /\
l = b : u32Bytes i))
(E. l2 (l = b : l2 /\
ifp (rm2 = 4) (readSIB rex mod rm l2)
(E. disp (readDisplacement mod disp l2 /\
rm = RM_mem 0 (base_reg (rex_reg (REX_B rex) rm2)) disp)))))) $;
theorem readModRM_T (rex rn rm l: nat):
$ readModRM rex rn rm l -> rn e. Regs /\ rm e. RM /\ l e. List u8 $;
def readOpcodeModRM (rex v rm l .rn: nat): wff =
$ E. rn (readModRM rex rn rm l /\ v = chop 3 rn) $;
theorem readOpcodeModRM_T (rex v rm l: nat):
$ readOpcodeModRM rex v rm l -> v e. Bits 3 /\ rm e. RM /\ l e. List u8 $;
def readPrefixes (rex l .b .rex2: nat): wff =
$ rex = 0 /\ l = 0 \/ E. b E. rex2 (
splitBits ((4, rex2) : (4, 4) : 0) b /\
rex = suc rex2 /\ l = b : 0) $;
theorem readPrefixesT (rex l: nat):
$ readPrefixes rex l -> rex e. REX /\ l e. List u8 $;
def readImmN (k q l .w: nat): wff =
$ 8 || k /\ E. w (w e. Bits k /\ q = sExtq k w /\ l = toBytes (k // 8) w) $;
theorem readImmN_T (k q l: nat):
$ k <= 64 /\ readImmN k q l -> q e. u64 /\ l e. List u8 $;
def WSize (.n: nat): set = $ Xp (8 ; 16 ; 32 ; sn 64) Bool i^i {n | fst n = 8 \/ snd n = 0} $;
def wsizeBits (sz: nat): nat = $ fst sz $;
def wsizeBytes (sz: nat): nat = $ wsizeBits sz // 8 $;
def wSz8 (have_rex: wff): nat = $ 8, nat have_rex $;
def wSz16: nat = $ 16, 0 $;
def wSz32: nat = $ 32, 0 $;
def wSz64: nat = $ 64, 0 $;
def readFullImm (sz q l: nat): wff =
$ readImmN (wsizeBits sz) q l $;
theorem readFullImmT (sz q l: nat):
$ sz e. WSize /\ readFullImm sz q l -> q e. u64 /\ l e. List u8 $;
def readImm (sz q l: nat): wff =
$ readImmN (min (wsizeBits sz) 32) q l $;
theorem readImmT (sz q l: nat):
$ sz e. WSize /\ readImm sz q l -> q e. u64 /\ l e. List u8 $;
def opSize (have_rex: wff) (w v: nat): nat =
$ if (true v) (if (true w) wSz64 wSz32) (wSz8 have_rex) $;
theorem opSizeT (have_rex: wff) (w v: nat): $ opSize have_rex w v e. WSize $;
def opSizeW (rex v: nat): nat = $ opSize (rex != 0) (REX_W rex) v $;
theorem opSizeW_T (rex v: nat): $ opSizeW rex v e. WSize $;
def DestSrc: set = $ Sum (Xp RM (Sum u64 Regs)) (Xp Regs RM) $;
def Rm_i (rm i: nat): nat = $ b0 (rm, b0 i) $;
def Rm_r (rm r: nat): nat = $ b0 (rm, b1 r) $;
def R_rm (r rm: nat): nat = $ b1 (r, rm) $;
theorem Rm_iT (rm i: nat): $ Rm_i rm i e. DestSrc <-> rm e. RM /\ i e. u64 $;
theorem Rm_rT (rm r: nat): $ Rm_r rm r e. DestSrc <-> rm e. RM /\ r e. Regs $;
theorem R_rmT (r rm: nat): $ R_rm r rm e. DestSrc <-> r e. Regs /\ rm e. RM $;
def ImmRM: set = $ Sum RM u64 $;
def immRM_rm (rm: nat): nat = $ b0 rm $;
def immRM_imm (i: nat): nat = $ b1 i $;
theorem immRM_rmT (rm: nat): $ immRM_rm rm e. ImmRM <-> rm e. RM $;
theorem immRM_immT (i: nat): $ immRM_imm i e. ImmRM <-> i e. u64 $;
def Unop: nat = $ upto 4 $;
def unopInc: nat = $ 0 $;
def unopDec: nat = $ 1 $;
def unopNot: nat = $ 2 $;
def unopNeg: nat = $ 3 $;
def Binop: nat = $ Bits 4 $;
def binopAdd: nat = $ 0 $;
def binopOr: nat = $ 1 $;
def binopAdc: nat = $ 2 $;
def binopSbb: nat = $ 3 $;
def binopAnd: nat = $ 4 $;
def binopSub: nat = $ 5 $;
def binopXor: nat = $ 6 $;
def binopCmp: nat = $ 7 $;
def binopRol: nat = $ 8 $;
def binopRor: nat = $ 9 $;
def binopRcl: nat = $ 10 $;
def binopRcr: nat = $ 11 $;
def binopShl: nat = $ 12 $;
def binopShr: nat = $ 13 $;
def binopTst: nat = $ 14 $;
def binopSar: nat = $ 15 $;
def BCond: nat = $ Bits 3 $;
def bcondO: nat = $ 0 $;
def bcondB: nat = $ 1 $;
def bcondE: nat = $ 2 $;
def bcondNA: nat = $ 3 $;
def bcondS: nat = $ 4 $;
def bcondL: nat = $ 6 $;
def bcondNG: nat = $ 7 $;
def Cond: set = $ Option (Bits 4) $;
def condAlways: nat = $ 0 $;
def condPos (c: nat): nat = $ suc (b0 c) $;
def condNeg (c: nat): nat = $ suc (b1 c) $;
theorem condAlwaysT: $ condAlways e. Cond $;
theorem condPosT (c: nat): $ c e. BCond <-> condPos c e. Cond $;
theorem condNegT (c: nat): $ c e. BCond <-> condNeg c e. Cond $;
def XASTArith: set =
$ Sum (Sum (Xp Unop (Xp WSize RM)) (Xp Binop (Xp WSize DestSrc)))
(Sum (Xp Bool (Xp WSize RM)) (Xp WSize (Option DestSrc))) $;
def xastUnop (unop sz rm: nat): nat = $ b0 (b0 (b0 (b0 (unop, sz, rm)))) $;
def xastBinop (binop sz ds: nat): nat = $ b0 (b0 (b0 (b1 (binop, sz, ds)))) $;
def xastMul (sz rm: nat): nat = $ b0 (b0 (b1 (b0 (0, sz, rm)))) $;
def xastDiv (sz rm: nat): nat = $ b0 (b0 (b1 (b0 (1, sz, rm)))) $;
def xastCDX (sz: nat): nat = $ b0 (b0 (b1 (b1 (sz, 0)))) $;
def xastLea (sz ds: nat): nat = $ b0 (b0 (b1 (b1 (sz, suc ds)))) $;
def XASTData: set =
$ Sum (Xp WSize (Sum (Xp Bool (Xp DestSrc WSize)) (Xp (upto 3) (Xp RM Regs))))
(Xp Cond (Sum (Xp WSize DestSrc) (Xp Bool RM))) $;
def xastMovX (b sz ds sz2: nat): nat = $ b0 (b1 (b0 (sz, b0 (b, ds, sz2)))) $;
def xastXchg (sz rm rn: nat): nat = $ b0 (b1 (b0 (sz, b1 (0, rm, rn)))) $;
def xastCmpXchg (sz rm rn: nat): nat = $ b0 (b1 (b0 (sz, b1 (1, rm, rn)))) $;
def xastXadd (sz rm rn: nat): nat = $ b0 (b1 (b0 (sz, b1 (2, rm, rn)))) $;
def xastCMov (c sz ds: nat): nat = $ b0 (b1 (b1 (c, b0 (sz, ds)))) $;
def xastSetCC (c b ds: nat): nat = $ b0 (b1 (b1 (c, b1 (b, ds)))) $;
def xastMov (sz ds: nat): nat = $ xastCMov condAlways sz ds $;
def xastMovZX (sz ds sz2: nat): nat = $ xastMovX 0 sz ds sz2 $;
def xastMovSX (sz ds sz2: nat): nat = $ xastMovX 1 sz ds sz2 $;
def XASTFlow: set =
$ Sum (Sum (Sum RM (Xp Cond u64)) (Sum ImmRM u64)) (Option (Sum ImmRM RM)) $;
def xastJump (rm: nat): nat = $ b1 (b0 (b0 (b0 (b0 rm)))) $;
def xastJCC (c q: nat): nat = $ b1 (b0 (b0 (b0 (b1 (c, q))))) $;
def xastCall (irm: nat): nat = $ b1 (b0 (b0 (b1 (b0 irm)))) $;
def xastRet (q: nat): nat = $ b1 (b0 (b0 (b1 (b1 q)))) $;
def xastLeave: nat = $ b1 (b0 (b1 0)) $;
def xastPush (irm: nat): nat = $ b1 (b0 (b1 (suc (b0 irm)))) $;
def xastPop (rm: nat): nat = $ b1 (b0 (b1 (suc (b1 rm)))) $;
def XASTMisc: set = $ upto 5 $;
def xastCMC: nat = $ b1 (b1 0) $;
def xastCLC: nat = $ b1 (b1 1) $;
def xastSTC: nat = $ b1 (b1 2) $;
def xastUD2: nat = $ b1 (b1 3) $;
def xastSysCall: nat = $ b1 (b1 4) $;
def XAST: set = $ Sum (Sum XASTArith XASTData) (Sum XASTFlow XASTMisc) $;
-- some typechecking sanity checks
theorem xastUnopT (unop sz rm: nat):
$ xastUnop unop sz rm e. XAST <-> unop e. Unop /\ sz e. WSize /\ rm e. RM $;
theorem xastBinopT (bop sz ds: nat):
$ xastBinop bop sz ds e. XAST <-> bop e. Binop /\ sz e. WSize /\ ds e. DestSrc $;
theorem xastMulT (sz rm: nat):
$ xastMul sz rm e. XAST <-> sz e. WSize /\ rm e. RM $;
theorem xastDivT (sz rm: nat):
$ xastDiv sz rm e. XAST <-> sz e. WSize /\ rm e. RM $;
theorem xastCDX_T (sz: nat):
$ xastCDX sz e. XAST <-> sz e. WSize $;
theorem xastLeaT (sz ds: nat):
$ xastLea sz ds e. XAST <-> sz e. WSize /\ ds e. DestSrc $;
theorem xastMovX_T (b sz ds sz2: nat):
$ xastMovX b sz ds sz2 e. XAST <->
bool b /\ sz e. WSize /\ ds e. DestSrc /\ sz2 e. WSize $;
theorem xastXchgT (sz rm rn: nat):
$ xastXchg sz rm rn e. XAST <-> sz e. WSize /\ rm e. RM /\ rn e. Regs $;
theorem xastCmpXchgT (sz rm rn: nat):
$ xastCmpXchg sz rm rn e. XAST <-> sz e. WSize /\ rm e. RM /\ rn e. Regs $;
theorem xastXaddT (sz rm rn: nat):
$ xastXadd sz rm rn e. XAST <-> sz e. WSize /\ rm e. RM /\ rn e. Regs $;
theorem xastCMovT (c sz ds: nat):
$ xastCMov c sz ds e. XAST <-> c e. Cond /\ sz e. WSize /\ ds e. DestSrc $;
theorem xastSetCC_T (c b rm: nat):
$ xastSetCC c b rm e. XAST <-> c e. Cond /\ bool b /\ rm e. RM $;
theorem xastMovZX_T (sz ds sz2: nat):
$ xastMovZX sz ds sz2 e. XAST <-> sz e. WSize /\ ds e. DestSrc /\ sz2 e. WSize $;
theorem xastMovSX_T (sz ds sz2: nat):
$ xastMovSX sz ds sz2 e. XAST <-> sz e. WSize /\ ds e. DestSrc /\ sz2 e. WSize $;
theorem xastMovT (sz ds: nat):
$ xastMov sz ds e. XAST <-> sz e. WSize /\ ds e. DestSrc $;
theorem xastJumpT (rm: nat): $ xastJump rm e. XAST <-> rm e. RM $;
theorem xastJCC_T (c q: nat): $ xastJCC c q e. XAST <-> c e. Cond /\ q e. u64 $;
theorem xastCallT (irm: nat): $ xastCall irm e. XAST <-> irm e. ImmRM $;
theorem xastRetT (q: nat): $ xastRet q e. XAST <-> q e. u64 $;
theorem xastLeaveT: $ xastLeave e. XAST $;
theorem xastPushT (irm: nat): $ xastPush irm e. XAST <-> irm e. ImmRM $;
theorem xastPopT (rm: nat): $ xastPop rm e. XAST <-> rm e. RM $;
theorem xastCMC_T: $ xastCMC e. XAST $;
theorem xastCLC_T: $ xastCLC e. XAST $;
theorem xastSTC_T: $ xastSTC e. XAST $;
theorem xastUD2T: $ xastUD2 e. XAST $;
theorem xastSysCallT: $ xastSysCall e. XAST $;
def decodeTwoCMov (rex ast b l .c .reg .r: nat): wff =
$ E. c E. reg E. r (splitBits ((4, c) : (4, 4) : 0) b /\
readModRM rex reg r l /\
ast = xastCMov (suc c) (opSize T. (REX_W rex) 1) (R_rm reg r)) $;
theorem decodeTwoCMovT (rex ast b l: nat):
$ decodeTwoCMov rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoJCC (_rex ast b l .c .imm: nat): wff =
$ E. c E. imm (splitBits ((4, c) : (4, 8) : 0) b /\
readImmN 32 imm l /\
ast = xastJCC (suc c) imm) $;
theorem decodeTwoJCC_T (rex ast b l: nat):
$ decodeTwoJCC rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoSetCC (rex ast b l .c .reg .r: nat): wff =
$ E. c E. reg E. r (splitBits ((4, c) : (4, 9) : 0) b /\
readModRM rex reg r l /\
ast = xastSetCC (suc c) (nat (rex != 0)) r) $;
theorem decodeTwoSetCC_T (rex ast b l: nat):
$ decodeTwoSetCC rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoCmpXchg (rex ast b l .v .reg .r: nat): wff =
$ E. v E. reg E. r (splitBits ((1, v) : (3, 0) : (4, 11) : 0) b /\
readModRM rex reg r l /\
ast = xastCmpXchg (opSizeW rex v) r reg) $;
theorem decodeTwoCmpXchgT (rex ast b l: nat):
$ decodeTwoCmpXchg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoMovX (rex ast b l .v .s .reg .r: nat): wff =
$ E. v E. s E. reg E. r (
splitBits ((1, v) : (2, 3) : (1, s) : (4, 11) : 0) b /\
readModRM rex reg r l /\
ast = xastMovX s (if (bool v) wSz16 (wSz8 (rex != 0)))
(R_rm reg r) (opSizeW rex 1)) $;
theorem decodeTwoMovX_T (rex ast b l: nat):
$ decodeTwoMovX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoXadd (rex ast b l .v .reg .r: nat): wff =
$ E. v E. reg E. r (
splitBits ((1, v) : (3, 0) : (4, 12) : 0) b /\
readModRM rex reg r l /\
ast = xastXadd (opSizeW rex v) r reg) $;
theorem decodeTwoXaddT (rex ast b l: nat):
$ decodeTwoXadd rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoUD2 (_rex ast b l: nat): wff =
$ b = ch x0 xb /\ l = 0 /\ ast = xastUD2 $;
theorem decodeTwoUD2T (rex ast b l: nat):
$ decodeTwoUD2 rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoSysCall (_rex ast b l: nat): wff =
$ b = ch x0 x5 /\ l = 0 /\ ast = xastSysCall $;
theorem decodeTwoSysCallT (rex ast b l: nat):
$ decodeTwoSysCall rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwoAux (rex ast b l: nat): wff =
$ decodeTwoCMov rex ast b l \/ decodeTwoJCC rex ast b l \/
decodeTwoSetCC rex ast b l \/ decodeTwoCmpXchg rex ast b l \/
decodeTwoMovX rex ast b l \/ decodeTwoXadd rex ast b l \/
decodeTwoUD2 rex ast b l \/ decodeTwoSysCall rex ast b l $;
theorem decodeTwoAuxT (rex ast b l: nat):
$ decodeTwoAux rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTwo (rex ast b l .b2 .l2: nat): wff =
$ b = ch x0 xf /\ E. b2 E. l2 (l = b2 : l2 /\ decodeTwoAux rex ast b2 l2) $;
theorem decodeTwoT (rex ast b l: nat):
$ decodeTwo rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopReg (rex ast b l .v .d .opc .reg .r: nat): wff =
$ E. v E. d E. opc E. reg E. r (
splitBits ((1, v) : (1, d) : (1, 0) : (3, opc) : (2, 0) : 0) b /\
readModRM rex reg r l /\
ast = xastBinop opc (opSizeW rex v)
(if (true d) (R_rm reg r) (Rm_r r reg))) $;
theorem decodeBinopRegT (rex ast b l: nat):
$ decodeBinopReg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopRAX (rex ast b l .v .opc .imm: nat): wff =
$ E. v E. opc E. imm (
splitBits ((1, v) : (2, 2) : (3, opc) : (2, 0) : 0) b /\
readImm (opSizeW rex v) imm l /\
ast = xastBinop opc (opSizeW rex v) (Rm_i (RM_reg RAX) imm)) $;
theorem decodeBinopRAX_T (rex ast b l: nat):
$ decodeBinopRAX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopImm (rex ast b l .v .opc .r .l1 .imm .l2: nat): wff =
$ E. v E. opc E. r E. l1 E. imm E. l2 (l = l1 ++ l2 /\
splitBits ((1, v) : (3, 0) : (4, 8) : 0) b /\
readOpcodeModRM rex opc r l1 /\
readImm (opSizeW rex v) imm l2 /\
ast = xastBinop opc (opSizeW rex v) (Rm_i r imm)) $;
theorem decodeBinopImmT (rex ast b l: nat):
$ decodeBinopImm rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopImm8 (rex ast b l .opc .r .l1 .imm .l2: nat): wff =
$ E. opc E. r E. imm E. l1 E. l2 (l = l1 ++ l2 /\ b = ch x8 x3 /\
readOpcodeModRM rex opc r l1 /\
readImmN 8 imm l2 /\
ast = xastBinop opc (opSizeW rex 1) (Rm_i r imm)) $;
theorem decodeBinopImm8T (rex ast b l: nat):
$ decodeBinopImm8 rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopHi (rex ast b l .v .opc .r .imm .l1 .l2: nat): wff =
$ E. v E. opc E. r E. imm E. l1 E. l2 (l = l1 ++ l2 /\
splitBits ((1, v) : (3, 0) : (4, 12) : 0) b /\
readOpcodeModRM rex opc r l1 /\ opc != 6 /\
readImmN 8 imm l2 /\
ast = xastBinop (rex_reg 1 opc) (opSizeW rex v) (Rm_i r imm)) $;
theorem decodeBinopHiT (rex ast b l: nat):
$ decodeBinopHi rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinopHiReg (rex ast b l .v .x .opc .r: nat): wff =
$ E. v E. x E. opc E. r (
splitBits ((1, v) : (1, x) : (2, 0) : (4, 13) : 0) b /\
readOpcodeModRM rex opc r l /\ opc != 6 /\
ast = xastBinop (rex_reg 1 opc) (opSizeW rex v)
(if (true x) (Rm_r r RCX) (Rm_i r 1))) $;
theorem decodeBinopHiRegT (rex ast b l: nat):
$ decodeBinopHiReg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeBinop (rex ast b l: nat): wff =
$ decodeBinopReg rex ast b l \/ decodeBinopRAX rex ast b l \/
decodeBinopImm rex ast b l \/ decodeBinopImm8 rex ast b l \/
decodeBinopHi rex ast b l \/ decodeBinopHiReg rex ast b l $;
theorem decodeBinopT (rex ast b l: nat):
$ decodeBinop rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMovSX (rex ast b l .reg .r: nat): wff =
$ E. reg E. r (b = ch x6 x3 /\
readModRM rex reg r l /\ ast = xastMovSX wSz32 (R_rm reg r) (opSizeW rex 1)) $;
theorem decodeMovSX_T (rex ast b l: nat):
$ decodeMovSX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMovReg (rex ast b l .v .d .reg .r: nat): wff =
$ E. v E. d E. reg E. r (
splitBits ((1, v) : (1, d) : (2, 2) : (4, 8) : 0) b /\
readModRM rex reg r l /\
ast = xastMov (opSizeW rex v) (if (true d) (R_rm reg r) (Rm_r r reg))) $;
theorem decodeMovRegT (rex ast b l: nat):
$ decodeMovReg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMov64 (rex ast b l .r .v .imm: nat): wff =
$ E. r E. v E. imm (
splitBits ((3, r) : (1, v) : (4, 11) : 0) b /\
readFullImm (opSizeW rex v) imm l /\
ast = xastMov (opSizeW rex v) (Rm_i (RM_reg (rex_reg (REX_B rex) r)) imm)) $;
theorem decodeMov64T (rex ast b l: nat):
$ decodeMov64 rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMovImm (rex ast b l .v .opc .r .imm .l1 .l2: nat): wff =
$ E. v E. r E. imm E. l1 E. l2 (l = l1 ++ l2 /\
splitBits ((1, v) : (3, 3) : (4, 12) : 0) b /\
readOpcodeModRM rex 0 r l1 /\
readImm (opSizeW rex v) imm l2 /\
ast = xastMov (opSizeW rex v) (Rm_i r imm)) $;
theorem decodeMovImmT (rex ast b l: nat):
$ decodeMovImm rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMov (rex ast b l: nat): wff =
$ decodeMovSX rex ast b l \/ decodeMovReg rex ast b l \/
decodeMov64 rex ast b l \/ decodeMovImm rex ast b l $;
theorem decodeMovT (rex ast b l: nat):
$ decodeMov rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodePushImm (_rex ast b l .x .imm .r: nat): wff =
$ E. x E. imm (
splitBits ((1, 0) : (1, x) : (2, 2) : (4, 6) : 0) b /\
readImmN (if (true x) 8 32) imm l /\
ast = xastPush (immRM_imm imm)) $;
theorem decodePushImmT (rex ast b l: nat):
$ decodePushImm rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodePushReg (rex ast b l .x .imm .r: nat): wff =
$ l = 0 /\ E. r (
splitBits ((3, r) : (1, 0) : (4, 5) : 0) b /\
ast = xastPush (immRM_rm (RM_reg (rex_reg (REX_B rex) r)))) $;
theorem decodePushRegT (rex ast b l: nat):
$ decodePushReg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodePopReg (rex ast b l .r: nat): wff =
$ l = 0 /\ E. r (
splitBits ((3, r) : (1, 1) : (4, 5) : 0) b /\
ast = xastPop (RM_reg (rex_reg (REX_B rex) r))) $;
theorem decodePopRegT (rex ast b l: nat):
$ decodePopReg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodePop0 (rex ast b l .r: nat): wff =
$ E. r (b = ch x8 xf /\ readOpcodeModRM rex 0 r l /\ ast = xastPop r) $;
theorem decodePop0T (rex ast b l: nat):
$ decodePop0 rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeStack (rex ast b l .r: nat): wff =
$ decodePushImm rex ast b l \/ decodePushReg rex ast b l \/
decodePopReg rex ast b l \/ decodePop0 rex ast b l $;
theorem decodeStackT (rex ast b l: nat):
$ decodeStack rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeJump (_rex ast b l .x .imm: nat): wff =
$ E. x E. imm (
splitBits ((1, 1) : (1, x) : (2, 2) : (4, 14) : 0) b /\
readImmN (if (true x) 8 32) imm l /\
ast = xastJCC condAlways imm) $;
theorem decodeJumpT (rex ast b l: nat):
$ decodeJump rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeJCC8 (_rex ast b l .c .imm: nat): wff =
$ E. c E. imm (splitBits ((4, c) : (4, 7) : 0) b /\
readImmN 8 imm l /\ ast = xastJCC (suc c) imm) $;
theorem decodeJCC8T (rex ast b l: nat):
$ decodeJCC8 rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeCall (_rex ast b l .imm: nat): wff =
$ E. imm (b = ch xe x8 /\
readImmN 32 imm l /\ ast = xastCall (immRM_imm imm)) $;
theorem decodeCallT (rex ast b l: nat):
$ decodeCall rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeRet (_rex ast b l .v .imm: nat): wff =
$ E. v E. imm (
splitBits ((1, v) : (3, 1) : (4, 12) : 0) b /\
ifp (true v) (imm = 0 /\ l = 0) (readImmN 16 imm l) /\
ast = xastRet imm) $;
theorem decodeRetT (rex ast b l: nat):
$ decodeRet rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeLeave (_rex ast b l: nat): wff =
$ b = ch xc x9 /\ l = 0 /\ ast = xastLeave $;
theorem decodeLeaveT (rex ast b l: nat):
$ decodeLeave rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeFlow (rex ast b l: nat): wff =
$ decodeJump rex ast b l \/ decodeJCC8 rex ast b l \/
decodeCall rex ast b l \/ decodeRet rex ast b l \/ decodeLeave rex ast b l $;
theorem decodeFlowT (rex ast b l: nat):
$ decodeFlow rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeXchg (rex ast b l .v .reg .r: nat): wff =
$ E. v E. reg E. r (
splitBits ((1, v) : (3, 3) : (4, 8) : 0) b /\
readModRM rex reg r l /\
ast = xastXchg (opSizeW rex v) r reg) $;
theorem decodeXchgT (rex ast b l: nat):
$ decodeXchg rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeXchgRAX (rex ast b l .v .reg .r: nat): wff =
$ l = 0 /\ E. r (
splitBits ((3, r) : (1, 0) : (4, 9) : 0) b /\
ast = xastXchg (opSizeW rex 1) (RM_reg RAX) (rex_reg (REX_B rex) r)) $;
theorem decodeXchgRAX_T (rex ast b l: nat):
$ decodeXchgRAX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeCDX (rex ast b l .reg .r: nat): wff =
$ E. reg E. r (b = ch x9 x9 /\ l = 0 /\ ast = xastCDX (opSize T. (REX_W rex) 1)) $;
theorem decodeCDX_T (rex ast b l: nat):
$ decodeCDX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeLea (rex ast b l .reg .r: nat): wff =
$ E. reg E. r (b = ch x8 xd /\
readModRM rex reg r l /\ RM_isMem r /\
ast = xastLea (opSize T. (REX_W rex) 1) (R_rm reg r)) $;
theorem decodeLeaT (rex ast b l: nat):
$ decodeLea rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTest (rex ast b l .v .reg .r: nat): wff =
$ E. v E. reg E. r (
splitBits ((1, v) : (3, 2) : (4, 8) : 0) b /\
readModRM rex reg r l /\
ast = xastBinop binopTst (opSizeW rex v) (Rm_r r reg)) $;
theorem decodeTestT (rex ast b l: nat):
$ decodeTest rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeTestRAX (rex ast b l .v .imm .sz: nat): wff =
$ E. v E. imm E. sz (
splitBits ((1, v) : (3, 4) : (4, 10) : 0) b /\
sz = opSize T. (REX_W rex) v /\
readImm sz imm l /\
ast = xastBinop binopTst sz (Rm_i (RM_reg RAX) imm)) $;
theorem decodeTestRAX_T (rex ast b l: nat):
$ decodeTestRAX rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeCMC (_rex ast b l: nat): wff = $ b = ch xf x5 /\ l = 0 /\ ast = xastCMC $;
theorem decodeCMC_T (rex ast b l: nat): $ decodeCMC rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeCLC (_rex ast b l: nat): wff = $ b = ch xf x8 /\ l = 0 /\ ast = xastCLC $;
theorem decodeCLC_T (rex ast b l: nat): $ decodeCLC rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeSTC (_rex ast b l: nat): wff = $ b = ch xf x9 /\ l = 0 /\ ast = xastSTC $;
theorem decodeSTC_T (rex ast b l: nat): $ decodeSTC rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeFlag (rex ast b l: nat): wff =
$ decodeCMC rex ast b l \/ decodeCLC rex ast b l \/ decodeSTC rex ast b l $;
theorem decodeFlagT (rex ast b l: nat):
$ decodeFlag rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeMisc (rex ast b l: nat): wff =
$ decodeXchg rex ast b l \/ decodeXchgRAX rex ast b l \/
decodeTest rex ast b l \/ decodeTestRAX rex ast b l \/
decodeCDX rex ast b l \/ decodeLea rex ast b l \/ decodeFlag rex ast b l $;
theorem decodeMiscT (rex ast b l: nat):
$ decodeMisc rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeHiAux (v sz r hi n ast l .imm: nat): wff =
$ ifp (true hi)
(l = 0 /\ (
n = 0 /\ ast = xastUnop unopInc sz r \/
n = 1 /\ ast = xastUnop unopDec sz r \/
true v /\ (
n = 2 /\ ast = xastCall (immRM_rm r) \/
n = 4 /\ ast = xastJump r \/
n = 6 /\ ast = xastPush (immRM_rm r))))
(n = 0 /\ E. imm (readImm sz imm l /\
ast = xastBinop binopTst sz (Rm_i r imm)) \/
l = 0 /\ (
n = 2 /\ ast = xastUnop unopNot sz r \/
n = 3 /\ ast = xastUnop unopNeg sz r \/
n = 4 /\ ast = xastMul sz r \/
n = 6 /\ ast = xastDiv sz r)) $;
theorem decodeHiAuxT (v sz r hi n ast l: nat):
$ sz e. WSize /\ r e. RM /\
decodeHiAux v sz r hi n ast l -> ast e. XAST /\ l e. List u8 $;
def decodeHi (rex ast b l .v .x .opc .r .l1 .l2: nat): wff =
$ E. v E. x E. opc E. r E. l1 E. l2 (l = l1 ++ l2 /\
splitBits ((1, v) : (2, 3) : (1, x) : (4, 15) : 0) b /\
readOpcodeModRM rex opc r l1 /\
decodeHiAux v (opSizeW rex v) r x opc ast l2) $;
theorem decodeHiT (rex ast b l: nat):
$ decodeHi rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decodeAux (rex ast b l: nat): wff =
$ decodeBinop rex ast b l \/ decodeMov rex ast b l \/
decodeStack rex ast b l \/ decodeFlow rex ast b l \/
decodeMisc rex ast b l \/ decodeHi rex ast b l \/ decodeTwo rex ast b l $;
theorem decodeAuxT (rex ast b l: nat):
$ decodeAux rex ast b l -> ast e. XAST /\ b e. u8 /\ l e. List u8 $;
def decode (ast l .rex .l1 .opc .l2: nat): wff =
$ E. rex E. l1 E. opc E. l2 (l = l1 ++ opc : l2 /\
readPrefixes rex l1 /\ decodeAux rex ast opc l2) /\
len l <= 15 $;
theorem decodeT (ast l: nat):
$ decode ast l -> ast e. XAST /\ l e. List u8 $;
----------------------------------------
-- Dynamic semantics
----------------------------------------
def Flags: nat = $ u64 $;
def CF (flags: nat): wff = $ 0 e. flags $;
def ZF (flags: nat): wff = $ 6 e. flags $;
def SF (flags: nat): wff = $ 7 e. flags $;
def OF (flags: nat): wff = $ 11 e. flags $;
def setCF (f: nat) (p: wff): nat = $ bitsUpdate 0 1 (nat p) f $;
def setZF (f: nat) (p: wff): nat = $ bitsUpdate 6 1 (nat p) f $;
def setSF (f: nat) (p: wff): nat = $ bitsUpdate 7 1 (nat p) f $;
def setOF (f: nat) (p: wff): nat = $ bitsUpdate 11 1 (nat p) f $;
theorem setCF_T (f: nat) (p: wff): $ f e. Flags -> setCF f p e. Flags $;
theorem setZF_T (f: nat) (p: wff): $ f e. Flags -> setZF f p e. Flags $;
theorem setSF_T (f: nat) (p: wff): $ f e. Flags -> setSF f p e. Flags $;
theorem setOF_T (f: nat) (p: wff): $ f e. Flags -> setOF f p e. Flags $;
def readBCond (f c: nat): wff;
theorem readBCondO (f: nat): $ readBCond f bcondO <-> OF f $;
theorem readBCondB (f: nat): $ readBCond f bcondB <-> CF f $;
theorem readBCondE (f: nat): $ readBCond f bcondE <-> ZF f $;
theorem readBCondNA (f: nat): $ readBCond f bcondNA <-> CF f \/ ZF f $;
theorem readBCondS (f: nat): $ readBCond f bcondS <-> SF f $;
theorem readBCondL (f: nat): $ readBCond f bcondL <-> ~(SF f <-> OF f) $;
theorem readBCondNG (f: nat): $ readBCond f bcondNG <-> ZF f \/ ~(SF f <-> OF f) $;
def readCondF (f c: nat): wff;
theorem readCondFAlways (f: nat): $ readCondF f condAlways $;
theorem readCondFPos (f c: nat): $ readCondF f (condPos c) <-> readBCond f c $;
theorem readCondFNeg (f c: nat): $ readCondF f (condNeg c) <-> ~readBCond f c $;
def Prot: set = $ Bits 3 $;
theorem finiteProt: $ finite Prot $;
def PROT_READ: nat = $ 1 $;
def PROT_WRITE: nat = $ 2 $;
def PROT_EXEC: nat = $ 4 $;
theorem PROT_READ_T: $ PROT_READ e. Prot $;
theorem PROT_WRITE_T: $ PROT_WRITE e. Prot $;
theorem PROT_EXEC_T: $ PROT_EXEC e. Prot $;
def Memory: set = $ Arrow u64 (Xp Prot u8) $;
theorem finiteMemory: $ finite Memory $;
def Exception: set = $ upto 3 $;
theorem finiteException: $ finite Exception $;
--| Represents the 'syscall' function
def exSysCall: nat = $ 0 $;
--| General protection fault, issued on invalid read/write
def exGPF: nat = $ 1 $;
--| Undefined instruction, issued on ud2 instruction
def exUD: nat = $ 2 $;
theorem exSysCallT: $ exSysCall e. Exception $;
theorem exGPF_T: $ exGPF e. Exception $;
theorem exUD_T: $ exUD e. Exception $;
--| ```
--| data Config = {
--| ex: Option Exception, -- nonnull if we are going to do IO on the next step
--| rip: u64, -- the intruction pointer
--| regs: Regs -> u64, -- the 16 general purpose registers
--| flags: Flags, -- the flags CF, ZF, SF, OF
--| mem: u64 -> Prot * u8 } -- the virtual memory
--| ```
def Config: set = $ Xp (Xp (Option Exception) u64) (Xp (Arrow Regs u64) (Xp Flags Memory)) $;
theorem finiteConfig: $ finite Config $;
def mkCfg (ex rip regs flags mem: nat): nat = $ (ex, rip), regs, flags, mem $;
theorem mkCfgT (ex rip regs flags mem: nat):
$ mkCfg ex rip regs flags mem e. Config <->
ex e. Option Exception /\ rip e. u64 /\ regs e. Arrow Regs u64 /\
flags e. Flags /\ mem e. Memory $;
def readException (k: nat): nat = $ pi11 k $;
def readRIP (k: nat): nat = $ pi12 k $;
def readReg (k r: nat): nat = $ pi21 k @ r $;
def readFlags (k: nat): nat = $ pi221 k $;
def getMemory (k: nat): nat = $ pi222 k $;
def readCond (k c: nat): wff = $ readCondF (readFlags k) c $;
theorem readExceptionT (k: nat): $ k e. Config -> readException k e. Option Exception $;
theorem readRIP_T (k: nat): $ k e. Config -> readRIP k e. u64 $;
theorem readRegT (k r: nat): $ k e. Config /\ r e. Regs -> readReg k r e. u64 $;
theorem readFlagsT (k: nat): $ k e. Config -> readFlags k e. Flags $;
theorem getMemoryT (k: nat): $ k e. Config -> getMemory k e. Memory $;
def readMemory1 (ps m a b .prot: nat): wff =
$ m e. Memory /\ a e. u64 /\ E. prot (m @ a = prot, b /\ ps C_ prot) $;
theorem readMemory1T (ps m a b: nat):
$ readMemory1 ps m a b -> ps e. Prot /\ m e. Memory /\ a e. u64 /\ b e. u8 $;
def readMemory (ps m a l: nat): wff;
theorem readMemory0 (ps m a: nat):
$ readMemory ps m a 0 <-> ps e. Prot /\ m e. Memory /\ a e. u64 $;
theorem readMemoryS (ps m a b l: nat):
$ readMemory ps m a (b : l) <->
readMemory1 ps m a b /\ readMemory ps m (a +_64 1) l $;
theorem readMemoryT (ps m a l: nat):
$ readMemory ps m a l -> ps e. Prot /\ m e. Memory /\ a e. u64 /\ l e. List u8 $;
def readMem (k a l: nat): wff = $ k e. Config /\ readMemory PROT_READ (getMemory k) a l $;
theorem readMemT (k a l: nat):
$ readMem k a l -> k e. Config /\ a e. u64 /\ l e. List u8 $;
def readMemX (k a l: nat): wff =
$ k e. Config /\ readMemory (PROT_READ + PROT_EXEC) (getMemory k) a l $;
theorem readMemX_T (k a l: nat):
$ readMemX k a l -> k e. Config /\ a e. u64 /\ l e. List u8 $;
def writeMemory1 (m a b m2 e .prot .b2: nat): wff =
$ m e. Memory /\ a e. u64 /\ b e. u8 /\
E. prot E. b2 (m @ a = prot, b2 /\
ifp (PROT_READ + PROT_WRITE C_ prot)
(m2 == write m a (prot, b) /\ e = 0)
(m2 == m /\ e = suc exGPF)) $;
theorem writeMemory1T (m a b m2 e: nat):
$ writeMemory1 m a b m2 e ->
m e. Memory /\ a e. u64 /\ b e. u8 /\
m2 e. Memory /\ e e. Option Exception $;
def writeMemory (m a l m2 e: nat): wff;
theorem writeMemory0 (m a m2 e: nat):
$ m e. Memory /\ a e. u64 ->
(writeMemory m a 0 m2 e <-> m2 = m /\ e = 0) $;
theorem writeMemoryS {m2 e1: nat} (m a b l m3 e: nat):
$ m e. Memory /\ a e. u64 /\ b e. u8 /\ l e. List u8 ->
(writeMemory m a (b : l) m3 e <->
E. m2 E. e1 (writeMemory1 m a b m2 e1 /\
ifp (e1 = 0)
(writeMemory m2 (a +_64 1) l m3 e)
(m3 = m2 /\ e = e1))) $;
theorem writeMemoryT (m a l m2 e: nat):
$ writeMemory m a l m2 e ->
m e. Memory /\ a e. u64 /\ l e. List u8 /\
m2 e. Memory /\ e e. Option Exception $;
def writeMem (k a l k2 .ip .r .f .m .m2 .e: nat): wff =
$ k e. Config /\ a e. u64 /\ l e. List u8 /\
E. ip E. r E. f E. m E. m2 E. e (writeMemory m a l m2 e /\
k = mkCfg 0 ip r f m /\ k2 = mkCfg e ip r f m2) $;
theorem writeMemT (k a l k2: nat):
$ writeMem k a l k2 -> k e. Config /\ a e. u64 /\ l e. List u8 /\ k2 e. Config $;
def EA: set = $ Sum u64 (Sum Regs u64) $;
def EA_i (q: nat): nat = $ b0 q $;
def EA_r (r: nat): nat = $ b1 (b0 r) $;
def EA_m (q: nat): nat = $ b1 (b1 q) $;
theorem EA_iT (q: nat): $ EA_i q e. EA <-> q e. u64 $;
theorem EA_rT (r: nat): $ EA_r r e. EA <-> r e. Regs $;
theorem EA_mT (q: nat): $ EA_m q e. EA <-> q e. u64 $;
def EA_addr (ea: nat): nat;
theorem EA_addrm (a: nat): $ EA_addr (EA_m a) = a $;
theorem EA_addr0 {a: nat} (ea: nat): $ ~(E. a ea = EA_m a) -> EA_addr ea = 0 $;
theorem EA_addrT (ea: nat): $ ea e. EA -> EA_addr ea e. u64 $;
def readIndex (k si: nat): nat;
theorem readIndex0 (k: nat): $ readIndex k 0 = 0 $;
theorem readIndexS (k sc r: nat):
$ readIndex k (suc (sc, r)) = chop 64 (shl (readReg k r) sc) $;
theorem readIndexT (k si: nat):
$ k e. Config /\ si e. Option ScaleIndex -> readIndex k si e. u64 $;
def readBase (k b: nat): nat;
theorem readBase0 (k: nat): $ readBase k 0 = 0 $;
theorem readBaseRIP (k: nat): $ readBase k base_RIP = readRIP k $;
theorem readBaseReg (k r: nat): $ readBase k (base_reg r) = readReg k r $;
theorem readBaseT (k b: nat):
$ k e. Config /\ b e. Base -> readBase k b e. u64 $;
def RM_EA (k rm: nat): nat;
theorem RM_EAreg (k r: nat): $ RM_EA k (RM_reg r) = EA_r r $;
theorem RM_EAmem (k si base q: nat): $ RM_EA k (RM_mem si base q) =
EA_m (readIndex k si +_64 readBase k base +_64 q) $;
theorem RM_EA_T (k rm: nat):
$ k e. Config /\ rm e. RM -> RM_EA k rm e. EA $;
def immRM_EA (k irm: nat): nat;
theorem immRM_EArm (k rm: nat): $ immRM_EA k (immRM_rm rm) = RM_EA k rm $;
theorem immRM_EAimm (k q: nat): $ immRM_EA k (immRM_imm q) = EA_i q $;
theorem immRM_EA_T (k irm: nat):
$ k e. Config /\ irm e. ImmRM -> immRM_EA k irm e. EA $;
def destEA (k ds: nat): nat;
theorem destEAm_i (k v q: nat): $ destEA k (Rm_i v q) = RM_EA k v $;
theorem destEAm_r (k v r: nat): $ destEA k (Rm_r v r) = RM_EA k v $;
theorem destEA_rm (k r rm: nat): $ destEA k (R_rm r rm) = EA_r r $;
theorem destEA_T (k ds: nat):
$ k e. Config /\ ds e. DestSrc -> destEA k ds e. EA $;
def srcEA (k ds: nat): nat;
theorem srcEAm_i (k v q: nat): $ srcEA k (Rm_i v q) = EA_i q $;
theorem srcEAm_r (k v r: nat): $ srcEA k (Rm_r v r) = EA_r r $;
theorem srcEA_rm (k r rm: nat): $ srcEA k (R_rm r rm) = RM_EA k rm $;
theorem srcEA_T (k ds: nat):
$ k e. Config /\ ds e. DestSrc -> srcEA k ds e. EA $;
def readRegSz (k sz r: nat): nat =
$ chop (wsizeBits sz)
(if (sz = wSz8 F. /\ 2 e. r) (shr (readReg k (r - 4)) 8) (readReg k r)) $;
theorem readRegSzT (k sz r: nat):
$ k e. Config /\ sz e. WSize /\ r e. Regs ->
readRegSz k sz r e. Bits (wsizeBits sz) $;
def readEA (k sz ea v: nat): wff;
theorem readEA_i (k q sz v: nat):
$ k e. Config /\ q e. u64 /\ sz e. WSize ->
(readEA k sz (EA_i q) v <-> v = chop (wsizeBits sz) q) $;
theorem readEA_r (k sz r v: nat):
$ k e. Config /\ r e. Regs /\ sz e. WSize ->
(readEA k sz (EA_r r) v <-> v = readRegSz k sz r) $;
theorem readEA_m (k a sz v: nat):
$ k e. Config /\ a e. u64 /\ sz e. WSize ->
(readEA k sz (EA_m a) v <->
v e. Bits (wsizeBits sz) /\ readMem k a (toBytes (wsizeBytes sz) v)) $;
theorem readEA_T (k sz ea v: nat): $ readEA k sz ea v ->
k e. Config /\ ea e. EA /\ sz e. WSize /\ v e. Bits (wsizeBits sz) $;
def readEA64 (k ea v: nat): wff = $ readEA k wSz64 ea v $;
theorem readEA64T (k ea v: nat): $ readEA64 k ea v ->
k e. Config /\ ea e. EA /\ v e. u64 $;
def setException (k e: nat): nat;
theorem setExceptionVal (ex ip rs f m e: nat):
$ setException (mkCfg ex ip rs f m) e = mkCfg e ip rs f m $;
theorem setExceptionT (k e: nat):
$ k e. Config /\ e e. Option Exception -> setException k e e. Config $;
def setReg (k r q: nat): nat;
theorem setRegVal (ex ip rs f m r q: nat):
$ setReg (mkCfg ex ip rs f m) r q = mkCfg ex ip (lower (write rs r q)) f m $;
theorem setRegT (k r q: nat):
$ k e. Config /\ r e. Regs /\ q e. u64 -> setReg k r q e. Config $;
def writeReg (k sz r v: nat): nat;
theorem writeReg8 (k r v: nat) (have_rex: wff):
$ writeReg k (wSz8 have_rex) r v = if (~have_rex /\ 2 e. r)
(setReg k (r - 4) (bitsUpdate 8 8 v (readReg k (r - 4))))
(setReg k r (bitsUpdate 0 8 v (readReg k r))) $;
theorem writeReg16 (k r v: nat):
$ writeReg k wSz16 r v = setReg k r (bitsUpdate 0 16 v (readReg k r)) $;
theorem writeReg32 (k r v: nat): $ writeReg k wSz32 r v = setReg k r v $;
theorem writeReg64 (k r v: nat): $ writeReg k wSz64 r v = setReg k r v $;
theorem writeRegT (k sz r v: nat): $ k e. Config /\ sz e. WSize /\
r e. Regs /\ v e. Bits (wsizeBits sz) -> writeReg k sz r v e. Config $;
def writeEASz (k sz ea v k2: nat): wff;
theorem writeEASz_i (k sz i v k2: nat): $ ~ writeEASz k sz (EA_i i) v k2 $;
theorem writeEASz_r (k sz r v k2: nat):
$ k e. Config /\ sz e. WSize /\ r e. Regs /\ v e. Bits (wsizeBits sz) ->
(writeEASz k sz (EA_r r) v k2 <-> k2 = writeReg k sz r v) $;
theorem writeEASz_m (k sz a v k2: nat):
$ k e. Config /\ sz e. WSize /\ a e. u64 /\ v e. Bits (wsizeBits sz) ->
(writeEASz k sz (EA_m a) v k2 <->
writeMem k a (toBytes (wsizeBits sz) v) k2) $;
theorem writeEASzT (k sz ea v k2: nat):
$ writeEASz k sz ea v k2 ->
k e. Config /\ sz e. WSize /\ ea e. EA /\ v e. Bits (wsizeBits sz) /\
k2 e. Config $;
def writeEA (k sz ea v k2: nat): wff =
$ v e. u64 /\ writeEASz k sz ea (chop (wsizeBits sz) v) k2 $;
theorem writeEA_T (k sz ea v k2: nat):
$ writeEA k sz ea v k2 ->
k e. Config /\ sz e. WSize /\ ea e. EA /\ v e. u64 /\
k2 e. Config $;
def writeRIP (k q: nat): nat;
theorem writeRIPVal (ex ip rs f m q: nat):
$ writeRIP (mkCfg ex ip rs f m) q = mkCfg ex q rs f m $;
theorem writeRIP_T (k q: nat):
$ k e. Config /\ q e. u64 -> writeRIP k q e. Config $;
def EA_callDest (k ea v: nat): wff;
theorem EA_callDest_i (k i v: nat):
$ k e. Config /\ i e. u64 ->
(EA_callDest k (EA_i i) v <-> v = readRIP k +_64 i) $;
theorem EA_callDest_r (k r v: nat):