SNAPKITTYWEST commited on
Commit
0e9783b
·
verified ·
1 Parent(s): 6705343

Sync from GitHub at 25c8330: hardware-in-the-loop rig, SAM D21 board, guard elimination on RV32/Cortex-M3

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .github/workflows/hardware.yml +33 -0
  2. .github/workflows/lean.yml +32 -1
  3. CHANGELOG.md +59 -0
  4. NEXT_STEPS.md +34 -6
  5. README.md +0 -0
  6. backend/common/Harness32.lean +130 -0
  7. backend/cortexm/CM/Boot.lean +4 -4
  8. backend/cortexm/CM/Correct.lean +54 -25
  9. backend/cortexm/CM/Emit.lean +67 -21
  10. backend/cortexm/CM/Guard.lean +51 -9
  11. backend/cortexm/CM/Init.lean +30 -22
  12. backend/cortexm/CM/Isa.lean +1 -1
  13. backend/cortexm/CM/Lower.lean +118 -71
  14. backend/cortexm/CM/Rel.lean +13 -2
  15. backend/cortexm/CM/Run.lean +31 -28
  16. backend/cortexm/CM/SimAux.lean +35 -34
  17. backend/cortexm/CM/SimBin.lean +9 -9
  18. backend/cortexm/CM/SimCtl.lean +29 -24
  19. backend/cortexm/CM/SimDiv.lean +43 -43
  20. backend/cortexm/CM/SimMemOps.lean +42 -42
  21. backend/cortexm/CM/SimOps.lean +45 -45
  22. backend/cortexm/CM/SimStack.lean +77 -75
  23. backend/cortexm/CM/SimStep.lean +35 -18
  24. backend/cortexm/CMMain.lean +89 -38
  25. backend/cortexm0/CM0/Boot.lean +4 -4
  26. backend/cortexm0/CM0/Correct.lean +54 -25
  27. backend/cortexm0/CM0/Emit.lean +135 -21
  28. backend/cortexm0/CM0/Guard.lean +51 -9
  29. backend/cortexm0/CM0/Init.lean +30 -22
  30. backend/cortexm0/CM0/Isa.lean +1 -1
  31. backend/cortexm0/CM0/Lower.lean +125 -74
  32. backend/cortexm0/CM0/Rel.lean +13 -2
  33. backend/cortexm0/CM0/Run.lean +31 -28
  34. backend/cortexm0/CM0/SimAux.lean +35 -34
  35. backend/cortexm0/CM0/SimBin.lean +9 -9
  36. backend/cortexm0/CM0/SimCtl.lean +29 -24
  37. backend/cortexm0/CM0/SimDiv.lean +51 -51
  38. backend/cortexm0/CM0/SimMemOps.lean +42 -42
  39. backend/cortexm0/CM0/SimOps.lean +45 -45
  40. backend/cortexm0/CM0/SimStack.lean +77 -75
  41. backend/cortexm0/CM0/SimStep.lean +35 -18
  42. backend/cortexm0/CM0Main.lean +123 -35
  43. backend/rv32/RV32/Correct.lean +54 -25
  44. backend/rv32/RV32/Emit.lean +12 -1
  45. backend/rv32/RV32/Guard.lean +51 -9
  46. backend/rv32/RV32/Init.lean +30 -22
  47. backend/rv32/RV32/Lower.lean +117 -70
  48. backend/rv32/RV32/Rel.lean +13 -2
  49. backend/rv32/RV32/Run.lean +31 -28
  50. backend/rv32/RV32/SimAux.lean +35 -34
.github/workflows/hardware.yml ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: hardware
2
+ # Runs every Forth example on real boards attached to a self-hosted runner (docs/HIL.md) and
3
+ # checks each board's serial transcript against the Lean semantics. A self-hosted runner must
4
+ # never run code from pull requests, so it never runs on them.
5
+ #
6
+ # For now it runs only when started from the Actions tab, so pushes do not queue a job that no
7
+ # machine can take. Once the rig is registered (docs/HIL.md, step 5), add
8
+ # push:
9
+ # branches: [master]
10
+ # under `on:` to check every change to master on the boards.
11
+ on:
12
+ workflow_dispatch:
13
+ jobs:
14
+ samd21:
15
+ runs-on: [self-hosted, linux, samd21]
16
+ env:
17
+ HIL_TTY: ${{ vars.SAMD21_TTY }}
18
+ HIL_ADAPTER_SERIAL: ${{ vars.SAMD21_ADAPTER_SERIAL }}
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - name: Make lake available
22
+ run: |
23
+ if [ ! -x "$HOME/.elan/bin/lake" ]; then
24
+ curl -sSfL https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh -o elan-init.sh
25
+ sh elan-init.sh -y --default-toolchain none
26
+ fi
27
+ echo "$HOME/.elan/bin" >> "$GITHUB_PATH"
28
+ - name: Build cm0c
29
+ run: lake build cm0c
30
+ - name: Every example on the SAM D21 Curiosity Nano
31
+ run: |
32
+ [ -n "$HIL_TTY" ] || { echo "set the repository variable SAMD21_TTY (docs/HIL.md)"; exit 1; }
33
+ scripts/hil/run-all.sh samd21-cnano "$HIL_TTY"
.github/workflows/lean.yml CHANGED
@@ -33,7 +33,7 @@ jobs:
33
  - name: Forth source files (WebAssembly)
34
  run: for f in examples/forth/*.fs; do .lake/build/bin/wasmw forth "$f" || exit 1; done
35
  - name: Install AArch64/RISC-V toolchain and emulators (user mode, the bare RV32 board and the Cortex-M boards)
36
- run: sudo apt-get update && sudo apt-get install -y clang lld qemu-user qemu-system-misc qemu-system-arm
37
  - name: AArch64 execution check (qemu)
38
  run: .lake/build/bin/a64c check 300
39
  - name: Forth source files (AArch64)
@@ -54,3 +54,34 @@ jobs:
54
  run: .lake/build/bin/cm0c check 300
55
  - name: Forth source files (Cortex-M0, 32-bit words)
56
  run: for f in examples/forth/*.fs; do .lake/build/bin/cm0c forth "$f" || exit 1; done
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  - name: Forth source files (WebAssembly)
34
  run: for f in examples/forth/*.fs; do .lake/build/bin/wasmw forth "$f" || exit 1; done
35
  - name: Install AArch64/RISC-V toolchain and emulators (user mode, the bare RV32 board and the Cortex-M boards)
36
+ run: sudo apt-get update && sudo apt-get install -y clang lld llvm qemu-user qemu-system-misc qemu-system-arm
37
  - name: AArch64 execution check (qemu)
38
  run: .lake/build/bin/a64c check 300
39
  - name: Forth source files (AArch64)
 
54
  run: .lake/build/bin/cm0c check 300
55
  - name: Forth source files (Cortex-M0, 32-bit words)
56
  run: for f in examples/forth/*.fs; do .lake/build/bin/cm0c forth "$f" || exit 1; done
57
+ - name: Without the depth certificates (--no-opt keeps every guard)
58
+ run: |
59
+ for t in cm0c cmc rv32c; do
60
+ for f in examples/forth/*.fs; do .lake/build/bin/$t forth "$f" --no-opt || exit 1; done
61
+ done
62
+ - name: Guard elimination shrinks the microcontroller code
63
+ run: |
64
+ mkdir -p /tmp/size && cd /tmp/size
65
+ for spec in cm0c:thumbv6m-none-eabi:-mcpu=cortex-m0 cmc:thumbv7m-none-eabi:-mcpu=cortex-m3 rv32c:riscv32-unknown-elf:-march=rv32im; do
66
+ t=${spec%%:*}; rest=${spec#*:}; tgt=${rest%%:*}; fl=${rest#*:}
67
+ for f in $GITHUB_WORKSPACE/examples/forth/*.fs; do
68
+ n=$(basename "$f" .fs)
69
+ $GITHUB_WORKSPACE/.lake/build/bin/$t emit-forth "$f" > "$t-$n-opt.s"
70
+ $GITHUB_WORKSPACE/.lake/build/bin/$t emit-forth "$f" --no-opt > "$t-$n-all.s"
71
+ for v in opt all; do clang --target=$tgt $fl -c -o "$t-$n-$v.o" "$t-$n-$v.s" || exit 1; done
72
+ a=$(llvm-size "$t-$n-all.o" | awk 'NR==2{print $1}'); b=$(llvm-size "$t-$n-opt.o" | awk 'NR==2{print $1}')
73
+ echo "$t $n: $a -> $b bytes of code"
74
+ [ "$b" -le "$a" ] || exit 1
75
+ done
76
+ done
77
+ - name: Board images (image, run on the emulated boards, verify the serial log)
78
+ run: |
79
+ mkdir -p /tmp/board && cd /tmp/board
80
+ # Microchip SAM D21 Curiosity Nano: not emulated; build every example's image (it must
81
+ # assemble, link into 128 KiB of flash and convert to Intel HEX)
82
+ for f in $GITHUB_WORKSPACE/examples/forth/*.fs; do $GITHUB_WORKSPACE/.lake/build/bin/cm0c image "$f" --board samd21-cnano || exit 1; done
83
+ for t in cm0c cmc; do $GITHUB_WORKSPACE/.lake/build/bin/$t image $GITHUB_WORKSPACE/examples/forth/fib.fs || exit 1; done
84
+ (timeout 10 qemu-system-arm -M microbit -kernel fib-microbit-v1.elf -display none -serial stdio -monitor none || true) > v1.log
85
+ (timeout 10 qemu-system-arm -M lm3s6965evb -kernel fib.elf -display none -serial stdio -monitor none || true) > lm3s.log
86
+ $GITHUB_WORKSPACE/.lake/build/bin/cm0c verify $GITHUB_WORKSPACE/examples/forth/fib.fs v1.log
87
+ $GITHUB_WORKSPACE/.lake/build/bin/cmc verify $GITHUB_WORKSPACE/examples/forth/fib.fs lm3s.log
CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ All notable changes to UniversalWord. The version is the one in `lakefile.toml`.
4
+
5
+ ## 0.1.0 — unreleased
6
+
7
+ The first release. Everything below is proved in Lean 4 (`leanprover/lean4:v4.34.1`) using only
8
+ the standard axioms `propext`, `Quot.sound` and `Classical.choice`, which `formal/Audit.lean`
9
+ checks in CI, or, for the agreement of the models with real tools and machines, tested by
10
+ execution in CI.
11
+
12
+ ### The Universal Word IR (`formal/`)
13
+
14
+ - Word-level machine semantics: words, memory, the instruction set, traps, the data, return and
15
+ auxiliary stacks, execution relations and a fuel-bounded interpreter proved sound and complete
16
+ against them (#4, #17).
17
+ - Checked stack-depth certificates (`WordDialect/Depth.lean`): lower bounds (`certOk`), upper
18
+ bounds against a capacity (`boundOk`), and per-word frame certificates that track each word's
19
+ net stack effect (`frameOk`), each proved sound; untrusted analyses propose them (#34–#36).
20
+
21
+ ### Frontends
22
+
23
+ - Forth: colon definitions, recursion, variables and constants, `CREATE`/`ALLOT`/`,`,
24
+ `IF`/`ELSE`/`THEN`, `BEGIN … UNTIL`/`WHILE … REPEAT`, `DO … LOOP`/`+LOOP` with `?DO`, `LEAVE`
25
+ and `UNLOOP`, `CASE … ENDCASE`, `>R R> R@`, and the double-cell words
26
+ `UM* UM/MOD M* SM/REM FM/MOD */MOD */`, compiled to the IR with `compile_correct`; a parser that
27
+ implements an inductive grammar exactly, with a proved print/parse round trip (#15–#23).
28
+ - A BCPL subset and Wolfram-style integer expressions and matrix products, compiled to the IR
29
+ with correctness proofs (#4).
30
+
31
+ ### Backends, each proved against its machine model and tested under emulation
32
+
33
+ - x86-64 (#5, #13, #15), WebAssembly (#6, #9, #10, #12, #14), AArch64 (#24, #27) and RISC-V
34
+ RV64IM (#25, #28), with `wordc`, `wasmw`, `a64c` and `rv64c`.
35
+ - Microcontroller profiles at 32-bit words, bare metal: RV32IM on the QEMU `virt` board
36
+ (`rv32c`, #29), Cortex-M3 on a Stellaris LM3S6965 (`cmc`, #30) and Cortex-M0 on a BBC micro:bit
37
+ (`cm0c`, #32, with division by a proved loop).
38
+ - Cortex-M images boot from flash, with the start-up copy proved (#31).
39
+ - Board runtime: UART set-up for the real boards, the end of a run signalled on the UART,
40
+ flashable `.hex` images, the expected serial transcript and a `verify` command
41
+ (`docs/HARDWARE.md`, #33). Not yet run on physical boards.
42
+
43
+ ### Verified optimisation
44
+
45
+ - The microcontroller backends leave out the stack guards the depth certificates show cannot
46
+ fire, with the certificates' checks as hypotheses of the end-to-end theorems: code is up to
47
+ 72% smaller on the Cortex-M0, 60% on the Cortex-M3 and 56% on RV32 (#34–#37). `--no-opt` keeps
48
+ every guard; `stats` counts the guards left out.
49
+
50
+ ### Known limits
51
+
52
+ - The machine models (and, for the boards, the device set-up) are trusted; agreement with real
53
+ assemblers, emulators and machines is tested, not proved. Physical boards are untested.
54
+ - The Forth lexer has no independent specification yet (`NEXT_STEPS.md`).
55
+ - Guard elimination is not yet used by the 64-bit backends or WebAssembly.
56
+
57
+ ### License
58
+
59
+ Parr Source License — No AI Training, Version 1.0 (`License`).
NEXT_STEPS.md CHANGED
@@ -63,13 +63,21 @@ the device addresses are those of the `virt` board, and the stacks hold 4096 wor
63
  ## Done: Cortex-M profile
64
 
65
  `backend/cortexm` lowers the 32-bit IR to Thumb-2 (ARMv7-M) and proves it end to end
66
- (`CM.Emit.binary_correct`), with a bare-metal runtime (vector table, UART output, semihosting
67
- exit). The image boots from flash: the reset handler's copy of `.data` to SRAM is proved
68
  (`CM/Boot.lean`, `boot_correct`). `cmc` runs it on an emulated Stellaris LM3S6965 Cortex-M3
69
- (`qemu-system-arm -M lm3s6965evb`); CI runs it. Choices a later change may revisit: the stop
70
- uses semihosting (a board without a debugger needs another end-of-run signal), the UART
71
- initialisation leaves the baud rate at its reset value, and the cell address uses `lsl` and
72
- `add` rather than Thumb-2's indexed `ldr`.
 
 
 
 
 
 
 
 
73
 
74
  ## Done: Cortex-M0 profile
75
 
@@ -81,6 +89,26 @@ end, from the flash image (`CM0.Emit.boot_correct`). ARMv6-M has no divide instr
81
  a `bl` (simple, at a cost in code size), constants are built from bytes rather than loaded from
82
  literal pools, and the stacks hold 1024 words each to fit the 16 KiB of SRAM.
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  ## 1. Forth: double-cell storage and arithmetic
85
 
86
  The double-cell storage words (`2@ 2! 2VARIABLE`) and double-cell arithmetic
 
63
  ## Done: Cortex-M profile
64
 
65
  `backend/cortexm` lowers the 32-bit IR to Thumb-2 (ARMv7-M) and proves it end to end
66
+ (`CM.Emit.binary_correct`), with a bare-metal runtime (vector table, UART output, end of run on
67
+ the UART). The image boots from flash: the reset handler's copy of `.data` to SRAM is proved
68
  (`CM/Boot.lean`, `boot_correct`). `cmc` runs it on an emulated Stellaris LM3S6965 Cortex-M3
69
+ (`qemu-system-arm -M lm3s6965evb`); CI runs it. Choices a later change may revisit: the cell
70
+ address uses `lsl` and `add` rather than Thumb-2's indexed `ldr`.
71
+
72
+ ## Done: board runtime
73
+
74
+ The Cortex-M3 and Cortex-M0 runtimes set up the clock and UART as a real board needs (crystal,
75
+ UART clock and pins, 115200 8N1) and end a run on the UART (`EXIT` and the status, then `wfi`)
76
+ instead of semihosting, so no debugger is needed. `cmc image` / `cm0c image` write the ELF, an
77
+ Intel HEX file and the UART transcript a correct run prints; `cmc verify` / `cm0c verify` check a
78
+ serial log captured from a board. `docs/HARDWARE.md` is the runbook. **Not yet run on real
79
+ silicon**: the board set-up follows the vendors' documentation and is exercised only on the
80
+ emulators, which ignore clocks and baud rates.
81
 
82
  ## Done: Cortex-M0 profile
83
 
 
89
  a `bl` (simple, at a cost in code size), constants are built from bytes rather than loaded from
90
  literal pools, and the stacks hold 1024 words each to fit the 16 KiB of SRAM.
91
 
92
+ ## Done: stack-guard elimination (RV32, Cortex-M3, Cortex-M0)
93
+
94
+ `formal/WordDialect/Depth.lean`: a stack-depth certificate, checked by `certOk`, holds at every
95
+ reachable state (`DepthInv.steps`); upper bounds, checked by `boundOk` and `frameOk` (per word)
96
+ against a capacity, are backed by invariants kept through every step taken within it
97
+ (`UbSound`). The three microcontroller lowerings drop each underflow guard the certificate covers
98
+ and each data-stack overflow guard where the bound shows room; `binary_correct` (and
99
+ `boot_correct` on the Cortex-M profiles) assume `certOk` and `UbSound`, which `rv32c`, `cmc` and
100
+ `cm0c` obtain from checks (`certTable`, `upperTable`), falling back to keeping the guards. Code
101
+ is up to 72% smaller. Choices a later
102
+ change may revisit:
103
+
104
+ - the 64-bit backends and WebAssembly do not use them yet;
105
+ - upper bounds are per word (frame certificates): a word is identified by its entry, so code
106
+ shared between two words (one reached by a jump from another) makes `frameOk` reject the
107
+ certificate, and the context-insensitive bound is used alone;
108
+ - auxiliary-stack and return-stack overflow guards are all kept (they are few);
109
+ - call return points claim depth 0 for lower bounds, so an underflow guard right after a call
110
+ stays.
111
+
112
  ## 1. Forth: double-cell storage and arithmetic
113
 
114
  The double-cell storage words (`2@ 2! 2VARIABLE`) and double-cell arithmetic
README.md CHANGED
The diff for this file is too large to render. See raw diff
 
backend/common/Harness32.lean CHANGED
@@ -93,6 +93,55 @@ def parseHexDump (s : Sample32) (out : String) : Except String Result :=
93
  else .ok (.halted (rest.take depth) ((rest.drop depth).take m) (rest.drop (depth + m)))
94
  | _ => .error s!"malformed dump: {out}"
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def check32 (run : Runner32) (s : Sample32) : IO Bool := do
97
  if let some e := s.buildError then
98
  IO.println s!"ERROR {s.name}: {e}"; return false
@@ -211,3 +260,84 @@ def checkAll32 (run : Runner32) (count : Nat) : IO Bool := do
211
  let fz ← fuzz32 run count
212
  let ovf ← checkOverflow32 run
213
  return ok && fz && ovf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  else .ok (.halted (rest.take depth) ((rest.drop depth).take m) (rest.drop (depth + m)))
94
  | _ => .error s!"malformed dump: {out}"
95
 
96
+ /-! ## The end-of-run protocol of the microcontroller runtimes
97
+
98
+ A board has no exit status to give back, so the Cortex-M runtimes end every run on the UART:
99
+ after the halt dump (if the program halted) they write a line `EXIT` and the status as one more
100
+ word line (`0` for halt, the trap code otherwise), then sleep. The host reads up to that line,
101
+ whether the other end is an emulator or a serial port. -/
102
+
103
+ def exitMarker : String := "EXIT"
104
+
105
+ /-- The eight-hexadecimal-digit line the runtimes print for a word. -/
106
+ def hexLine (v : Nat) : String :=
107
+ let d := Nat.toDigits 16 (v % 2 ^ 32)
108
+ String.ofList (List.replicate (8 - d.length) '0' ++ d)
109
+
110
+ /-- Lines of a transcript: carriage returns dropped (a serial terminal may add them), blank
111
+ lines and anything before the first word line (boot noise on a real board) ignored. -/
112
+ def transcriptLines (t : String) : List String :=
113
+ let ls := ((t.replace "\r" "").splitOn "\n").map String.trim |>.filter (· ≠ "")
114
+ ls.dropWhile fun l => l ≠ exitMarker ∧ (hexWords l).isNone
115
+
116
+ /-- The result a transcript reports: the status after `EXIT`, and for status 0 the dump before it. -/
117
+ def parseTranscript (s : Sample32) (t : String) : Except String Result :=
118
+ let ls := transcriptLines t
119
+ match ls.findIdx? (· == exitMarker) with
120
+ | none => .error s!"no {exitMarker} line in the output: {t}"
121
+ | some i =>
122
+ match hexWords (ls.getD (i + 1) "") with
123
+ | some [0] => parseHexDump s (String.intercalate "\n" (ls.take i))
124
+ | some [k] => .ok (.trap k)
125
+ | _ => .error s!"no status after {exitMarker}: {t}"
126
+
127
+ /-- The exact UART output a correct run prints: what a board's serial log must contain. -/
128
+ def transcriptOf : Result → Option String
129
+ | .halted st mem regs =>
130
+ some (String.intercalate "\n" ((st.length :: st ++ mem ++ regs).map hexLine ++
131
+ [exitMarker, hexLine 0]) ++ "\n")
132
+ | .trap k => some (exitMarker ++ "\n" ++ hexLine k ++ "\n")
133
+ | .timeout => none
134
+
135
+ /-- Read a running target's UART up to the `EXIT` line and the status after it (or the end of
136
+ the output, if the target stops first). -/
137
+ partial def readUntilExit (h : IO.FS.Handle) (acc : String := "") (seen : Bool := false) :
138
+ IO String := do
139
+ let l ← h.getLine
140
+ if l.isEmpty then return acc
141
+ let acc := acc ++ l
142
+ if seen then return acc
143
+ readUntilExit h acc (l.trim == exitMarker)
144
+
145
  def check32 (run : Runner32) (s : Sample32) : IO Bool := do
146
  if let some e := s.buildError then
147
  IO.println s!"ERROR {s.name}: {e}"; return false
 
260
  let fz ← fuzz32 run count
261
  let ovf ← checkOverflow32 run
262
  return ok && fz && ovf
263
+
264
+ /-! ## Guard elimination
265
+
266
+ The microcontroller profiles leave out stack guards that the checked certificates of
267
+ `WordDialect.Depth` show cannot fire. These checks exercise the boundary: a data stack of
268
+ `capacity` words filled exactly by straight-line code (every overflow guard removed; the run
269
+ halts), the same after a call to a word with net effect -1, and one word more in each case, or a
270
+ recursion that grows the stack (the guard that must fire is kept; exit 6). -/
271
+
272
+ def checkCapacity32 (run : Runner32) (capacity : Nat) : IO Bool := do
273
+ let fill : Sample32 :=
274
+ { name := "cap_fill", prog := List.replicate capacity (.word 1) ++ [.halt], mem := [] }
275
+ let ok1 ← check32 run fill
276
+ -- the word at `w` pushes two words and drops three: net effect -1
277
+ let afterCall (extra : Nat) : List (WordDialect.Instr 32) :=
278
+ let w := 2 + (capacity + extra) + 1
279
+ [.word 7, .call w] ++ List.replicate (capacity + extra) (.word 1) ++ [.halt] ++
280
+ [.word 1, .word 2, .drop, .drop, .drop, .ret]
281
+ let ok2 ← check32 run { name := "cap_fill_after_call", prog := afterCall 0, mem := [] }
282
+ let mut ok := ok1 && ok2
283
+ for (name, prog) in [("cap_over_word", List.replicate capacity (.word 1) ++ [.word 1, .halt]),
284
+ ("cap_over_dup", List.replicate capacity (.word 1) ++ [.dup, .halt]),
285
+ ("cap_over_after_call", afterCall 1),
286
+ -- recursion that grows the data stack by two words a level
287
+ ("ovf_recursive_push2", [.call 2, .halt, .word 1, .word 2, .call 2, .ret])] do
288
+ match ← run { name, prog, mem := [] } with
289
+ | .ok (.trap 6) => IO.println s!"PASS {name} overflow exit 6"
290
+ | .ok got => IO.println s!"FAIL {name} expected overflow exit 6, got {repr got}"; ok := false
291
+ | .error e => IO.println s!"ERROR {name}: {e}"; ok := false
292
+ return ok
293
+
294
+ /-- How many guards the certificates `lo` (lower bounds) and `hi` (upper bounds) leave out of
295
+ program `p`, against a data stack of `dCap` words. -/
296
+ def guardStats (s : Sample32) (lo hi : Nat → Nat) (dCap : Nat) : String :=
297
+ let p := s.prog
298
+ let grows : WordDialect.Instr 32 → Bool
299
+ | .word _ | .ptr _ | .push _ | .dup | .over | .fromr | .rfetch => true
300
+ | _ => false
301
+ let idx := p.zipIdx
302
+ let uf := idx.filter fun (i, _) => 0 < i.pops
303
+ let ufKept := uf.filter fun (i, k) => lo k < i.pops
304
+ let ov := idx.filter fun (i, _) => grows i
305
+ let ovKept := ov.filter fun (_, k) => !(hi k + 1 ≤ dCap)
306
+ let frames := if frameOk p dCap (analyseFrames p dCap) then "accepted" else "rejected"
307
+ s!"{s.name}: {p.length} instructions; underflow guards {uf.length} → {ufKept.length}; data-stack overflow guards {ov.length} → {ovKept.length} (frame certificate {frames})"
308
+
309
+ /-! ## Images for real boards
310
+
311
+ `image` turns a program into files for a real board: the ELF, an Intel HEX file (what a
312
+ micro:bit takes by drag and drop, and what most flash tools accept), and the UART transcript a
313
+ correct run prints (`transcriptOf` of the Lean outcome). `verify` checks a serial log captured
314
+ from the board against the Lean semantics. -/
315
+
316
+ /-- Write `<stem>.elf`, `<stem>.hex` and `<stem>.expected` next to each other. -/
317
+ def writeImage (s : Sample32) (elf : String) (stem : String) : IO UInt32 := do
318
+ if let some e := s.buildError then IO.eprintln e; return 1
319
+ match transcriptOf (expected32 s) with
320
+ | none => IO.eprintln s!"{s.name}: the IR run does not end within the fuel"; return 1
321
+ | some t =>
322
+ IO.FS.writeBinFile (stem ++ ".elf") (← IO.FS.readBinFile elf)
323
+ let o ← IO.Process.output
324
+ { cmd := "llvm-objcopy", args := #["-O", "ihex", elf, stem ++ ".hex"] }
325
+ if o.exitCode != 0 then IO.eprintln s!"llvm-objcopy failed: {o.stderr}"; return 1
326
+ IO.FS.writeFile (stem ++ ".expected") t
327
+ IO.println s!"wrote {stem}.elf, {stem}.hex and {stem}.expected (the UART output a correct run prints)"
328
+ return 0
329
+
330
+ /-- Compare a serial log from a board with the Lean semantics. -/
331
+ def verifyLog (s : Sample32) (logPath : String) : IO UInt32 := do
332
+ if let some e := s.buildError then IO.eprintln e; return 1
333
+ -- keep printable ASCII and newlines: a board can put glitch bytes (not UTF-8) on the line as
334
+ -- its UART comes up
335
+ let bytes ← IO.FS.readBinFile logPath
336
+ let log := String.mk (bytes.toList.filterMap fun b =>
337
+ if b == 10 || (32 ≤ b && b < 127) then some (Char.ofNat b.toNat) else none)
338
+ let exp := expected32 s
339
+ match parseTranscript s log with
340
+ | .error e => IO.println s!"FAIL {s.name}: {e}"; return 1
341
+ | .ok got =>
342
+ if got == exp then IO.println s!"PASS {s.name} {repr exp}"; return 0
343
+ else IO.println s!"FAIL {s.name}\n lean: {repr exp}\n board: {repr got}"; return 1
backend/cortexm/CM/Boot.lean CHANGED
@@ -4,7 +4,7 @@ import CM.Init
4
  # CM.Boot
5
 
6
  Booting from flash, proved. A Cortex-M runs from flash: the vector table and code are there, and
7
- `.data` (IR memory, the register file and the semihosting block) is linked to RAM with its load
8
  address in flash. The reset handler first copies `.data` to RAM with the ten-instruction loop
9
  `Emit.copyCode`, printed from the model like the lowered program, then runs the prologue.
10
 
@@ -260,15 +260,15 @@ theorem copy_holds {r : Runtime} {ld : Loader} {lma : Nat} {x0 : M} (h : FlashHo
260
  copy loop runs to its end; from there the prologue runs, and the lowered code reaches the outcome
261
  the IR reaches from `State.init` on the memory image, or exits with `overflow`. -/
262
  theorem boot_correct (r : Runtime) (ld : Loader) (lma : Nat) (p : Prog 32)
263
- (hlen : 17 * p.length < 2 ^ 32) (hreg : RegsOk (cfgOf r ld) p) {o : Outcome 32}
264
- (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M}
265
  (h : FlashHolds r ld lma x0) (hpc : x0.pc = 0) :
266
  ∃ x1, RSteps (copyCode (ofN lma) (ofN ld.mb) (dataWords r)) x0 x1 ∧ x1.pc = 10 ∧
267
  rseq (prologueCode r ld) x1 = .next { entryState r ld x1 with pc := x1.pc + 6 } ∧
268
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x1) o ∨
269
  RExec (lowerProg r.layout p) (entryState r ld x1) .overflow) := by
270
  obtain ⟨x1, hs, hpc1, hh⟩ := copy_holds h hpc
271
- exact ⟨x1, hs, hpc1, binary_correct r ld p hlen hreg hx hh⟩
272
 
273
  end Emit
274
  end CM
 
4
  # CM.Boot
5
 
6
  Booting from flash, proved. A Cortex-M runs from flash: the vector table and code are there, and
7
+ `.data` (IR memory, the register file and the two-word status block) is linked to RAM with its load
8
  address in flash. The reset handler first copies `.data` to RAM with the ten-instruction loop
9
  `Emit.copyCode`, printed from the model like the lowered program, then runs the prologue.
10
 
 
260
  copy loop runs to its end; from there the prologue runs, and the lowered code reaches the outcome
261
  the IR reaches from `State.init` on the memory image, or exits with `overflow`. -/
262
  theorem boot_correct (r : Runtime) (ld : Loader) (lma : Nat) (p : Prog 32)
263
+ (hlen : 17 * p.length < 2 ^ 32) (hreg : RegsOk (cfgOf r ld) p) (hok : certOk p r.cert = true)
264
+ (hub : UbSound p r.dCap r.ub) {o : Outcome 32} (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M}
265
  (h : FlashHolds r ld lma x0) (hpc : x0.pc = 0) :
266
  ∃ x1, RSteps (copyCode (ofN lma) (ofN ld.mb) (dataWords r)) x0 x1 ∧ x1.pc = 10 ∧
267
  rseq (prologueCode r ld) x1 = .next { entryState r ld x1 with pc := x1.pc + 6 } ∧
268
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x1) o ∨
269
  RExec (lowerProg r.layout p) (entryState r ld x1) .overflow) := by
270
  obtain ⟨x1, hs, hpc1, hh⟩ := copy_holds h hpc
271
+ exact ⟨x1, hs, hpc1, binary_correct r ld p hlen hreg hok hub hx hh⟩
272
 
273
  end Emit
274
  end CM
backend/cortexm/CM/Correct.lean CHANGED
@@ -25,6 +25,11 @@ Hypotheses of both (all explicit):
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
 
 
 
 
 
28
  * `hsz` code indices fit in 32 bits;
29
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
30
  -/
@@ -44,15 +49,30 @@ def Final (c : Cfg) (p : Prog 32) (code : List (Instr Nat)) (x : M) : Outcome 32
44
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
45
  | .trapped t => RExec code x (.trapped t)
46
 
47
- theorem offs_ge {p : Prog 32} {k : Nat} (h : p.length ≤ k) : offs p k = offs p p.length := by
48
- simp [offs, List.take_of_length_le h, List.take_length]
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
51
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
52
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
53
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
54
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
55
- {s : State 32} {x : M} (hs : Rel c p s x) :
 
 
56
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
57
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
58
  cases hi : p[s.pc]? with
@@ -65,43 +85,48 @@ theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
65
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
66
  · omega
67
  obtain ⟨f0, _⟩ := lowerProg_stub L p
68
- have hpc : x.pc = offs p p.length := by rw [hs.2, offs_ge hge]
 
69
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
70
  | some i =>
71
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
72
  rw [hst]
73
- exact sim_exec hg hL hMs hLd hLr hLa hLal hsz hs hi (fun r hr => hreg s.pc i hi r hr)
74
 
75
  /-- Whole-program preservation, with no capacity hypothesis: the Thumb-2 code reaches the IR
76
  outcome, or exits with `overflow` because a stack was full. -/
77
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
78
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
79
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
80
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
81
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
82
- ∀ {x : M}, Rel c p s x →
83
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
84
  induction h with
85
  | @halt s s' hst =>
86
- intro x hs
87
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
88
  rw [hst] at this
89
  rcases this with this | ⟨_, h6⟩
90
  · exact .inl this
91
  · exact .inr h6
92
  | @trap s t hst =>
93
- intro x hs
94
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
95
  rw [hst] at this
96
  rcases this with this | ⟨_, h6⟩
97
  · exact .inl this
98
  · exact .inr h6
99
  | @next s s' o hst _ ih =>
100
- intro x hs
101
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
102
  rw [hst] at this
103
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
104
- · rcases ih hrel with hih | h6
105
  · left
106
  cases o with
107
  | next _ => exact hih.elim
@@ -117,31 +142,35 @@ every reachable state), no overflow guard fires and the outcome is exactly the I
117
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
118
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
119
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
120
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
121
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
122
- ∀ {x : M}, Rel c p s x → (∀ s', Steps p s s' → Fits c s') →
123
  Final c p (lowerProg L p) x o := by
124
  induction h with
125
  | @halt s s' hst =>
126
- intro x hs hb
127
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
128
  rw [hst] at this
129
  rcases this with this | ⟨hnf, _⟩
130
  · exact this
131
  · exact absurd (hb s .refl) hnf
132
  | @trap s t hst =>
133
- intro x hs hb
134
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
135
  rw [hst] at this
136
  rcases this with this | ⟨hnf, _⟩
137
  · exact this
138
  · exact absurd (hb s .refl) hnf
139
  | @next s s' o hst _ ih =>
140
- intro x hs hb
141
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
142
  rw [hst] at this
143
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
144
- · have hih := ih hrel (fun s'' hss => hb s'' (Steps.cons hst hss))
145
  cases o with
146
  | next _ => exact hih.elim
147
  | halted r5 =>
@@ -159,7 +188,7 @@ theorem init_rel {c : Cfg} {p : Prog 32} {s0 : State 32} {x0 : M} (hg : Geom c)
159
  (h13 : x0.regs Reg.r6 = ofN c.mb) (h12 : x0.regs Reg.r7 = ofN c.sp0)
160
  (hsp : x0.regs Reg.r8 = ofN c.sp0) (hbp : x0.regs Reg.r9 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
161
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
162
- (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs p s0.pc) : Rel c p s0 x0 :=
163
  ⟨{ r4 := by simpa [hd] using h15
164
  r5 := h14
165
  r6 := h13
 
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
28
+ * `hLf`, `hok`, `I` the code was lowered with the configuration's facts: its lower-bound
29
+ certificate passes `certOk`, and its upper bound `c.ub` is implied by an
30
+ invariant `I` kept by every step within the data stack's capacity (`hIs`,
31
+ `hIb`; `WordDialect.UbSound`); the runs carry `DepthInv` and `I`, so every
32
+ underflow or overflow guard the lowering left out would have passed;
33
  * `hsz` code indices fit in 32 bits;
34
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
35
  -/
 
49
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
50
  | .trapped t => RExec code x (.trapped t)
51
 
52
+ theorem offs_ge (cf : Nat → Facts) {p : Prog 32} {k : Nat} (h : p.length ≤ k) :
53
+ offs cf p k = offs cf p p.length := by
54
+ induction p generalizing cf k with
55
+ | nil => cases k <;> simp [offs]
56
+ | cons i is ih =>
57
+ cases k with
58
+ | zero => simp at h
59
+ | succ k => simp only [List.length_cons, offs]; rw [ih _ (by simp at h; omega)]
60
+
61
+ /-- A related state is within the data stack's capacity. -/
62
+ theorem cap_of_rel {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hs : Rel c p s x) :
63
+ s.dstack.length ≤ c.dCap := by
64
+ have := hs.1.capD
65
+ unfold Cfg.dCap
66
+ omega
67
 
68
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
69
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
70
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
71
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
72
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
73
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
74
+ {s : State 32} {x : M} (hs : Rel c p s x) (hdi : DepthInv c.cert s)
75
+ (hub : s.dstack.length ≤ c.ub s.pc) :
76
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
77
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
78
  cases hi : p[s.pc]? with
 
85
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
86
  · omega
87
  obtain ⟨f0, _⟩ := lowerProg_stub L p
88
+ rw [hLf] at f0
89
+ have hpc : x.pc = offs c.facts p p.length := by rw [hs.2, offs_ge _ hge]
90
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
91
  | some i =>
92
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
93
  rw [hst]
94
+ exact sim_exec hg hL hMs hLd hLr hLa hLal hLf hsz hs hdi.depth hub hi (fun r hr => hreg s.pc i hi r hr)
95
 
96
  /-- Whole-program preservation, with no capacity hypothesis: the Thumb-2 code reaches the IR
97
  outcome, or exits with `overflow` because a stack was full. -/
98
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
99
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
100
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
101
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
102
+ {I : State 32 → Prop}
103
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
104
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
105
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
106
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
107
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s →
108
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
109
  induction h with
110
  | @halt s s' hst =>
111
+ intro x hs hdi hbi
112
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
113
  rw [hst] at this
114
  rcases this with this | ⟨_, h6⟩
115
  · exact .inl this
116
  · exact .inr h6
117
  | @trap s t hst =>
118
+ intro x hs hdi hbi
119
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
120
  rw [hst] at this
121
  rcases this with this | ⟨_, h6⟩
122
  · exact .inl this
123
  · exact .inr h6
124
  | @next s s' o hst _ ih =>
125
+ intro x hs hdi hbi
126
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
127
  rw [hst] at this
128
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
129
+ · rcases ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) with hih | h6
130
  · left
131
  cases o with
132
  | next _ => exact hih.elim
 
142
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
143
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
144
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
145
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
146
+ {I : State 32 → Prop}
147
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
148
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
149
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
150
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
151
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s → (∀ s', Steps p s s' → Fits c s') →
152
  Final c p (lowerProg L p) x o := by
153
  induction h with
154
  | @halt s s' hst =>
155
+ intro x hs hdi hbi hb
156
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
157
  rw [hst] at this
158
  rcases this with this | ⟨hnf, _⟩
159
  · exact this
160
  · exact absurd (hb s .refl) hnf
161
  | @trap s t hst =>
162
+ intro x hs hdi hbi hb
163
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
164
  rw [hst] at this
165
  rcases this with this | ⟨hnf, _⟩
166
  · exact this
167
  · exact absurd (hb s .refl) hnf
168
  | @next s s' o hst _ ih =>
169
+ intro x hs hdi hbi hb
170
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
171
  rw [hst] at this
172
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
173
+ · have hih := ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) (fun s'' hss => hb s'' (Steps.cons hst hss))
174
  cases o with
175
  | next _ => exact hih.elim
176
  | halted r5 =>
 
188
  (h13 : x0.regs Reg.r6 = ofN c.mb) (h12 : x0.regs Reg.r7 = ofN c.sp0)
189
  (hsp : x0.regs Reg.r8 = ofN c.sp0) (hbp : x0.regs Reg.r9 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
190
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
191
+ (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs c.facts p s0.pc) : Rel c p s0 x0 :=
192
  ⟨{ r4 := by simpa [hd] using h15
193
  r5 := h14
194
  r6 := h13
backend/cortexm/CM/Emit.lean CHANGED
@@ -25,13 +25,14 @@ is linked to RAM with its load address in flash. There is no operating system. T
25
  The rest of the runtime (`epilogue`) is hand-written assembly. It
26
  * implements `exitHalt` as: write `depth`, the data stack, IR memory and the virtual register
27
  file to the UART (a PL011, UART0 of the Stellaris LM3S6965 at `uartBase`, polling its
28
- transmit-full flag), one word per line as eight hexadecimal digits, then stop with status 0,
29
- * implements `exitTrap t` as stopping with status `code t`, and `exitOvf` (stack overflow) with
30
  status 6.
31
 
32
- The machine is stopped through semihosting (`bkpt 0xab`, operation `SYS_EXIT_EXTENDED`), which
33
- the emulator and debug probes implement; on a board running without a debugger, that one stub is
34
- replaced by whatever signals the end of a run. The lowered code itself uses no device.
 
35
  -/
36
 
37
  namespace WordDialect
@@ -150,7 +151,8 @@ def body (code : List (Instr Nat)) : String :=
150
  /-- Data-stack placement (`capacity` words ending at `dEnd`), return-stack placement (`rcap`
151
  entries ending at `rEnd`), IR memory image, register-file size, auxiliary-stack placement
152
  (`acap` words ending at `aEnd`), the initial stack pointer of the vector table (used only by
153
- exception entry; the lowered code does not use `sp`), and the address of the PL011 UART. The three stacks
 
154
  are sections the linker places at fixed addresses (`cmc` uses a linker script). -/
155
  structure Runtime where
156
  dEnd : Nat
@@ -163,6 +165,16 @@ structure Runtime where
163
  acap : Nat
164
  spInit : Nat := 0x20010000
165
  uartBase : Nat := 0x4000C000
 
 
 
 
 
 
 
 
 
 
166
 
167
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
168
 
@@ -170,11 +182,15 @@ def Runtime.rBase (r : Runtime) : Nat := r.rEnd - 4 * r.rcap
170
 
171
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
172
 
 
 
 
173
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
174
  def Runtime.layout (r : Runtime) : Layout :=
175
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
176
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
177
- aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4) }
 
178
 
179
  /-- Assembler directives and the vector table: initial stack pointer and reset vector. -/
180
  def vectors (r : Runtime) : String :=
@@ -182,7 +198,7 @@ def vectors (r : Runtime) : String :=
182
  s!"\t.word {hex r.spInit}\n\t.word _start\n"
183
 
184
  /-- The `.data` image: IR memory, the register file (`nregs + 1` words) and the two-word
185
- semihosting parameter block, in the order `epilogue` lays them out. The image is linked into
186
  flash and copied to RAM at reset. -/
187
  def dataImage (r : Runtime) : List Nat := r.memImage ++ List.replicate (r.nregs + 3) 0
188
 
@@ -212,11 +228,43 @@ def prologue (r : Runtime) : String :=
212
  s!"\t{li "r7" r.rEnd}\n\tmov r8, r7\n\t{la "r6" "irmem"}\n\t{la "r5" "regfile"}\n" ++
213
  s!"\t{li "r4" r.dEnd}\n\t{li "r9" r.aEnd}\n"
214
 
215
- /-- Output and exit routines, entered only from `exitHalt`, `exitTrap` and `exitOvf`, so they
216
- may use any register. `putc` writes `r3` to the UART; `putw` writes `r0` as eight hexadecimal
217
- digits and a newline; `putws` writes the `r9` words at address `r7`. `.Lexit` stops the machine
218
- through semihosting with status `r1`. -/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  def devices (r : Runtime) : String :=
 
220
  "\t.thumb_func\nputc:\n" ++
221
  s!"\t{li "r12" r.uartBase}\n" ++
222
  "1:\tldr r11, [r12, #0x18]\n\ttst r11, #0x20\n\tbne 1b\n\tstr r3, [r12]\n\tbx lr\n" ++
@@ -227,15 +275,13 @@ def devices (r : Runtime) : String :=
227
  "\t.thumb_func\nputws:\n\tmov r8, lr\n" ++
228
  "5:\tcmp r9, #0\n\tbeq 6f\n\tldr r0, [r7], #4\n\tbl putw\n\tsubs r9, r9, #1\n\tb 5b\n" ++
229
  "6:\tbx r8\n" ++
230
- s!".Lexit:\n\t{la "r0" "exitblk"}\n\t{li "r2" 0x20026}\n" ++
231
- "\tstr r2, [r0]\n\tstr r1, [r0, #4]\n\tmov r1, r0\n\tmovs r0, #0x20\n\tbkpt 0xab\n7:\tb 7b\n"
 
 
232
 
233
- /-- Turn on UART0: its clock (`RCGC1`, bit 0, in the Stellaris system control block) and the
234
- UART with its transmitter (`UARTCTL = UARTEN | TXE | RXE`). The baud rate is left at its reset
235
- divisor; the emulator ignores it. -/
236
- def uartOn (r : Runtime) : String :=
237
- s!"\t{li "r12" 0x400FE104}\n\tldr r11, [r12]\n\torr r11, r11, #1\n\tstr r11, [r12]\n" ++
238
- s!"\t{li "r12" r.uartBase}\n\tmovw r11, #0x301\n\tstr r11, [r12, #0x30]\n"
239
 
240
  def epilogue (r : Runtime) : String :=
241
  let m := r.memImage.length
@@ -244,7 +290,7 @@ def epilogue (r : Runtime) : String :=
244
  "\tmov r7, r4\n\tbl putws\n" ++
245
  s!"\t{la "r7" "irmem"}\n\t{li "r9" m}\n\tbl putws\n" ++
246
  s!"\t{la "r7" "regfile"}\n\t{li "r9" r.nregs}\n\tbl putws\n" ++
247
- "\tmovs r1, #0\n\tb .Lexit\n" ++
248
  String.join ((List.range 6).map fun k => s!".Ltrap{k + 1}:\n\tmovs r1, #{k + 1}\n\tb .Lexit\n") ++
249
  devices r ++ "\t.ltorg\n" ++
250
  "\t.data\n\t.balign 4\nirmem:\n" ++
 
25
  The rest of the runtime (`epilogue`) is hand-written assembly. It
26
  * implements `exitHalt` as: write `depth`, the data stack, IR memory and the virtual register
27
  file to the UART (a PL011, UART0 of the Stellaris LM3S6965 at `uartBase`, polling its
28
+ transmit-full flag), one word per line as eight hexadecimal digits, then end with status 0,
29
+ * implements `exitTrap t` as ending with status `code t`, and `exitOvf` (stack overflow) with
30
  status 6.
31
 
32
+ A run ends on the UART, the same way on the emulator and on a board, with no debugger: after
33
+ the dump (if any) the runtime prints a line `EXIT` and the status, stores the status at `exitblk`,
34
+ and sleeps. Before printing it sets up the clock and UART0 as a board needs (`uartInit`). The
35
+ lowered code itself uses no device.
36
  -/
37
 
38
  namespace WordDialect
 
151
  /-- Data-stack placement (`capacity` words ending at `dEnd`), return-stack placement (`rcap`
152
  entries ending at `rEnd`), IR memory image, register-file size, auxiliary-stack placement
153
  (`acap` words ending at `aEnd`), the initial stack pointer of the vector table (used only by
154
+ exception entry; the lowered code does not use `sp`), the address of the PL011 UART, and the
155
+ clock and baud rate its divisor is computed from. The three stacks
156
  are sections the linker places at fixed addresses (`cmc` uses a linker script). -/
157
  structure Runtime where
158
  dEnd : Nat
 
165
  acap : Nat
166
  spInit : Nat := 0x20010000
167
  uartBase : Nat := 0x4000C000
168
+ /-- System clock the UART divisor is computed from: the 8 MHz crystal of the EK-LM3S6965. -/
169
+ clockHz : Nat := 8000000
170
+ baud : Nat := 115200
171
+ /-- The stack-depth certificate the code is lowered with (`WordDialect.Depth`); the driver
172
+ passes `safeCert` of the program. The default claims nothing and keeps every guard. -/
173
+ cert : Nat → Nat := fun _ => 0
174
+ /-- The upper bound on the data-stack depth the code is lowered with; the driver passes
175
+ `upperTable` of the program against `dCap` (`WordDialect.Depth`). An overflow guard is left out
176
+ where `ub k + 1 ≤ dCap`; the default (`2^32` everywhere) shows no room, so every guard stays. -/
177
+ ub : Nat → Nat := fun _ => 2 ^ 32
178
 
179
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
180
 
 
182
 
183
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
184
 
185
+ /-- The data stack's capacity in words. -/
186
+ def Runtime.dCap (r : Runtime) : Nat := (r.dEnd - r.dBase) / 4
187
+
188
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
189
  def Runtime.layout (r : Runtime) : Layout :=
190
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
191
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
192
+ aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4), cert := r.cert,
193
+ ub := r.ub, dCap := r.dCap }
194
 
195
  /-- Assembler directives and the vector table: initial stack pointer and reset vector. -/
196
  def vectors (r : Runtime) : String :=
 
198
  s!"\t.word {hex r.spInit}\n\t.word _start\n"
199
 
200
  /-- The `.data` image: IR memory, the register file (`nregs + 1` words) and the two-word
201
+ status block `exitblk`, in the order `epilogue` lays them out. The image is linked into
202
  flash and copied to RAM at reset. -/
203
  def dataImage (r : Runtime) : List Nat := r.memImage ++ List.replicate (r.nregs + 3) 0
204
 
 
228
  s!"\t{li "r7" r.rEnd}\n\tmov r8, r7\n\t{la "r6" "irmem"}\n\t{la "r5" "regfile"}\n" ++
229
  s!"\t{li "r4" r.dEnd}\n\t{li "r9" r.aEnd}\n"
230
 
231
+ /-- The UART divisor for `baud` at `clockHz`: 64 × the PL011's `clock / (16 baud)`, rounded,
232
+ split into the integer (`IBRD`) and fractional (`FBRD`) parts. -/
233
+ def Runtime.divisor (r : Runtime) : Nat × Nat :=
234
+ let d := (r.clockHz * 4 + r.baud / 2) / r.baud
235
+ (d / 64, d % 64)
236
+
237
+ /-- Bring up UART0 as a board needs it (the emulator needs none of it): run the system clock
238
+ from the main oscillator with the 8 MHz crystal (as StellarisWare's `SysCtlClockSet` with
239
+ `SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ` does: `RCC.MOSCDIS = 0`, `OSCSRC = main`,
240
+ `XTAL = 8 MHz`), wait for it, clock UART0 and GPIO port A, give PA0/PA1 to the UART, and set
241
+ `baud` 8N1. Uses `r10 … r12`. -/
242
+ def uartInit (r : Runtime) : String :=
243
+ let (ib, fb) := r.divisor
244
+ "\t.thumb_func\nuart_init:\n" ++
245
+ s!"\t{li "r12" 0x400FE060}\n\tldr r11, [r12]\n\t{li "r10" 0x3F1}\n\tbic r11, r11, r10\n" ++
246
+ "\torr r11, r11, #0x380\n\tstr r11, [r12]\n" ++
247
+ "\tmovw r11, #0x8000\n9:\tsubs r11, r11, #1\n\tbne 9b\n" ++
248
+ s!"\t{li "r12" 0x400FE104}\n\tldr r11, [r12]\n\torr r11, r11, #1\n\tstr r11, [r12]\n" ++
249
+ s!"\t{li "r12" 0x400FE108}\n\tldr r11, [r12]\n\torr r11, r11, #1\n\tstr r11, [r12]\n" ++
250
+ "\tnop\n\tnop\n\tnop\n" ++
251
+ s!"\t{li "r12" 0x40004000}\n\tldr r11, [r12, #0x420]\n\torr r11, r11, #3\n\tstr r11, [r12, #0x420]\n" ++
252
+ "\tldr r11, [r12, #0x51C]\n\torr r11, r11, #3\n\tstr r11, [r12, #0x51C]\n" ++
253
+ s!"\t{li "r12" r.uartBase}\n\tmovs r11, #0\n\tstr r11, [r12, #0x30]\n" ++
254
+ s!"\tmovw r11, #{ib}\n\tstr r11, [r12, #0x24]\n\tmovw r11, #{fb}\n\tstr r11, [r12, #0x28]\n" ++
255
+ "\tmovs r11, #0x60\n\tstr r11, [r12, #0x2C]\n\tmovw r11, #0x301\n\tstr r11, [r12, #0x30]\n" ++
256
+ "\tbx lr\n"
257
+
258
+ /-- Output and end-of-run routines, entered only from `exitHalt`, `exitTrap` and `exitOvf`, so
259
+ they may use any register. `putc` writes `r3` to the UART; `putw` writes `r0` as eight
260
+ hexadecimal digits and a newline; `putws` writes the `r9` words at address `r7`.
261
+
262
+ The end of a run (`.Lexit` with the status in `r1`, entered with the UART not yet set up;
263
+ `.Lfinish` with it set up) needs no debugger: the status goes to the two words at `exitblk`
264
+ (the status and the marker `0xE0D0F1A1`, for a debugger that wants to read it), then the UART
265
+ gets the line `EXIT` and the status as a word line, and the core sleeps (`wfi`) for good. -/
266
  def devices (r : Runtime) : String :=
267
+ uartInit r ++
268
  "\t.thumb_func\nputc:\n" ++
269
  s!"\t{li "r12" r.uartBase}\n" ++
270
  "1:\tldr r11, [r12, #0x18]\n\ttst r11, #0x20\n\tbne 1b\n\tstr r3, [r12]\n\tbx lr\n" ++
 
275
  "\t.thumb_func\nputws:\n\tmov r8, lr\n" ++
276
  "5:\tcmp r9, #0\n\tbeq 6f\n\tldr r0, [r7], #4\n\tbl putw\n\tsubs r9, r9, #1\n\tb 5b\n" ++
277
  "6:\tbx r8\n" ++
278
+ ".Lexit:\n\tmov r6, r1\n\tbl uart_init\n\tmov r1, r6\n" ++
279
+ s!".Lfinish:\n\tmov r6, r1\n\t{la "r0" "exitblk"}\n\tstr r1, [r0]\n\t{li "r2" 0xE0D0F1A1}\n\tstr r2, [r0, #4]\n" ++
280
+ String.join ("EXIT\n".toList.map fun ch => s!"\tmovs r3, #{ch.toNat}\n\tbl putc\n") ++
281
+ "\tmov r0, r6\n\tbl putw\n7:\twfi\n\tb 7b\n"
282
 
283
+ /-- Set up the UART for the halt dump. -/
284
+ def uartOn (_r : Runtime) : String := "\tbl uart_init\n"
 
 
 
 
285
 
286
  def epilogue (r : Runtime) : String :=
287
  let m := r.memImage.length
 
290
  "\tmov r7, r4\n\tbl putws\n" ++
291
  s!"\t{la "r7" "irmem"}\n\t{li "r9" m}\n\tbl putws\n" ++
292
  s!"\t{la "r7" "regfile"}\n\t{li "r9" r.nregs}\n\tbl putws\n" ++
293
+ "\tmovs r1, #0\n\tb .Lfinish\n" ++
294
  String.join ((List.range 6).map fun k => s!".Ltrap{k + 1}:\n\tmovs r1, #{k + 1}\n\tb .Lexit\n") ++
295
  devices r ++ "\t.ltorg\n" ++
296
  "\t.data\n\t.balign 4\nirmem:\n" ++
backend/cortexm/CM/Guard.lean CHANGED
@@ -40,7 +40,7 @@ theorem uf_cond {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hg : Geom c) (hs
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
- theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
@@ -62,19 +62,38 @@ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Ins
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
- /-- Too few operands: the guard exits with `stackUnderflow`. -/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
67
- {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
68
- (hn : 0 < n) (hn3 : n ≤ 3) (hk : s.dstack.length < n) (hpc : x.pc = base)
69
- (hat : RAt code base (uf L n base)) : RExec code x (.trapped .stackUnderflow) := by
70
- rw [uf_eq L hn] at hat
 
 
71
  obtain ⟨h1, h2, h3, _⟩ := hat
72
- let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 * n))
73
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
74
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
75
  have hholds : Cond.eval .ule (xa.regs r4) (xa.regs r0) = false := by
76
- have := uf_cond hg hs hL hn hn3
77
- have h : ¬ n ≤ s.dstack.length := by omega
78
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
79
  exact RExec.of_steps (RSteps.single hst1)
80
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
@@ -131,6 +150,29 @@ theorem ovfD_trap (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase
131
  rw [hra r4 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
132
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
135
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
136
  Cond.eval .uge (x.regs Reg.r8) (x.regs Reg.r7 - L.rGap) =
 
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
+ theorem uf_pass_pos {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
 
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
+ /-- The guard of an instruction popping `k` words, when the data stack is known to hold at least
66
+ `g` words: with enough operands it falls through, to `base + ufSize (need g k)` (at once when the
67
+ certificate made the guard empty). -/
68
+ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
69
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
70
+ (hL : L.dEnd = ofN c.dEnd) (hk3 : k ≤ 3) (hk : k ≤ s.dstack.length) (hpc : x.pc = base)
71
+ (hat : RAt code base (uf L (need g k) base)) :
72
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ufSize (need g k) ∧ x1.mem = x.mem ∧
73
+ (∀ r, r ≠ r0 → x1.regs r = x.regs r) := by
74
+ by_cases h0 : need g k = 0
75
+ · rw [h0]; exact ⟨x, .refl, hs, by simp [ufSize, hpc], rfl, fun _ _ => rfl⟩
76
+ · have hn : 0 < need g k := Nat.pos_of_ne_zero h0
77
+ have hle := need_le g k
78
+ obtain ⟨x1, a, b, hpc1, d, e⟩ := uf_pass_pos hg hs hL hn (by omega) (by omega) hpc hat
79
+ exact ⟨x1, a, b, by rw [hpc1, ufSize_pos hn], d, e⟩
80
+
81
+ /-- Too few operands: the guard exits with `stackUnderflow`. It is there, because the depth
82
+ certificate's bound `g.lo` is a true lower bound (`hgd`) and the stack holds fewer than `k` words. -/
83
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
84
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
85
+ (hL : L.dEnd = ofN c.dEnd) (hk0 : 0 < k) (hk3 : k ≤ 3) (hgd : g.lo ≤ s.dstack.length) (hk : s.dstack.length < k)
86
+ (hpc : x.pc = base) (hat : RAt code base (uf L (need g k) base)) :
87
+ RExec code x (.trapped .stackUnderflow) := by
88
+ rw [need_of_lt (by omega)] at hat
89
+ rw [uf_eq L hk0] at hat
90
  obtain ⟨h1, h2, h3, _⟩ := hat
91
+ let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 * k))
92
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
93
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
94
  have hholds : Cond.eval .ule (xa.regs r4) (xa.regs r0) = false := by
95
+ have := uf_cond hg hs hL hk0 hk3
96
+ have h : ¬ k ≤ s.dstack.length := by omega
97
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
98
  exact RExec.of_steps (RSteps.single hst1)
99
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
 
150
  rw [hra r4 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
151
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
152
 
153
+ /-- The data-stack guard where the facts keep it: with room for one more word, it falls through
154
+ to `base + ovfSize g` (at once when the bound left the guard out). -/
155
+ theorem ovfG_pass {g : Facts} (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase + 4))
156
+ (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) (hpc : x.pc = base)
157
+ (hat : RAt code base (ovf L g base)) :
158
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ovfSize g ∧ x1.mem = x.mem ∧
159
+ (∀ r, r ≠ r0 → x1.regs r = x.regs r) := by
160
+ unfold ovf at hat
161
+ unfold ovfSize
162
+ cases hn : g.noOvf
163
+ · simp only [hn, Bool.false_eq_true, if_false] at hat ⊢
164
+ exact ovfD_pass hg hs hLd hfit hpc hat
165
+ · exact ⟨x, .refl, hs, by simp [hpc], rfl, fun _ _ => rfl⟩
166
+
167
+ /-- Data stack full: the guard is there (the bound did not claim room) and exits with
168
+ `overflow`. -/
169
+ theorem ovfG_trap {g : Facts} (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x)
170
+ (hLd : L.dLim = ofN (c.dBase + 4)) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd)
171
+ (hpc : x.pc = base) (hat : RAt code base (ovf L g base)) : RExec code x .overflow := by
172
+ unfold ovf at hat
173
+ simp only [hn, Bool.false_eq_true, if_false] at hat
174
+ exact ovfD_trap hg hs hLd h hpc hat
175
+
176
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
177
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
178
  Cond.eval .uge (x.regs Reg.r8) (x.regs Reg.r7 - L.rGap) =
backend/cortexm/CM/Init.lean CHANGED
@@ -34,7 +34,9 @@ flash only (`copy_holds`, `boot_correct`).
34
 
35
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
36
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
37
- only about the program.
 
 
38
  -/
39
 
40
  namespace WordDialect
@@ -51,7 +53,8 @@ structure Loader where
51
  /-- The runtime placement for one run, as a `Cfg`. -/
52
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
53
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
54
- M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase }
 
55
 
56
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
57
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
@@ -76,36 +79,38 @@ theorem prologue_run (r : Runtime) (ld : Loader) (x0 : M) :
76
  .next { entryState r ld x0 with pc := x0.pc + 6 } := by
77
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
78
 
79
- theorem isize_le (i : WordDialect.Instr 32) : isize i ≤ 17 := by
80
- cases i <;> simp [isize, ufSize]
81
-
82
- theorem sum_isize_le : ∀ l : Prog 32, (l.map isize).sum ≤ 17 * l.length
83
- | [] => by simp
84
- | i :: l => by
85
- have := isize_le i
86
- have := sum_isize_le l
87
- simp only [List.map_cons, List.sum_cons, List.length_cons]
 
 
 
 
88
  omega
89
 
90
  /-- Code indices are bounded by the program length. -/
91
- theorem offs_lt {p : Prog 32} (h : 17 * p.length < 2 ^ 32) (k : Nat) : offs p k < 2 ^ 32 := by
92
- have h1 := sum_isize_le (p.take k)
93
- have h2 : (p.take k).length ≤ p.length := by rw [List.length_take]; omega
94
- simp only [offs]
95
- omega
96
 
97
  theorem layout_ok (r : Runtime) (ld : Loader) :
98
- r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
99
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
100
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
101
- ⟨rfl, rfl, rfl, rfl, rfl, rfl⟩
102
 
103
  /-- After the prologue, the machine is related to the IR's initial state. -/
104
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
105
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
106
  have hg := h.geom
107
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
108
- ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init])
109
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
110
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
111
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
@@ -126,14 +131,17 @@ theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p :
126
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
127
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
128
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 17 * p.length < 2 ^ 32)
129
- (hreg : RegsOk (cfgOf r ld) p) {o : Outcome 32}
 
130
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
131
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 6 } ∧
132
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
133
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
134
- obtain ⟨hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
 
135
  exact ⟨prologue_run r ld x0,
136
- lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal (offs_lt hlen) hreg hx (entry_rel r ld h p)⟩
 
137
 
138
  end Emit
139
  end CM
 
34
 
35
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
36
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
37
+ only about the program, including `certOk` for the runtime's stack-depth certificate and
38
+ `UbSound` for its upper bound (the lowering leaves out the underflow and overflow guards they
39
+ cover).
40
  -/
41
 
42
  namespace WordDialect
 
53
  /-- The runtime placement for one run, as a `Cfg`. -/
54
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
55
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
56
+ M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase,
57
+ cert := r.cert, ub := r.ub }
58
 
59
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
60
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
 
79
  .next { entryState r ld x0 with pc := x0.pc + 6 } := by
80
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
81
 
82
+ theorem isize_le (g : Facts) (i : WordDialect.Instr 32) : isize g i ≤ 17 := by
83
+ have hu : ∀ k, ufSize (need g k) ≤ 3 := fun k => by unfold ufSize; split <;> omega
84
+ have hv : ovfSize g ≤ 3 := by unfold ovfSize; split <;> omega
85
+ have h1 := hu 1; have h2 := hu 2; have h3 := hu 3
86
+ cases i <;> simp only [isize] <;> omega
87
+
88
+ theorem offs_le (cf : Nat → Facts) : ∀ (p : Prog 32) (k : Nat), offs cf p k ≤ 17 * p.length
89
+ | [], k => by cases k <;> simp [offs]
90
+ | i :: l, 0 => by simp [offs]
91
+ | i :: l, k + 1 => by
92
+ have := isize_le (cf 0) i
93
+ have := offs_le (fun j => cf (j + 1)) l k
94
+ simp only [offs, List.length_cons]
95
  omega
96
 
97
  /-- Code indices are bounded by the program length. -/
98
+ theorem offs_lt (cf : Nat → Facts) {p : Prog 32} (h : 17 * p.length < 2 ^ 32) (k : Nat) :
99
+ offs cf p k < 2 ^ 32 :=
100
+ Nat.lt_of_le_of_lt (offs_le cf p k) h
 
 
101
 
102
  theorem layout_ok (r : Runtime) (ld : Loader) :
103
+ r.layout.facts = (cfgOf r ld).facts ∧ r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
104
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
105
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
106
+ ⟨funext fun _ => rfl, rfl, rfl, rfl, rfl, rfl, rfl⟩
107
 
108
  /-- After the prologue, the machine is related to the IR's initial state. -/
109
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
110
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
111
  have hg := h.geom
112
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
113
+ ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init, offs_zero])
114
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
115
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
116
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
 
131
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
132
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
133
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 17 * p.length < 2 ^ 32)
134
+ (hreg : RegsOk (cfgOf r ld) p) (hok : certOk p r.cert = true)
135
+ (hub : UbSound p r.dCap r.ub) {o : Outcome 32}
136
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
137
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 6 } ∧
138
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
139
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
140
+ obtain ⟨hLc, hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
141
+ obtain ⟨I, hI0, hIs, hIb⟩ := hub
142
  exact ⟨prologue_run r ld x0,
143
+ lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal hLc hok hIs hIb (offs_lt _ hlen)
144
+ hreg hx (entry_rel r ld h p) (DepthInv.init (certOk_entry hok) _) (hI0 _)⟩
145
 
146
  end Emit
147
  end CM
backend/cortexm/CM/Isa.lean CHANGED
@@ -38,7 +38,7 @@ Scope and trust boundary:
38
  * `exitHalt` / `exitTrap t` stand for the runtime stubs that dump state and stop the machine;
39
  they are terminal here. `exitOvf` is the stub for a stack-overflow guard (status 6); it has no
40
  IR counterpart, since IR stacks are unbounded. There is no operating system: the stubs talk to
41
- a UART and stop the machine through semihosting (`CM.Emit`).
42
 
43
  That the model matches the hardware is the stated assumption of this backend; `cmc` tests it by
44
  running the emitted code on an emulated Cortex-M3 board (`qemu-system-arm -M lm3s6965evb`).
 
38
  * `exitHalt` / `exitTrap t` stand for the runtime stubs that dump state and stop the machine;
39
  they are terminal here. `exitOvf` is the stub for a stack-overflow guard (status 6); it has no
40
  IR counterpart, since IR stacks are unbounded. There is no operating system: the stubs talk to
41
+ a UART and end the run there (`CM.Emit`).
42
 
43
  That the model matches the hardware is the stated assumption of this backend; `cmc` tests it by
44
  running the emitted code on an emulated Cortex-M3 board (`qemu-system-arm -M lm3s6965evb`).
backend/cortexm/CM/Lower.lean CHANGED
@@ -1,4 +1,5 @@
1
  import CM.Isa
 
2
 
3
  /-!
4
  # CM.Lower
@@ -49,6 +50,24 @@ structure Layout where
49
  rGap : W -- `4 rcap - 8`: a call has room iff `r8 ≥ r7 - rGap`
50
  aEnd : W -- empty auxiliary stack: `r9 = aEnd`
51
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `r9 ≥ aLim`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  /-- Stack-underflow guard for `k` operands: continue when `r4 ≤ dEnd - 4k`. -/
54
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
@@ -58,10 +77,25 @@ def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
58
 
59
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
60
 
 
 
 
 
 
 
 
 
 
61
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
62
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
63
  [.movImm r0 L.dLim, .bcc .uge r4 r0 (base + 3), .exitOvf]
64
 
 
 
 
 
 
 
65
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
66
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
67
  [.movRR r0 r7, .movImm r1 L.rGap, .sub r0 r1, .bcc .uge r8 r0 (base + 5), .exitOvf]
@@ -75,131 +109,144 @@ def emptyA (L : Layout) (base : Nat) : List (Instr Nat) :=
75
  [.movImm r0 L.aEnd, .bcc .ne r9 r0 (base + 3), .exitTrap .returnUnderflow]
76
 
77
  /-- Code size of one IR instruction. -/
78
- def isize : WordDialect.Instr 32 → Nat
79
- | .word _ | .ptr _ => 6
80
- | .load => ufSize 1 + 8
81
- | .store => ufSize 2 + 9
82
- | .add | .sub | .mul | .and | .or | .xor => ufSize 2 + 5
83
- | .div | .sdiv => ufSize 2 + 7
84
- | .not => ufSize 1 + 3
85
- | .shl | .shr => ufSize 2 + 8
86
- | .rotl => ufSize 2 + 6
87
- | .rotr => ufSize 2 + 5
88
- | .cmp _ => ufSize 2 + 7
89
- | .select => ufSize 3 + 7
90
  | .jmp _ => 1
91
- | .branch _ => ufSize 1 + 3
92
  | .call _ => 6
93
  | .ret => 3
94
- | .push _ => 6
95
- | .pop _ => ufSize 1 + 3
96
- | .dup => ufSize 1 + 6
97
- | .drop => ufSize 1 + 1
98
- | .swap => ufSize 2 + 4
99
- | .over => ufSize 2 + 6
100
- | .rot => ufSize 3 + 6
101
- | .tor => ufSize 1 + 7
102
- | .fromr => 10
103
- | .rfetch => 9
104
  | .halt => 1
105
 
106
  /-- Code for one IR instruction placed at code index `base`; `off t` is the code index of IR
107
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
108
- def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) : WordDialect.Instr 32 → List (Instr Nat)
109
- | .word w => ovfD L base ++ [.movImm r0 w, .addImm r4 (-4), .store r4 0 r0]
110
- | .ptr p => ovfD L base ++ [.movImm r0 p.toWord, .addImm r4 (-4), .store r4 0 r0]
 
111
  | .load =>
112
- let b0 := base + ufSize 1
113
- uf L 1 base ++
114
  [.load r0 r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r1 (b0 + 4),
115
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r6, .load r0 r0 0, .store r4 0 r0]
116
  | .store =>
117
- let b0 := base + ufSize 2
118
- uf L 2 base ++
119
  [.load r0 r4 0, .load r1 r4 4, .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (b0 + 5),
120
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r6, .store r0 0 r1, .addImm r4 8]
121
- | .add => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .add r0 r1, .store r4 4 r0, .addImm r4 4]
122
- | .sub => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .sub r0 r1, .store r4 4 r0, .addImm r4 4]
123
- | .mul => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .mul r0 r1, .store r4 4 r0, .addImm r4 4]
124
- | .and => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .and r0 r1, .store r4 4 r0, .addImm r4 4]
125
- | .or => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .or r0 r1, .store r4 4 r0, .addImm r4 4]
126
- | .xor => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .xor r0 r1, .store r4 4 r0, .addImm r4 4]
127
  | .div =>
128
- let b0 := base + ufSize 2
129
- uf L 2 base ++
130
  [.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero, .divu r0 r0 r1,
131
  .store r4 4 r0, .addImm r4 4]
132
  | .sdiv =>
133
- let b0 := base + ufSize 2
134
- uf L 2 base ++
135
  [.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero, .div r0 r0 r1,
136
  .store r4 4 r0, .addImm r4 4]
137
- | .not => uf L 1 base ++ [.load r0 r4 0, .not r0, .store r4 0 r0]
138
  | .shl =>
139
- uf L 2 base ++
140
  [.load r1 r4 0, .load r0 r4 4, .lsl r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
141
  .store r4 4 r0, .addImm r4 4]
142
  | .shr =>
143
- uf L 2 base ++
144
  [.load r1 r4 0, .load r0 r4 4, .lsr r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
145
  .store r4 4 r0, .addImm r4 4]
146
  | .rotl =>
147
- uf L 2 base ++
148
  [.load r1 r4 0, .load r0 r4 4, .neg r1, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
149
  | .rotr =>
150
- uf L 2 base ++
151
  [.load r1 r4 0, .load r0 r4 4, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
152
  | .cmp c =>
153
- let b0 := base + ufSize 2
154
- uf L 2 base ++
155
  [.load r1 r4 0, .load r0 r4 4, .movImm r2 1#32, .bcc c r0 r1 (b0 + 5), .movImm r2 0#32,
156
  .store r4 4 r2, .addImm r4 4]
157
  | .select =>
158
- let b0 := base + ufSize 3
159
- uf L 3 base ++
160
  [.load r1 r4 0, .load r0 r4 4, .load r3 r4 8, .beqz r1 (b0 + 5), .movRR r0 r3,
161
  .store r4 8 r0, .addImm r4 8]
162
  | .jmp t => [.jmp (off t)]
163
- | .branch t => uf L 1 base ++ [.load r0 r4 0, .addImm r4 4, .bnez r0 (off t)]
164
  | .call t => ovfR L base ++ [.call (off t)]
165
  | .ret => [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret]
166
- | .push r => ovfD L base ++ [.load r0 r5 (4 * (r : Int)), .addImm r4 (-4), .store r4 0 r0]
167
- | .pop r => uf L 1 base ++ [.load r0 r4 0, .addImm r4 4, .store r5 (4 * (r : Int)) r0]
168
  | .dup =>
169
- uf L 1 base ++ ovfD L (base + ufSize 1) ++ [.load r0 r4 0, .addImm r4 (-4), .store r4 0 r0]
170
- | .drop => uf L 1 base ++ [.addImm r4 4]
171
- | .swap => uf L 2 base ++ [.load r0 r4 0, .load r1 r4 4, .store r4 0 r1, .store r4 4 r0]
172
  | .over =>
173
- uf L 2 base ++ ovfD L (base + ufSize 2) ++ [.load r0 r4 4, .addImm r4 (-4), .store r4 0 r0]
174
  | .rot =>
175
- uf L 3 base ++
176
  [.load r0 r4 0, .load r1 r4 4, .load r2 r4 8, .store r4 0 r2, .store r4 4 r0,
177
  .store r4 8 r1]
178
  | .tor =>
179
- uf L 1 base ++ ovfA L (base + ufSize 1) ++
180
  [.load r0 r4 0, .addImm r4 4, .addImm r9 (-4), .store r9 0 r0]
181
  | .fromr =>
182
- emptyA L base ++ ovfD L (base + 3) ++
183
  [.load r0 r9 0, .addImm r9 4, .addImm r4 (-4), .store r4 0 r0]
184
  | .rfetch =>
185
- emptyA L base ++ ovfD L (base + 3) ++ [.load r0 r9 0, .addImm r4 (-4), .store r4 0 r0]
186
  | .halt => [.exitHalt]
187
 
188
- theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (i : WordDialect.Instr 32) :
189
- (lowerInstr L base off i).length = isize i := by
190
- cases i <;> simp [lowerInstr, isize, uf, ufSize, ovfD, ovfR, ovfA, emptyA] <;> (try split) <;> simp
 
 
 
 
 
 
191
 
192
- /-- Prefix sums of instruction sizes: `offs p k` is the code index of IR instruction `k`.
193
- For `k` past the end it is the index of the final bad-pc stub. -/
194
- def offs (p : Prog 32) (k : Nat) : Nat := ((p.take k).map isize).sum
 
 
 
 
195
 
196
- def lowerGo (L : Layout) (off : Nat → Nat) : Nat → List (WordDialect.Instr 32) → List (Instr Nat)
197
- | _, [] => [.exitTrap .badPc]
198
- | b, i :: is => lowerInstr L b off i ++ lowerGo L off (b + isize i) is
 
199
 
200
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
201
- IR program traps `badPc` exactly as the IR semantics does. -/
202
- def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs p) 0 p
 
203
 
204
  end CM
205
  end WordDialect
 
1
  import CM.Isa
2
+ import WordDialect.Depth
3
 
4
  /-!
5
  # CM.Lower
 
50
  rGap : W -- `4 rcap - 8`: a call has room iff `r8 ≥ r7 - rGap`
51
  aEnd : W -- empty auxiliary stack: `r9 = aEnd`
52
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `r9 ≥ aLim`
53
+ /-- A depth certificate (`WordDialect.Depth`): at IR instruction `k` the data stack holds at
54
+ least `cert k` words, so an operand-count guard for at most that many words is left out. -/
55
+ cert : Nat → Nat := fun _ => 0
56
+ /-- An upper bound on the data-stack depth at each IR instruction, and the data stack's
57
+ capacity in words. Where `ub k + 1 ≤ dCap` the data-stack overflow guard is left out. The
58
+ default capacity `0` leaves every guard in. -/
59
+ ub : Nat → Nat := fun _ => 0
60
+ dCap : Nat := 0
61
+
62
+ /-- What the lowering knows at one IR instruction: a lower bound on the data-stack depth, and
63
+ whether one more word is known to fit. -/
64
+ structure Facts where
65
+ lo : Nat := 0
66
+ noOvf : Bool := false
67
+
68
+ /-- The facts at IR instruction `k`. -/
69
+ def Layout.facts (L : Layout) (k : Nat) : Facts :=
70
+ { lo := L.cert k, noOvf := decide (L.ub k + 1 ≤ L.dCap) }
71
 
72
  /-- Stack-underflow guard for `k` operands: continue when `r4 ≤ dEnd - 4k`. -/
73
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
 
77
 
78
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
79
 
80
+ /-- The operand count an instruction popping `k` words still has to check when the data stack is
81
+ known to hold at least `g.lo` words: none if `k ≤ g.lo`. -/
82
+ def need (g : Facts) (k : Nat) : Nat := if k ≤ g.lo then 0 else k
83
+
84
+ theorem need_le (g : Facts) (k : Nat) : need g k ≤ k := by unfold need; split <;> omega
85
+
86
+ theorem need_of_lt {g : Facts} {k : Nat} (h : g.lo < k) : need g k = k := by
87
+ unfold need; split <;> omega
88
+
89
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
90
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
91
  [.movImm r0 L.dLim, .bcc .uge r4 r0 (base + 3), .exitOvf]
92
 
93
+ /-- The data-stack overflow guard where it is needed: none when the facts say one more word fits. -/
94
+ def ovf (L : Layout) (g : Facts) (base : Nat) : List (Instr Nat) :=
95
+ if g.noOvf then [] else ovfD L base
96
+
97
+ def ovfSize (g : Facts) : Nat := if g.noOvf then 0 else 3
98
+
99
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
100
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
101
  [.movRR r0 r7, .movImm r1 L.rGap, .sub r0 r1, .bcc .uge r8 r0 (base + 5), .exitOvf]
 
109
  [.movImm r0 L.aEnd, .bcc .ne r9 r0 (base + 3), .exitTrap .returnUnderflow]
110
 
111
  /-- Code size of one IR instruction. -/
112
+ def isize (g : Facts) : WordDialect.Instr 32 → Nat
113
+ | .word _ | .ptr _ => ovfSize g + 3
114
+ | .load => ufSize (need g 1) + 8
115
+ | .store => ufSize (need g 2) + 9
116
+ | .add | .sub | .mul | .and | .or | .xor => ufSize (need g 2) + 5
117
+ | .div | .sdiv => ufSize (need g 2) + 7
118
+ | .not => ufSize (need g 1) + 3
119
+ | .shl | .shr => ufSize (need g 2) + 8
120
+ | .rotl => ufSize (need g 2) + 6
121
+ | .rotr => ufSize (need g 2) + 5
122
+ | .cmp _ => ufSize (need g 2) + 7
123
+ | .select => ufSize (need g 3) + 7
124
  | .jmp _ => 1
125
+ | .branch _ => ufSize (need g 1) + 3
126
  | .call _ => 6
127
  | .ret => 3
128
+ | .push _ => ovfSize g + 3
129
+ | .pop _ => ufSize (need g 1) + 3
130
+ | .dup => ufSize (need g 1) + ovfSize g + 3
131
+ | .drop => ufSize (need g 1) + 1
132
+ | .swap => ufSize (need g 2) + 4
133
+ | .over => ufSize (need g 2) + ovfSize g + 3
134
+ | .rot => ufSize (need g 3) + 6
135
+ | .tor => ufSize (need g 1) + 7
136
+ | .fromr => ovfSize g + 7
137
+ | .rfetch => ovfSize g + 6
138
  | .halt => 1
139
 
140
  /-- Code for one IR instruction placed at code index `base`; `off t` is the code index of IR
141
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
142
+ def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts) :
143
+ WordDialect.Instr 32 → List (Instr Nat)
144
+ | .word w => ovf L g base ++ [.movImm r0 w, .addImm r4 (-4), .store r4 0 r0]
145
+ | .ptr p => ovf L g base ++ [.movImm r0 p.toWord, .addImm r4 (-4), .store r4 0 r0]
146
  | .load =>
147
+ let b0 := base + ufSize (need g 1)
148
+ uf L (need g 1) base ++
149
  [.load r0 r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r1 (b0 + 4),
150
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r6, .load r0 r0 0, .store r4 0 r0]
151
  | .store =>
152
+ let b0 := base + ufSize (need g 2)
153
+ uf L (need g 2) base ++
154
  [.load r0 r4 0, .load r1 r4 4, .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (b0 + 5),
155
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r6, .store r0 0 r1, .addImm r4 8]
156
+ | .add => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .add r0 r1, .store r4 4 r0, .addImm r4 4]
157
+ | .sub => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .sub r0 r1, .store r4 4 r0, .addImm r4 4]
158
+ | .mul => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .mul r0 r1, .store r4 4 r0, .addImm r4 4]
159
+ | .and => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .and r0 r1, .store r4 4 r0, .addImm r4 4]
160
+ | .or => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .or r0 r1, .store r4 4 r0, .addImm r4 4]
161
+ | .xor => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .xor r0 r1, .store r4 4 r0, .addImm r4 4]
162
  | .div =>
163
+ let b0 := base + ufSize (need g 2)
164
+ uf L (need g 2) base ++
165
  [.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero, .divu r0 r0 r1,
166
  .store r4 4 r0, .addImm r4 4]
167
  | .sdiv =>
168
+ let b0 := base + ufSize (need g 2)
169
+ uf L (need g 2) base ++
170
  [.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero, .div r0 r0 r1,
171
  .store r4 4 r0, .addImm r4 4]
172
+ | .not => uf L (need g 1) base ++ [.load r0 r4 0, .not r0, .store r4 0 r0]
173
  | .shl =>
174
+ uf L (need g 2) base ++
175
  [.load r1 r4 0, .load r0 r4 4, .lsl r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
176
  .store r4 4 r0, .addImm r4 4]
177
  | .shr =>
178
+ uf L (need g 2) base ++
179
  [.load r1 r4 0, .load r0 r4 4, .lsr r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
180
  .store r4 4 r0, .addImm r4 4]
181
  | .rotl =>
182
+ uf L (need g 2) base ++
183
  [.load r1 r4 0, .load r0 r4 4, .neg r1, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
184
  | .rotr =>
185
+ uf L (need g 2) base ++
186
  [.load r1 r4 0, .load r0 r4 4, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
187
  | .cmp c =>
188
+ let b0 := base + ufSize (need g 2)
189
+ uf L (need g 2) base ++
190
  [.load r1 r4 0, .load r0 r4 4, .movImm r2 1#32, .bcc c r0 r1 (b0 + 5), .movImm r2 0#32,
191
  .store r4 4 r2, .addImm r4 4]
192
  | .select =>
193
+ let b0 := base + ufSize (need g 3)
194
+ uf L (need g 3) base ++
195
  [.load r1 r4 0, .load r0 r4 4, .load r3 r4 8, .beqz r1 (b0 + 5), .movRR r0 r3,
196
  .store r4 8 r0, .addImm r4 8]
197
  | .jmp t => [.jmp (off t)]
198
+ | .branch t => uf L (need g 1) base ++ [.load r0 r4 0, .addImm r4 4, .bnez r0 (off t)]
199
  | .call t => ovfR L base ++ [.call (off t)]
200
  | .ret => [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret]
201
+ | .push r => ovf L g base ++ [.load r0 r5 (4 * (r : Int)), .addImm r4 (-4), .store r4 0 r0]
202
+ | .pop r => uf L (need g 1) base ++ [.load r0 r4 0, .addImm r4 4, .store r5 (4 * (r : Int)) r0]
203
  | .dup =>
204
+ uf L (need g 1) base ++ ovf L g (base + ufSize (need g 1)) ++ [.load r0 r4 0, .addImm r4 (-4), .store r4 0 r0]
205
+ | .drop => uf L (need g 1) base ++ [.addImm r4 4]
206
+ | .swap => uf L (need g 2) base ++ [.load r0 r4 0, .load r1 r4 4, .store r4 0 r1, .store r4 4 r0]
207
  | .over =>
208
+ uf L (need g 2) base ++ ovf L g (base + ufSize (need g 2)) ++ [.load r0 r4 4, .addImm r4 (-4), .store r4 0 r0]
209
  | .rot =>
210
+ uf L (need g 3) base ++
211
  [.load r0 r4 0, .load r1 r4 4, .load r2 r4 8, .store r4 0 r2, .store r4 4 r0,
212
  .store r4 8 r1]
213
  | .tor =>
214
+ uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
215
  [.load r0 r4 0, .addImm r4 4, .addImm r9 (-4), .store r9 0 r0]
216
  | .fromr =>
217
+ emptyA L base ++ ovf L g (base + 3) ++
218
  [.load r0 r9 0, .addImm r9 4, .addImm r4 (-4), .store r4 0 r0]
219
  | .rfetch =>
220
+ emptyA L base ++ ovf L g (base + 3) ++ [.load r0 r9 0, .addImm r4 (-4), .store r4 0 r0]
221
  | .halt => [.exitHalt]
222
 
223
+ theorem uf_length (L : Layout) (k base : Nat) : (uf L k base).length = ufSize k := by
224
+ unfold uf ufSize; split <;> simp
225
+
226
+ theorem ovf_length (L : Layout) (g : Facts) (base : Nat) : (ovf L g base).length = ovfSize g := by
227
+ unfold ovf ovfSize; split <;> simp [ovfD]
228
+
229
+ theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts)
230
+ (i : WordDialect.Instr 32) : (lowerInstr L base off g i).length = isize g i := by
231
+ cases i <;> simp [lowerInstr, isize, uf_length, ovf_length, ovfR, ovfA, emptyA] <;> omega
232
 
233
+ /-- Prefix sums of instruction sizes: `offs cf p k` is the code index of IR instruction `k`,
234
+ where `cf j` are the facts at instruction `j` (its guards depend on them). For `k` past
235
+ the end it is the index of the final bad-pc stub. -/
236
+ def offs (cf : Nat → Facts) : Prog 32 → Nat → Nat
237
+ | _, 0 => 0
238
+ | [], _ + 1 => 0
239
+ | i :: is, k + 1 => isize (cf 0) i + offs (fun j => cf (j + 1)) is k
240
 
241
+ def lowerGo (L : Layout) (off : Nat → Nat) :
242
+ (Nat → Facts) → Nat → List (WordDialect.Instr 32) → List (Instr Nat)
243
+ | _, _, [] => [.exitTrap .badPc]
244
+ | cf, b, i :: is => lowerInstr L b off (cf 0) i ++ lowerGo L off (fun j => cf (j + 1)) (b + isize (cf 0) i) is
245
 
246
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
247
+ IR program traps `badPc` exactly as the IR semantics does. Instruction `k` leaves out the
248
+ guards that `L.facts k` makes redundant. -/
249
+ def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs L.facts p) L.facts 0 p
250
 
251
  end CM
252
  end WordDialect
backend/cortexm/CM/Rel.lean CHANGED
@@ -33,6 +33,17 @@ structure Cfg where
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  structure Geom (c : Cfg) : Prop where
38
  dEnd_lt : c.dEnd < 2 ^ 32
@@ -95,7 +106,7 @@ def MemRel (c : Cfg) (mem : Memory 32) (m : Memory 32) : Prop :=
95
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
96
 
97
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
98
- ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs p a))
99
 
100
  /-- The Thumb-2 memory's addressable set covers every region. -/
101
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
@@ -125,7 +136,7 @@ structure Rel0 (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop where
125
 
126
  /-- Full relation: everything in `Rel0`, and the Thumb-2 pc is the start of the IR pc's code. -/
127
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
128
- Rel0 c p s x ∧ x.pc = offs p s.pc
129
 
130
  /-- `Rel0` does not look at scratch registers or the pc. -/
131
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
 
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
36
+ /-- The depth certificate the code was lowered with (`Layout.cert`). -/
37
+ cert : Nat → Nat := fun _ => 0
38
+ /-- The upper bound on the data-stack depth the code was lowered with (`Layout.ub`). -/
39
+ ub : Nat → Nat := fun _ => 2 ^ 32
40
+
41
+ /-- The data stack's capacity in words. -/
42
+ def Cfg.dCap (c : Cfg) : Nat := (c.dEnd - c.dBase) / 4
43
+
44
+ /-- The facts the code was lowered with (`Layout.facts`). -/
45
+ def Cfg.facts (c : Cfg) (k : Nat) : Facts :=
46
+ { lo := c.cert k, noOvf := decide (c.ub k + 1 ≤ c.dCap) }
47
 
48
  structure Geom (c : Cfg) : Prop where
49
  dEnd_lt : c.dEnd < 2 ^ 32
 
106
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
107
 
108
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
109
+ ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs c.facts p a))
110
 
111
  /-- The Thumb-2 memory's addressable set covers every region. -/
112
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
 
136
 
137
  /-- Full relation: everything in `Rel0`, and the Thumb-2 pc is the start of the IR pc's code. -/
138
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
139
+ Rel0 c p s x ∧ x.pc = offs c.facts p s.pc
140
 
141
  /-- `Rel0` does not look at scratch registers or the pc. -/
142
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
backend/cortexm/CM/Run.lean CHANGED
@@ -63,11 +63,10 @@ theorem rstep_of_fetch {code : List (Instr Nat)} {m : M} {i : Instr Nat}
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
- theorem offs_cons (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
- offs (i :: is) (k + 1) = isize i + offs is k := by
68
- simp [offs, List.take_succ_cons]
69
 
70
- theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by simp [offs]
71
 
72
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
73
  induction seg generalizing pre with
@@ -77,66 +76,70 @@ theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) p
77
  have := ih (pre ++ [i])
78
  simpa [List.append_assoc] using this
79
 
80
- /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs ps k`. -/
 
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
- ∀ (ps : Prog 32) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps k)
85
- (lowerInstr L (pre.length + offs ps k) off i) := by
86
  intro ps
87
  induction ps with
88
- | nil => intro pre k i h; simp at h
89
  | cons j js ih =>
90
- intro pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
- have := rat_embed pre (lowerInstr L pre.length off j) (lowerGo L off (pre.length + isize j) js)
 
96
  simpa [List.append_assoc] using this
97
  | succ k =>
98
  simp only [List.getElem?_cons_succ] at h
99
- have := ih (pre ++ lowerInstr L pre.length off j) k i h
100
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
101
  simp [lowerInstr_length]
102
  rw [hl] at this
103
  simp only [lowerGo, offs_cons]
104
- have e : pre.length + (isize j + offs js k) = pre.length + isize j + offs js k := by omega
 
105
  rw [e]
106
  simpa [List.append_assoc] using this
107
 
108
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
109
  (h : p[k]? = some i) :
110
- RAt (lowerProg L p) (offs p k) (lowerInstr L (offs p k) (offs p) i) := by
111
- have := lowerGo_at L (offs p) p [] k i h
112
  simpa [lowerProg] using this
113
 
114
- /-- The final stub (bad-pc trap) sits at `offs p p.length`. -/
115
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
116
- ∀ (ps : Prog 32) (pre : List (Instr Nat)),
117
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps ps.length) [.exitTrap .badPc] := by
 
118
  intro ps
119
  induction ps with
120
  | nil =>
121
- intro pre
122
- simp only [lowerGo, List.length_nil, offs, List.take_nil, List.map_nil, List.sum_nil,
123
- Nat.add_zero]
124
  have := rat_embed pre [.exitTrap .badPc] []
125
  simpa using this
126
  | cons j js ih =>
127
- intro pre
128
- have := ih (pre ++ lowerInstr L pre.length off j)
129
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
130
  simp [lowerInstr_length]
131
  rw [hl] at this
132
  simp only [lowerGo, List.length_cons, offs_cons]
133
- have e : pre.length + (isize j + offs js js.length) = pre.length + isize j + offs js js.length := by omega
 
134
  rw [e]
135
  simpa [List.append_assoc] using this
136
 
137
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
138
- RAt (lowerProg L p) (offs p p.length) [.exitTrap .badPc] := by
139
- have := lowerGo_stub L (offs p) p []
140
  simpa [lowerProg] using this
141
 
142
  end CM
 
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
+ theorem offs_cons (cf : Nat → Facts) (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
+ offs cf (i :: is) (k + 1) = isize (cf 0) i + offs (fun j => cf (j + 1)) is k := rfl
 
68
 
69
+ theorem offs_zero (cf : Nat → Facts) (p : Prog 32) : offs cf p 0 = 0 := by cases p <;> rfl
70
 
71
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
72
  induction seg generalizing pre with
 
76
  have := ih (pre ++ [i])
77
  simpa [List.append_assoc] using this
78
 
79
+ /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs cf ps k`, with
80
+ the guards for the facts `cf k`. -/
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps k)
85
+ (lowerInstr L (pre.length + offs cf ps k) off (cf k) i) := by
86
  intro ps
87
  induction ps with
88
+ | nil => intro cf pre k i h; simp at h
89
  | cons j js ih =>
90
+ intro cf pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
+ have := rat_embed pre (lowerInstr L pre.length off (cf 0) j)
96
+ (lowerGo L off (fun j => cf (j + 1)) (pre.length + isize (cf 0) j) js)
97
  simpa [List.append_assoc] using this
98
  | succ k =>
99
  simp only [List.getElem?_cons_succ] at h
100
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j) k i h
101
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
102
  simp [lowerInstr_length]
103
  rw [hl] at this
104
  simp only [lowerGo, offs_cons]
105
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js k) =
106
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js k := by omega
107
  rw [e]
108
  simpa [List.append_assoc] using this
109
 
110
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
111
  (h : p[k]? = some i) :
112
+ RAt (lowerProg L p) (offs L.facts p k) (lowerInstr L (offs L.facts p k) (offs L.facts p) (L.facts k) i) := by
113
+ have := lowerGo_at L (offs L.facts p) p L.facts [] k i h
114
  simpa [lowerProg] using this
115
 
116
+ /-- The final stub (bad-pc trap) sits at `offs cf p p.length`. -/
117
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
118
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)),
119
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps ps.length)
120
+ [.exitTrap .badPc] := by
121
  intro ps
122
  induction ps with
123
  | nil =>
124
+ intro cf pre
125
+ simp only [lowerGo, List.length_nil, offs_zero, Nat.add_zero]
 
126
  have := rat_embed pre [.exitTrap .badPc] []
127
  simpa using this
128
  | cons j js ih =>
129
+ intro cf pre
130
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j)
131
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
132
  simp [lowerInstr_length]
133
  rw [hl] at this
134
  simp only [lowerGo, List.length_cons, offs_cons]
135
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length) =
136
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length := by omega
137
  rw [e]
138
  simpa [List.append_assoc] using this
139
 
140
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
141
+ RAt (lowerProg L p) (offs L.facts p p.length) [.exitTrap .badPc] := by
142
+ have := lowerGo_stub L (offs L.facts p) p L.facts []
143
  simpa [lowerProg] using this
144
 
145
  end CM
backend/cortexm/CM/SimAux.lean CHANGED
@@ -203,7 +203,7 @@ end Steps
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
- {base : Nat}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
@@ -305,32 +305,32 @@ end Guards
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
- {L : Layout} {base : Nat} {off : Nat → Nat}
309
 
310
  /-- Placement of the `tor` code. -/
311
- theorem xat_tor (hat : RAt code base (lowerInstr L base off .tor)) :
312
- RAt code base (uf L 1 base) ∧ RAt code (base + 3) (ovfA L (base + 3)) ∧
313
- RAt code (base + 6) [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r9 (-4),
314
  .store Reg.r9 0 r0] := by
315
- have hat' : RAt code base (uf L 1 base ++ ovfA L (base + 3) ++
316
  [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r9 (-4), .store Reg.r9 0 r0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
320
  rw [hufl] at hato
321
- have hl : (uf L 1 base ++ ovfA L (base + 3)).length = 6 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
- x'.pc = base + isize (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
@@ -343,39 +343,40 @@ theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
- by simp [isize, ufSize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
- /-- Placement of `emptyA L base ++ ovfD L (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
- (hat : RAt code base (emptyA L base ++ ovfD L (base + 3) ++ rest)) :
359
- RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovfD L (base + 3)) ∧
360
- RAt code (base + 6) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
- have hl : (emptyA L base ++ ovfD L (base + 3)).length = 6 := rfl
366
- rw [hl] at hatr
 
367
  exact ⟨hate, hato, hatr⟩
368
 
369
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
370
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
371
  {a : W} {as : List W} (hd : s.astack = a :: as)
372
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
373
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
374
- x'.pc = base + isize (.fromr : WordDialect.Instr 32) := by
375
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
376
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
377
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
378
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
379
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
380
  (by simp) (fetch_cast f0 (by omega))
381
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
@@ -386,30 +387,30 @@ theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = o
386
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
387
 
388
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
389
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr)) (he : s.astack = []) :
390
  RExec code x (.trapped .returnUnderflow) :=
391
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r9 0,
392
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
393
 
394
- theorem sim_fromr_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
395
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
396
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
397
  RExec code x .overflow := by
398
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
399
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
400
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
401
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
402
 
403
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
404
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
405
  {a : W} {as : List W} (hd : s.astack = a :: as)
406
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
407
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
408
- x'.pc = base + isize (.rfetch : WordDialect.Instr 32) := by
409
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
410
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
411
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
412
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
413
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
414
  (by simp) (fetch_cast f0 (by omega))
415
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
@@ -418,19 +419,19 @@ theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim =
418
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
419
 
420
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
421
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch)) (he : s.astack = []) :
422
  RExec code x (.trapped .returnUnderflow) :=
423
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r9 0,
424
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
425
 
426
- theorem sim_rfetch_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
427
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
428
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
429
  RExec code x .overflow := by
430
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
431
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
432
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
433
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
434
 
435
  end Ops
436
 
 
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
+ {base : Nat} {g : Facts}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
 
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
309
 
310
  /-- Placement of the `tor` code. -/
311
+ theorem xat_tor (hat : RAt code base (lowerInstr L base off g .tor)) :
312
+ RAt code base (uf L (need g 1) base) ∧ RAt code (base + ufSize (need g 1)) (ovfA L (base + ufSize (need g 1))) ∧
313
+ RAt code (base + ufSize (need g 1) + 3) [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r9 (-4),
314
  .store Reg.r9 0 r0] := by
315
+ have hat' : RAt code base (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
316
  [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r9 (-4), .store Reg.r9 0 r0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
+ have hufl := uf_length L (need g 1) base
320
  rw [hufl] at hato
321
+ have hl : (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1))).length = ufSize (need g 1) + 3 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
+ x'.pc = base + isize g (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
 
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
+ by simp [isize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
+ /-- Placement of `emptyA L base ++ ovf L g (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
+ (hat : RAt code base (emptyA L base ++ ovf L g (base + 3) ++ rest)) :
359
+ RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovf L g (base + 3)) ∧
360
+ RAt code (base + 3 + ovfSize g) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
+ have hl : (emptyA L base ++ ovf L g (base + 3)).length = 3 + ovfSize g := by
366
+ simp [ovf_length, emptyA]; omega
367
+ rw [hl, ← Nat.add_assoc] at hatr
368
  exact ⟨hate, hato, hatr⟩
369
 
370
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
371
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
372
  {a : W} {as : List W} (hd : s.astack = a :: as)
373
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
374
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
375
+ x'.pc = base + isize g (.fromr : WordDialect.Instr 32) := by
376
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
377
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
378
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
379
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
380
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
381
  (by simp) (fetch_cast f0 (by omega))
382
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
 
387
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
388
 
389
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
390
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr)) (he : s.astack = []) :
391
  RExec code x (.trapped .returnUnderflow) :=
392
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r9 0,
393
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
394
 
395
+ theorem sim_fromr_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
396
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
397
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
398
  RExec code x .overflow := by
399
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
400
  .addImm Reg.r9 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
401
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
402
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
403
 
404
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
405
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
406
  {a : W} {as : List W} (hd : s.astack = a :: as)
407
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
408
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
409
+ x'.pc = base + isize g (.rfetch : WordDialect.Instr 32) := by
410
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
411
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
412
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
413
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
414
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
415
  (by simp) (fetch_cast f0 (by omega))
416
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
 
419
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
420
 
421
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
422
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch)) (he : s.astack = []) :
423
  RExec code x (.trapped .returnUnderflow) :=
424
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r9 0,
425
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
426
 
427
+ theorem sim_rfetch_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
428
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
429
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
430
  RExec code x .overflow := by
431
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r9 0,
432
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
433
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
434
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
435
 
436
  end Ops
437
 
backend/cortexm/CM/SimBin.lean CHANGED
@@ -28,23 +28,23 @@ theorem scratch_ne (r : Reg) (h : r = r0 ∨ r = r1 ∨ r = r2 ∨ r = r3) :
28
  rcases h with rfl | rfl | rfl | rfl <;> decide
29
 
30
  theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
- {L : Layout} {base : Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
32
  (hpc : x.pc = base) (mid : List (Instr Nat)) (rr : Reg)
33
  (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
34
  (hmid : MidSpec mid rr f) (hstr : ∀ i ∈ mid, i.straightR = true)
35
- (hat : RAt code base (uf L 2 base ++
36
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4])))
37
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
38
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
39
- x'.pc = base + 3 + (4 + mid.length) := by
40
  have hk : 2 ≤ s.dstack.length := by simp [hd]
41
  obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
42
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
43
  rw [hufl] at hatrest
44
  obtain ⟨hatA, hatB⟩ := rat_append.mp hatrest
45
  obtain ⟨hatLd, hatMid⟩ := rat_append.mp hatA
46
  obtain ⟨f0, f1, _⟩ := hatLd
47
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
48
  have hrcx := scratch_ne r1 (by simp)
49
  have hrax := scratch_ne r0 (by simp)
50
  -- load r1, [r4 + 0]
@@ -53,14 +53,14 @@ theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (
53
  have hst0 : RSteps code x1 x2 := RSteps.single (by
54
  rw [rstep_of_fetch (m := x1) (by rw [hpc1]; exact f0), e0, hx2])
55
  have hr2 : Rel0 c p s x2 := by rw [hx2]; exact mov_rel0 hr1 r1 hrcx b
56
- have hpc2 : x2.pc = base + 3 + 1 := by simp [hx2, M.mov, M.setReg, M.adv, hpc1]
57
  -- load r0, [r4 + 4]
58
  have e1 := ld_stack hr2 (j := 1) (v := a) (by simp [hd]) r0 (disp := 4) (by simp)
59
  obtain ⟨x3, hx3⟩ : ∃ x3, x3 = x2.mov r0 a := ⟨_, rfl⟩
60
  have hst1 : RSteps code x2 x3 := RSteps.single (by
61
  rw [rstep_of_fetch (m := x2) (by rw [hpc2]; exact f1), e1, hx3])
62
  have hr3 : Rel0 c p s x3 := by rw [hx3]; exact mov_rel0 hr2 r0 hrax a
63
- have hpc3 : x3.pc = base + 3 + 2 := by simp [hx3, M.mov, M.setReg, M.adv, hpc2]
64
  have hax : x3.regs r0 = a := by simp [hx3, M.mov, M.setReg, M.adv]
65
  have hcx : x3.regs r1 = b := by simp [hx3, hx2, M.mov, M.setReg, M.adv]
66
  -- mid
@@ -71,12 +71,12 @@ theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (
71
  have hlen : 1 < s.dstack.length := by simp [hd]
72
  obtain ⟨mem', e2, hr5⟩ := st_stack hg hr4 (j := 1) hlen rr (disp := 4) (by simp)
73
  obtain ⟨st, adj, _⟩ := hatB
74
- have hpc4' : x4.pc = base + 3 + (2 + mid.length) := by rw [hpc4, hpc3]; omega
75
  obtain ⟨x5, hx5⟩ : ∃ x5, x5 = ({ x4.adv with mem := mem' } : M) := ⟨_, rfl⟩
76
  have hst2 : RSteps code x4 x5 := RSteps.single (by
77
  rw [rstep_of_fetch (m := x4) (fetch_cast st (by rw [hpc4']; simp; omega)), e2, hx5])
78
  rw [← hx5] at hr5
79
- have hpc5 : x5.pc = base + 3 + (2 + mid.length + 1) := by
80
  simp [hx5, M.adv]; omega
81
  -- adjust r4
82
  have hlen5 : 1 ≤ ({ s with dstack := s.dstack.set 1 (x4.regs rr) } : State 32).dstack.length := by
 
28
  rcases h with rfl | rfl | rfl | rfl <;> decide
29
 
30
  theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
+ {L : Layout} {base : Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
32
  (hpc : x.pc = base) (mid : List (Instr Nat)) (rr : Reg)
33
  (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
34
  (hmid : MidSpec mid rr f) (hstr : ∀ i ∈ mid, i.straightR = true)
35
+ (hat : RAt code base (uf L (need g 2) base ++
36
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4])))
37
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
38
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
39
+ x'.pc = base + ufSize (need g 2) + (4 + mid.length) := by
40
  have hk : 2 ≤ s.dstack.length := by simp [hd]
41
  obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
42
+ have hufl := uf_length L (need g 2) base
43
  rw [hufl] at hatrest
44
  obtain ⟨hatA, hatB⟩ := rat_append.mp hatrest
45
  obtain ⟨hatLd, hatMid⟩ := rat_append.mp hatA
46
  obtain ⟨f0, f1, _⟩ := hatLd
47
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
48
  have hrcx := scratch_ne r1 (by simp)
49
  have hrax := scratch_ne r0 (by simp)
50
  -- load r1, [r4 + 0]
 
53
  have hst0 : RSteps code x1 x2 := RSteps.single (by
54
  rw [rstep_of_fetch (m := x1) (by rw [hpc1]; exact f0), e0, hx2])
55
  have hr2 : Rel0 c p s x2 := by rw [hx2]; exact mov_rel0 hr1 r1 hrcx b
56
+ have hpc2 : x2.pc = base + ufSize (need g 2) + 1 := by simp [hx2, M.mov, M.setReg, M.adv, hpc1]
57
  -- load r0, [r4 + 4]
58
  have e1 := ld_stack hr2 (j := 1) (v := a) (by simp [hd]) r0 (disp := 4) (by simp)
59
  obtain ⟨x3, hx3⟩ : ∃ x3, x3 = x2.mov r0 a := ⟨_, rfl⟩
60
  have hst1 : RSteps code x2 x3 := RSteps.single (by
61
  rw [rstep_of_fetch (m := x2) (by rw [hpc2]; exact f1), e1, hx3])
62
  have hr3 : Rel0 c p s x3 := by rw [hx3]; exact mov_rel0 hr2 r0 hrax a
63
+ have hpc3 : x3.pc = base + ufSize (need g 2) + 2 := by simp [hx3, M.mov, M.setReg, M.adv, hpc2]
64
  have hax : x3.regs r0 = a := by simp [hx3, M.mov, M.setReg, M.adv]
65
  have hcx : x3.regs r1 = b := by simp [hx3, hx2, M.mov, M.setReg, M.adv]
66
  -- mid
 
71
  have hlen : 1 < s.dstack.length := by simp [hd]
72
  obtain ⟨mem', e2, hr5⟩ := st_stack hg hr4 (j := 1) hlen rr (disp := 4) (by simp)
73
  obtain ⟨st, adj, _⟩ := hatB
74
+ have hpc4' : x4.pc = base + ufSize (need g 2) + (2 + mid.length) := by rw [hpc4, hpc3]; omega
75
  obtain ⟨x5, hx5⟩ : ∃ x5, x5 = ({ x4.adv with mem := mem' } : M) := ⟨_, rfl⟩
76
  have hst2 : RSteps code x4 x5 := RSteps.single (by
77
  rw [rstep_of_fetch (m := x4) (fetch_cast st (by rw [hpc4']; simp; omega)), e2, hx5])
78
  rw [← hx5] at hr5
79
+ have hpc5 : x5.pc = base + ufSize (need g 2) + (2 + mid.length + 1) := by
80
  simp [hx5, M.adv]; omega
81
  -- adjust r4
82
  have hlen5 : 1 ≤ ({ s with dstack := s.dstack.set 1 (x4.regs rr) } : State 32).dstack.length := by
backend/cortexm/CM/SimCtl.lean CHANGED
@@ -14,19 +14,24 @@ namespace CM
14
 
15
  open Reg
16
 
17
- theorem offs_succ {p : Prog 32} {k : Nat} {i : WordDialect.Instr 32} (h : p[k]? = some i) :
18
- offs p (k + 1) = offs p k + isize i := by
19
- have hk : k < p.length := (List.getElem?_eq_some_iff.mp h).1
20
- have hi : p[k] = i := (List.getElem?_eq_some_iff.mp h).2
21
- simp [offs, List.take_succ, h, List.sum_append]
 
 
 
 
 
22
 
23
  section Ctl
24
 
25
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
26
- {L : Layout} {base : Nat} {off : Nat → Nat}
27
 
28
  theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
29
- (hat : RAt code base (lowerInstr L base off (.jmp t))) :
30
  ∃ x', RSteps code x x' ∧ Rel0 c p s x' ∧ x'.pc = off t := by
31
  have hat' : RAt code base [.jmp (off t)] := hat
32
  obtain ⟨f0, _⟩ := hat'
@@ -35,18 +40,18 @@ theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
35
 
36
  /-- `branch t`: both outcomes. -/
37
  theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
38
- (hpc : x.pc = base) {t : Nat} (hat : RAt code base (lowerInstr L base off (.branch t)))
39
  {cc : W} {d : List W} (hd : s.dstack = cc :: d) :
40
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
41
- x'.pc = (if Word.isTrue cc then off t else base + isize (.branch t : WordDialect.Instr 32)) := by
42
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
43
  .bnez r0 (off t)]) := hat
44
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
45
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
46
  rw [hufl] at hatr
47
  obtain ⟨f0, f1, f2, _⟩ := hatr
48
  have hk : 1 ≤ s.dstack.length := by simp [hd]
49
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
50
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
51
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
52
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
@@ -60,7 +65,7 @@ theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
60
  simp [exec, hax3, hc]
61
  refine ⟨x3.adv, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4),
62
  hr3.congr rfl rfl rfl rfl rfl rfl rfl, ?_⟩
63
- simp [hc, Word.isTrue, M.adv, hpc3, isize, ufSize]; omega
64
  · have hst4 : step code x3 = .next { x3 with pc := off t } := by
65
  rw [rstep_of_fetch (m := x3) (fetch_cast f2 (by omega))]
66
  simp [exec, hax3, hc]
@@ -69,7 +74,7 @@ theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
69
  simp [hc, Word.isTrue]
70
 
71
  theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
72
- (hat : RAt code base (lowerInstr L base off .halt)) : RExec code x (.halted x) := by
73
  have hat' : RAt code base [.exitHalt] := hat
74
  obtain ⟨f0, _⟩ := hat'
75
  exact RExec.halt (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
@@ -78,7 +83,7 @@ theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
78
  (`r8`) and writes `lr`. -/
79
  theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
80
  (hat : RAt code base [.call (off t)])
81
- (hret : base + 1 = offs p (s.pc + 1)) (hfitR : s.rstack.length + 2 ≤ c.rcap) :
82
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
83
  x'.pc = off t := by
84
  obtain ⟨f0, _⟩ := hat
@@ -170,9 +175,9 @@ theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t :
170
  · simp only [List.length_cons]; omega
171
 
172
  theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
173
- (hat : RAt code base (lowerInstr L base off .ret)) {a : Nat} {rs : List Nat}
174
- (hr : s.rstack = a :: rs) (hsz : offs p a < 2 ^ 32) :
175
- ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := rs } x' ∧ x'.pc = offs p a := by
176
  have hat' : RAt code base [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
177
  obtain ⟨f0, f1, f3, _⟩ := hat'
178
  have hcapR := hs.capR
@@ -194,14 +199,14 @@ theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
194
  rw [hr] at hread
195
  simp only [List.length_cons, Nat.mul_zero, Nat.add_zero] at hread
196
  have hst3 : step code { x1 with pc := base + 2 } = .next { ((({ x1 with pc := base + 2 } : M).setReg
197
- lr (ofN (offs p a))).setReg r8 (ofN (c.sp0 - 4 * rs.length))) with pc := offs p a } := by
198
  rw [rstep_of_fetch (m := { x1 with pc := base + 2 }) f3]
199
  have hx1r : x1.regs r8 = ofN (c.sp0 - 4 * (rs.length + 1)) := hrsp
200
  have hx1m : x1.mem = x.mem := rfl
201
  have hadd : ofN (c.sp0 - 4 * (rs.length + 1)) + 4#32 = ofN (c.sp0 - 4 * rs.length) := by
202
  show ofN _ + ofN 4 = _
203
  rw [ofN_add]; congr 1; omega
204
- have hv : (ofN (offs p a)).toNat = offs p a := by
205
  simp [ofN, BitVec.toNat_ofNat, Nat.mod_eq_of_lt hsz]
206
  simp only [exec]
207
  rw [hx1m, hx1r, hread]
@@ -230,7 +235,7 @@ theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
230
  omega
231
 
232
  theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
233
- (hat : RAt code base (lowerInstr L base off .ret)) (hr : s.rstack = []) :
234
  RExec code x (.trapped .returnUnderflow) := by
235
  have hat' : RAt code base [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
236
  obtain ⟨f0, f1, _⟩ := hat'
@@ -241,8 +246,8 @@ theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
241
 
242
  /-- `call t`: the return-stack guard, then the model's `call`. -/
243
  theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
244
- (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off (.call t)))
245
- (hret : base + isize (.call t : WordDialect.Instr 32) = offs p (s.pc + 1))
246
  (hfitR : s.rstack.length + 2 ≤ c.rcap) :
247
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
248
  x'.pc = off t := by
@@ -255,7 +260,7 @@ theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : N
255
  exact ⟨x', hs1.trans hs', hr', hpc'⟩
256
 
257
  theorem sim_call_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
258
- (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off (.call t)))
259
  (h : ¬ s.rstack.length + 2 ≤ c.rcap) : RExec code x .overflow := by
260
  have hat' : RAt code base (ovfR L base ++ [.call (off t)]) := hat
261
  exact ovfR_trap hg hs hLr h hpc (rat_append.mp hat').1
 
14
 
15
  open Reg
16
 
17
+ theorem offs_succ (cf : Nat → Facts) {p : Prog 32} {k : Nat} {i : WordDialect.Instr 32}
18
+ (h : p[k]? = some i) : offs cf p (k + 1) = offs cf p k + isize (cf k) i := by
19
+ induction p generalizing cf k with
20
+ | nil => simp at h
21
+ | cons j js ih =>
22
+ cases k with
23
+ | zero => simp at h; subst h; simp [offs_cons, offs_zero]
24
+ | succ k =>
25
+ simp only [List.getElem?_cons_succ] at h
26
+ rw [offs_cons, offs_cons, ih (fun j => cf (j + 1)) h]; omega
27
 
28
  section Ctl
29
 
30
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
32
 
33
  theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
34
+ (hat : RAt code base (lowerInstr L base off g (.jmp t))) :
35
  ∃ x', RSteps code x x' ∧ Rel0 c p s x' ∧ x'.pc = off t := by
36
  have hat' : RAt code base [.jmp (off t)] := hat
37
  obtain ⟨f0, _⟩ := hat'
 
40
 
41
  /-- `branch t`: both outcomes. -/
42
  theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
43
+ (hpc : x.pc = base) {t : Nat} (hat : RAt code base (lowerInstr L base off g (.branch t)))
44
  {cc : W} {d : List W} (hd : s.dstack = cc :: d) :
45
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
46
+ x'.pc = (if Word.isTrue cc then off t else base + isize g (.branch t : WordDialect.Instr 32)) := by
47
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
48
  .bnez r0 (off t)]) := hat
49
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
50
+ have hufl := uf_length L (need g 1) base
51
  rw [hufl] at hatr
52
  obtain ⟨f0, f1, f2, _⟩ := hatr
53
  have hk : 1 ≤ s.dstack.length := by simp [hd]
54
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
55
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
56
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
57
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
 
65
  simp [exec, hax3, hc]
66
  refine ⟨x3.adv, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4),
67
  hr3.congr rfl rfl rfl rfl rfl rfl rfl, ?_⟩
68
+ simp [hc, Word.isTrue, M.adv, hpc3, isize]; omega
69
  · have hst4 : step code x3 = .next { x3 with pc := off t } := by
70
  rw [rstep_of_fetch (m := x3) (fetch_cast f2 (by omega))]
71
  simp [exec, hax3, hc]
 
74
  simp [hc, Word.isTrue]
75
 
76
  theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
77
+ (hat : RAt code base (lowerInstr L base off g .halt)) : RExec code x (.halted x) := by
78
  have hat' : RAt code base [.exitHalt] := hat
79
  obtain ⟨f0, _⟩ := hat'
80
  exact RExec.halt (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
 
83
  (`r8`) and writes `lr`. -/
84
  theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
85
  (hat : RAt code base [.call (off t)])
86
+ (hret : base + 1 = offs c.facts p (s.pc + 1)) (hfitR : s.rstack.length + 2 ≤ c.rcap) :
87
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
88
  x'.pc = off t := by
89
  obtain ⟨f0, _⟩ := hat
 
175
  · simp only [List.length_cons]; omega
176
 
177
  theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
178
+ (hat : RAt code base (lowerInstr L base off g .ret)) {a : Nat} {rs : List Nat}
179
+ (hr : s.rstack = a :: rs) (hsz : offs c.facts p a < 2 ^ 32) :
180
+ ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := rs } x' ∧ x'.pc = offs c.facts p a := by
181
  have hat' : RAt code base [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
182
  obtain ⟨f0, f1, f3, _⟩ := hat'
183
  have hcapR := hs.capR
 
199
  rw [hr] at hread
200
  simp only [List.length_cons, Nat.mul_zero, Nat.add_zero] at hread
201
  have hst3 : step code { x1 with pc := base + 2 } = .next { ((({ x1 with pc := base + 2 } : M).setReg
202
+ lr (ofN (offs c.facts p a))).setReg r8 (ofN (c.sp0 - 4 * rs.length))) with pc := offs c.facts p a } := by
203
  rw [rstep_of_fetch (m := { x1 with pc := base + 2 }) f3]
204
  have hx1r : x1.regs r8 = ofN (c.sp0 - 4 * (rs.length + 1)) := hrsp
205
  have hx1m : x1.mem = x.mem := rfl
206
  have hadd : ofN (c.sp0 - 4 * (rs.length + 1)) + 4#32 = ofN (c.sp0 - 4 * rs.length) := by
207
  show ofN _ + ofN 4 = _
208
  rw [ofN_add]; congr 1; omega
209
+ have hv : (ofN (offs c.facts p a)).toNat = offs c.facts p a := by
210
  simp [ofN, BitVec.toNat_ofNat, Nat.mod_eq_of_lt hsz]
211
  simp only [exec]
212
  rw [hx1m, hx1r, hread]
 
235
  omega
236
 
237
  theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
238
+ (hat : RAt code base (lowerInstr L base off g .ret)) (hr : s.rstack = []) :
239
  RExec code x (.trapped .returnUnderflow) := by
240
  have hat' : RAt code base [.bcc .ne r8 r7 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
241
  obtain ⟨f0, f1, _⟩ := hat'
 
246
 
247
  /-- `call t`: the return-stack guard, then the model's `call`. -/
248
  theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
249
+ (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off g (.call t)))
250
+ (hret : base + isize g (.call t : WordDialect.Instr 32) = offs c.facts p (s.pc + 1))
251
  (hfitR : s.rstack.length + 2 ≤ c.rcap) :
252
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
253
  x'.pc = off t := by
 
260
  exact ⟨x', hs1.trans hs', hr', hpc'⟩
261
 
262
  theorem sim_call_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
263
+ (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off g (.call t)))
264
  (h : ¬ s.rstack.length + 2 ≤ c.rcap) : RExec code x .overflow := by
265
  have hat' : RAt code base (ovfR L base ++ [.call (off t)]) := hat
266
  exact ovfR_trap hg hs hLr h hpc (rat_append.mp hat').1
backend/cortexm/CM/SimDiv.lean CHANGED
@@ -18,7 +18,7 @@ open Reg
18
  section Div
19
 
20
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
21
- {L : Layout} {base : Nat} {off : Nat → Nat}
22
 
23
  /-- `Rel0` ignores scratch registers. -/
24
  theorem rel0_scratch (hs : Rel0 c p s x) {x' : M} (hm : x'.mem = x.mem)
@@ -50,32 +50,32 @@ theorem zg_trap (hb : x.regs r1 = 0#32) {t : Nat}
50
  /-- `div` and `sdiv` share their lowering shape: load both operands, trap on a zero divisor,
51
  divide into `r0`, store and pop. `g` is the Thumb-2 division (defined at zero), `f` the IR's. -/
52
  theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
53
- (hpc : x.pc = base) (i : Instr Nat) (g f : W → W → W)
54
- (hi : ∀ m : M, exec i m = .next (m.arith r0 (g (m.regs r0) (m.regs r1))))
55
- (hfg : ∀ a b, b ≠ 0#32 → g a b = f a b)
56
- (hat : RAt code base (uf L 2 base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
57
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero, i, .store Reg.r4 4 r0,
58
  .addImm Reg.r4 4]))
59
  {a b : W} {d : List W} (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
60
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
61
- x'.pc = base + (ufSize 2 + 7) := by
62
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
63
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
64
  rw [hufl] at hatr
65
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
66
  have hk : 2 ≤ s.dstack.length := by simp [hd]
67
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
68
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
69
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
70
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
71
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
72
  have hcx3 : x3.regs r1 = b := by rw [ho3 r1 (by decide), hv2]
73
  obtain ⟨x4, hs4, hr4, hpc4, hreg4, hm4⟩ := zg_pass (code := code) hr3 hcx3 hb
74
- (t := base + ufSize 2 + 4) (by simp [ufSize]; omega)
75
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
76
  have hax4 : x4.regs r0 = a := by rw [hreg4, hv3]
77
  have hcx4 : x4.regs r1 = b := by rw [hreg4, hcx3]
78
- let x5 := x4.arith r0 (g (x4.regs r0) (x4.regs r1))
79
  have hst5 : step code x4 = .next x5 := by rw [rstep_of_fetch (fetch_cast f4 (by omega)), hi]
80
  have hr5 : Rel0 c p s x5 := arith_rel0 hr4 r0 (scratch_ne r0 (by simp)) _
81
  have hax5 : x5.regs r0 = f a b := by simp [x5, M.arith, M.setReg, hax4, hcx4, hfg a b hb]
@@ -90,19 +90,19 @@ theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x
90
  rw [e] at hr7'
91
  exact ⟨x7, ((((hs1.trans hs2).trans hs3).trans hs4).trans
92
  ((RSteps.single hst5).trans (hs6.trans hs7))), hr7', by
93
- simp [x5, M.arith, ufSize] at hpc7 hpc6 ⊢; omega⟩
94
 
95
  theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
96
  (hpc : x.pc = base) (rest : List (Instr Nat))
97
- (hat : RAt code base (uf L 2 base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
98
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero] ++ rest)))
99
  {a : W} {d : List W} (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) := by
100
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
101
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
102
  rw [hufl] at hatr
103
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
104
  have hk : 2 ≤ s.dstack.length := by simp [hd]
105
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
106
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := 0#32)
107
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
108
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -112,46 +112,46 @@ theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
112
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
113
 
114
  theorem sim_div_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
115
- (hat : RAt code base (lowerInstr L base off .div)) {a b : W} {d : List W}
116
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
117
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.udiv b :: d } x' ∧
118
- x'.pc = base + isize (.div : WordDialect.Instr 32) :=
119
  sim_divop_ok hg hL hs hpc (.divu r0 r0 r1) divu BitVec.udiv (fun _ => rfl)
120
  (fun a b h => by simp [divu, h]) hat hd hb
121
 
122
  theorem sim_div_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
123
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .div)) {a : W} {d : List W}
124
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
125
  sim_divop_zero hg hL hs hpc [.divu r0 r0 r1, .store Reg.r4 4 r0, .addImm Reg.r4 4] hat hd
126
 
127
  theorem sim_sdiv_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
128
- (hat : RAt code base (lowerInstr L base off .sdiv)) {a b : W} {d : List W}
129
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
130
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.sdiv b :: d } x' ∧
131
- x'.pc = base + isize (.sdiv : WordDialect.Instr 32) :=
132
  sim_divop_ok hg hL hs hpc (.div r0 r0 r1) divs BitVec.sdiv (fun _ => rfl)
133
  (fun a b h => by simp [divs, h]) hat hd hb
134
 
135
  theorem sim_sdiv_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
136
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .sdiv)) {a : W} {d : List W}
137
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
138
  sim_divop_zero hg hL hs hpc [.div r0 r0 r1, .store Reg.r4 4 r0, .addImm Reg.r4 4] hat hd
139
 
140
  theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
141
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .select)) {cc y v : W}
142
  {d : List W} (hd : s.dstack = cc :: y :: v :: d) :
143
  ∃ x', RSteps code x x' ∧
144
  Rel0 c p { s with dstack := (if Word.isTrue cc then v else y) :: d } x' ∧
145
- x'.pc = base + isize (.select : WordDialect.Instr 32) := by
146
- have hat' : RAt code base (uf L 3 base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
147
- .load r3 Reg.r4 8, .beqz r1 (base + ufSize 3 + 5), .movRR r0 r3, .store Reg.r4 8 r0,
148
  .addImm Reg.r4 8]) := hat
149
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
150
- have hufl : (uf L 3 base).length = 3 := by simp [uf]
151
  rw [hufl] at hatr
152
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
153
  have hk : 3 ≤ s.dstack.length := by simp [hd]
154
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
155
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
156
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
157
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := y)
@@ -160,13 +160,13 @@ theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
160
  (by simp [hd]) (rd := r3) (by simp) (disp := 8) (by simp) (fetch_cast f2 (by omega))
161
  have hcx4 : x4.regs r1 = cc := by rw [ho4 r1 (by decide), ho3 r1 (by decide), hv2]
162
  have hax4 : x4.regs r0 = y := by rw [ho4 r0 (by decide), hv3]
163
- -- after the branch (and the `mv` when `cc ≠ 0`), `r0` holds the result at `base + 3 + 5`
164
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
165
- x6.pc = base + 3 + 5 ∧ x6.regs r0 = (if Word.isTrue cc then v else y) := by
166
  by_cases hc : cc = 0#32
167
- · have hst : step code x4 = .next { x4 with pc := base + ufSize 3 + 5 } := by
168
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
169
- refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, by simp [ufSize], ?_⟩
170
  simp [hax4, Word.isTrue, hc]
171
  · have hst : step code x4 = .next x4.adv := by
172
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
@@ -189,24 +189,24 @@ theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
189
  simp [hd, hval]
190
  rw [e] at hr8'
191
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
192
- by simp [isize, ufSize]; omega⟩
193
 
194
  /-- `cmp c`: `r2 := 1`, then `bcc c` skips `r2 := 0` exactly when the IR comparison holds. -/
195
  theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
196
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off (.cmp cd)))
197
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
198
  ∃ x', RSteps code x x' ∧
199
  Rel0 c p { s with dstack := Word.ofBool (cd.eval a b) :: d } x' ∧
200
- x'.pc = base + isize (.cmp cd : WordDialect.Instr 32) := by
201
- have hat' : RAt code base (uf L 2 base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
202
- .movImm r2 1#32, .bcc cd r0 r1 (base + ufSize 2 + 5), .movImm r2 0#32, .store Reg.r4 4 r2,
203
  .addImm Reg.r4 4]) := hat
204
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
205
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
206
  rw [hufl] at hatr
207
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
208
  have hk : 2 ≤ s.dstack.length := by simp [hd]
209
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
210
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
212
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -217,11 +217,11 @@ theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dE
217
  have hax4 : x4.regs r0 = a := by rw [ho4 r0 (by decide), hv3]
218
  have hcx4 : x4.regs r1 = b := by rw [ho4 r1 (by decide), hcx3]
219
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
220
- x6.pc = base + 3 + 5 ∧ x6.regs r2 = Word.ofBool (cd.eval a b) := by
221
  by_cases hc : cd.eval a b = true
222
- · have hst : step code x4 = .next { x4 with pc := base + ufSize 2 + 5 } := by
223
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hax4, hcx4, hc]
224
- refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, by simp [ufSize], ?_⟩
225
  simp [hv4, hc, Word.ofBool]
226
  · have hc' : cd.eval a b = false := by simpa using hc
227
  have hst : step code x4 = .next x4.adv := by
@@ -242,7 +242,7 @@ theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dE
242
  simp [hd, hval]
243
  rw [e] at hr8'
244
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
245
- by simp [isize, ufSize]; omega⟩
246
 
247
  end Div
248
 
 
18
  section Div
19
 
20
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
21
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
22
 
23
  /-- `Rel0` ignores scratch registers. -/
24
  theorem rel0_scratch (hs : Rel0 c p s x) {x' : M} (hm : x'.mem = x.mem)
 
50
  /-- `div` and `sdiv` share their lowering shape: load both operands, trap on a zero divisor,
51
  divide into `r0`, store and pop. `g` is the Thumb-2 division (defined at zero), `f` the IR's. -/
52
  theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
53
+ (hpc : x.pc = base) (i : Instr Nat) (gf f : W → W → W)
54
+ (hi : ∀ m : M, exec i m = .next (m.arith r0 (gf (m.regs r0) (m.regs r1))))
55
+ (hfg : ∀ a b, b ≠ 0#32 → gf a b = f a b)
56
+ (hat : RAt code base (uf L (need g 2) base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
57
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero, i, .store Reg.r4 4 r0,
58
  .addImm Reg.r4 4]))
59
  {a b : W} {d : List W} (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
60
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
61
+ x'.pc = base + (ufSize (need g 2) + 7) := by
62
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
63
+ have hufl := uf_length L (need g 2) base
64
  rw [hufl] at hatr
65
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
66
  have hk : 2 ≤ s.dstack.length := by simp [hd]
67
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
68
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
69
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
70
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
71
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
72
  have hcx3 : x3.regs r1 = b := by rw [ho3 r1 (by decide), hv2]
73
  obtain ⟨x4, hs4, hr4, hpc4, hreg4, hm4⟩ := zg_pass (code := code) hr3 hcx3 hb
74
+ (t := base + ufSize (need g 2) + 4) (by omega)
75
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
76
  have hax4 : x4.regs r0 = a := by rw [hreg4, hv3]
77
  have hcx4 : x4.regs r1 = b := by rw [hreg4, hcx3]
78
+ let x5 := x4.arith r0 (gf (x4.regs r0) (x4.regs r1))
79
  have hst5 : step code x4 = .next x5 := by rw [rstep_of_fetch (fetch_cast f4 (by omega)), hi]
80
  have hr5 : Rel0 c p s x5 := arith_rel0 hr4 r0 (scratch_ne r0 (by simp)) _
81
  have hax5 : x5.regs r0 = f a b := by simp [x5, M.arith, M.setReg, hax4, hcx4, hfg a b hb]
 
90
  rw [e] at hr7'
91
  exact ⟨x7, ((((hs1.trans hs2).trans hs3).trans hs4).trans
92
  ((RSteps.single hst5).trans (hs6.trans hs7))), hr7', by
93
+ simp [x5, M.arith] at hpc7 hpc6 ⊢; omega⟩
94
 
95
  theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
96
  (hpc : x.pc = base) (rest : List (Instr Nat))
97
+ (hat : RAt code base (uf L (need g 2) base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
98
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero] ++ rest)))
99
  {a : W} {d : List W} (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) := by
100
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
101
+ have hufl := uf_length L (need g 2) base
102
  rw [hufl] at hatr
103
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
104
  have hk : 2 ≤ s.dstack.length := by simp [hd]
105
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
106
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := 0#32)
107
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
108
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
112
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
113
 
114
  theorem sim_div_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
115
+ (hat : RAt code base (lowerInstr L base off g .div)) {a b : W} {d : List W}
116
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
117
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.udiv b :: d } x' ∧
118
+ x'.pc = base + isize g (.div : WordDialect.Instr 32) :=
119
  sim_divop_ok hg hL hs hpc (.divu r0 r0 r1) divu BitVec.udiv (fun _ => rfl)
120
  (fun a b h => by simp [divu, h]) hat hd hb
121
 
122
  theorem sim_div_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
123
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .div)) {a : W} {d : List W}
124
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
125
  sim_divop_zero hg hL hs hpc [.divu r0 r0 r1, .store Reg.r4 4 r0, .addImm Reg.r4 4] hat hd
126
 
127
  theorem sim_sdiv_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
128
+ (hat : RAt code base (lowerInstr L base off g .sdiv)) {a b : W} {d : List W}
129
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
130
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.sdiv b :: d } x' ∧
131
+ x'.pc = base + isize g (.sdiv : WordDialect.Instr 32) :=
132
  sim_divop_ok hg hL hs hpc (.div r0 r0 r1) divs BitVec.sdiv (fun _ => rfl)
133
  (fun a b h => by simp [divs, h]) hat hd hb
134
 
135
  theorem sim_sdiv_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
136
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .sdiv)) {a : W} {d : List W}
137
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
138
  sim_divop_zero hg hL hs hpc [.div r0 r0 r1, .store Reg.r4 4 r0, .addImm Reg.r4 4] hat hd
139
 
140
  theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
141
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .select)) {cc y v : W}
142
  {d : List W} (hd : s.dstack = cc :: y :: v :: d) :
143
  ∃ x', RSteps code x x' ∧
144
  Rel0 c p { s with dstack := (if Word.isTrue cc then v else y) :: d } x' ∧
145
+ x'.pc = base + isize g (.select : WordDialect.Instr 32) := by
146
+ have hat' : RAt code base (uf L (need g 3) base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
147
+ .load r3 Reg.r4 8, .beqz r1 (base + ufSize (need g 3) + 5), .movRR r0 r3, .store Reg.r4 8 r0,
148
  .addImm Reg.r4 8]) := hat
149
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
150
+ have hufl := uf_length L (need g 3) base
151
  rw [hufl] at hatr
152
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
153
  have hk : 3 ≤ s.dstack.length := by simp [hd]
154
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
155
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
156
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
157
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := y)
 
160
  (by simp [hd]) (rd := r3) (by simp) (disp := 8) (by simp) (fetch_cast f2 (by omega))
161
  have hcx4 : x4.regs r1 = cc := by rw [ho4 r1 (by decide), ho3 r1 (by decide), hv2]
162
  have hax4 : x4.regs r0 = y := by rw [ho4 r0 (by decide), hv3]
163
+ -- after the branch (and the `mv` when `cc ≠ 0`), `r0` holds the result at `base + ufSize (need g 3) + 5`
164
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
165
+ x6.pc = base + ufSize (need g 3) + 5 ∧ x6.regs r0 = (if Word.isTrue cc then v else y) := by
166
  by_cases hc : cc = 0#32
167
+ · have hst : step code x4 = .next { x4 with pc := base + ufSize (need g 3) + 5 } := by
168
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
169
+ refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, rfl, ?_⟩
170
  simp [hax4, Word.isTrue, hc]
171
  · have hst : step code x4 = .next x4.adv := by
172
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
 
189
  simp [hd, hval]
190
  rw [e] at hr8'
191
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
192
+ by simp [isize]; omega⟩
193
 
194
  /-- `cmp c`: `r2 := 1`, then `bcc c` skips `r2 := 0` exactly when the IR comparison holds. -/
195
  theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
196
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g (.cmp cd)))
197
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
198
  ∃ x', RSteps code x x' ∧
199
  Rel0 c p { s with dstack := Word.ofBool (cd.eval a b) :: d } x' ∧
200
+ x'.pc = base + isize g (.cmp cd : WordDialect.Instr 32) := by
201
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
202
+ .movImm r2 1#32, .bcc cd r0 r1 (base + ufSize (need g 2) + 5), .movImm r2 0#32, .store Reg.r4 4 r2,
203
  .addImm Reg.r4 4]) := hat
204
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
205
+ have hufl := uf_length L (need g 2) base
206
  rw [hufl] at hatr
207
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
208
  have hk : 2 ≤ s.dstack.length := by simp [hd]
209
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
210
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
212
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
217
  have hax4 : x4.regs r0 = a := by rw [ho4 r0 (by decide), hv3]
218
  have hcx4 : x4.regs r1 = b := by rw [ho4 r1 (by decide), hcx3]
219
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
220
+ x6.pc = base + ufSize (need g 2) + 5 ∧ x6.regs r2 = Word.ofBool (cd.eval a b) := by
221
  by_cases hc : cd.eval a b = true
222
+ · have hst : step code x4 = .next { x4 with pc := base + ufSize (need g 2) + 5 } := by
223
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hax4, hcx4, hc]
224
+ refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, rfl, ?_⟩
225
  simp [hv4, hc, Word.ofBool]
226
  · have hc' : cd.eval a b = false := by simpa using hc
227
  have hst : step code x4 = .next x4.adv := by
 
242
  simp [hd, hval]
243
  rw [e] at hr8'
244
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
245
+ by simp [isize]; omega⟩
246
 
247
  end Div
248
 
backend/cortexm/CM/SimMemOps.lean CHANGED
@@ -16,7 +16,7 @@ open Reg
16
  section Ops
17
 
18
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
- {L : Layout} {base : Nat} {off : Nat → Nat}
20
 
21
  theorem ult_memSize {a : W} {n : Nat} (hn : n < 2 ^ 32) :
22
  a.ult (BitVec.ofNat 32 n) = decide (a.toNat < n) := by
@@ -65,42 +65,42 @@ theorem addr_trap (hs : Rel0 c p s x) {rt : Reg} (hrt : rt = r1 ∨ rt = r2) {n
65
 
66
  theorem sim_push_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
67
  (hr : r < c.nregs) (hLd : L.dLim = ofN (c.dBase + 4))
68
- (hat : RAt code base (lowerInstr L base off (.push r)))
69
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
70
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := s.regs r :: s.dstack } x' ∧
71
- x'.pc = base + isize (.push r : WordDialect.Instr 32) := by
72
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
73
- obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfD_pass hg hs hLd hfit hpc hato
74
  have hst : step code x0 = .next (x0.mov r0 (s.regs r)) := by
75
  rw [rstep_of_fetch (by rw [hpc0]; exact f0), ld_reg hr0 hr r0 rfl]
76
  have hr1 : Rel0 c p s (x0.mov r0 (s.regs r)) := mov_rel0 hr0 r0 (scratch_ne r0 (by simp)) _
77
- have hpc1 : (x0.mov r0 (s.regs r)).pc = base + 3 + 1 := by simp [M.mov, M.setReg, M.adv, hpc0]
78
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
79
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
80
  have hv : (x0.mov r0 (s.regs r)).regs r0 = s.regs r := by simp [M.mov, M.setReg, M.adv]
81
  rw [hv] at hr2
82
  exact ⟨x2, (hs0.trans (RSteps.single hst)).trans hs2, hr2, by simp [isize]; omega⟩
83
 
84
- theorem sim_push_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
85
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.push r)))
86
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
87
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
88
- exact ovfD_trap hg hs hLd h hpc hato
89
 
90
  theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
91
- {r : Nat} (hr : r < c.nregs) (hat : RAt code base (lowerInstr L base off (.pop r)))
92
  {a : W} {d : List W} (hd : s.dstack = a :: d) :
93
  ∃ x', RSteps code x x' ∧
94
  Rel0 c p { s with dstack := d, regs := State.setReg s.regs r a } x' ∧
95
- x'.pc = base + isize (.pop r : WordDialect.Instr 32) := by
96
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
97
  .store Reg.r5 (4 * (r : Int)) r0]) := hat
98
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
99
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
100
  rw [hufl] at hatr
101
  obtain ⟨f0, f1, f2, _⟩ := hatr
102
  have hk : 1 ≤ s.dstack.length := by simp [hd]
103
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
104
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
105
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
106
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
@@ -114,18 +114,18 @@ theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
114
  have e : s.dstack.drop 1 = d := by simp [hd]
115
  rw [e, hax3] at hr4'
116
  exact ⟨_, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4), hr4',
117
- by simp [M.adv, isize, ufSize]; omega⟩
118
 
119
  theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
120
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .load))
121
  {a v : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = some v) :
122
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := v :: d } x' ∧
123
- x'.pc = base + isize (.load : WordDialect.Instr 32) := by
124
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
125
- .bcc .ult r0 r1 (base + ufSize 1 + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6,
126
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
127
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
128
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
129
  rw [hufl] at hatr
130
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, _⟩ := hatr
131
  have hk : 1 ≤ s.dstack.length := by simp [hd]
@@ -135,11 +135,11 @@ theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
135
  have := hs.irvalid a
136
  rw [hvv] at this
137
  simpa using this.symm
138
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
139
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
140
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
141
  obtain ⟨x3, hs3, hr3, hpc3, hax3, ho3, hm3⟩ := addr_pass (code := code) hr2 (rt := r1) (by simp)
142
- (n := c.M) hMlt (t := base + ufSize 1 + 4) (by simp [ufSize]; omega) hv2 hlt (by
143
  rw [← hMs]
144
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
145
  obtain ⟨x4, hs4, hr4, hpc4, hax4, _, _⟩ := idx_steps hr3 hax3
@@ -153,17 +153,17 @@ theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
153
  simp [hd, M.mov, M.setReg, M.adv]
154
  rw [e] at hr6
155
  exact ⟨x6, ((((hs1.trans hs2).trans hs3).trans hs4).trans (RSteps.single hst5)).trans hs6, hr6,
156
- by simp [M.mov, M.setReg, M.adv, isize, ufSize] at *; omega⟩
157
 
158
  theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
159
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .load))
160
  {a : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = none) :
161
  RExec code x (.trapped .badAddress) := by
162
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
163
- .bcc .ult r0 r1 (base + ufSize 1 + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6,
164
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
165
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
166
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
167
  rw [hufl] at hatr
168
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
169
  have hk : 1 ≤ s.dstack.length := by simp [hd]
@@ -173,25 +173,25 @@ theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize
173
  have := hs.irvalid a
174
  rw [hvv] at this
175
  simpa using this
176
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
177
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
178
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
179
  exact RExec.of_steps (hs1.trans hs2) (addr_trap (code := code) hr2 (rt := r1) (by simp)
180
- (n := c.M) hMlt (t := base + ufSize 1 + 4) (by simp [ufSize]; omega) hv2 hge (by
181
  rw [← hMs]
182
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩))
183
 
184
  theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
185
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .store))
186
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) {m : Memory 32}
187
  (hw : s.mem.write? a v = some m) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, mem := m } x' ∧
189
- x'.pc = base + isize (.store : WordDialect.Instr 32) := by
190
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
191
- .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize 2 + 5),
192
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6, .store r0 0 r1, .addImm Reg.r4 8]) := hat
193
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
194
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
195
  rw [hufl] at hatr
196
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, f8, _⟩ := hatr
197
  have hk : 2 ≤ s.dstack.length := by simp [hd]
@@ -204,14 +204,14 @@ theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
204
  have := hs.irvalid a
205
  rw [hv] at this
206
  simpa using this.symm
207
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
212
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
213
  obtain ⟨x4, hs4, hr4, hpc4, hax4, ho4, hm4⟩ := addr_pass (code := code) hr3 (rt := r2) (by simp)
214
- (n := c.M) hMlt (t := base + ufSize 2 + 5) (by simp [ufSize]; omega) hax3 hlt (by
215
  rw [← hMs]
216
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩)
217
  have hcx4 : x4.regs r1 = v := by rw [ho4 r1 (by decide), hv3]
@@ -229,17 +229,17 @@ theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
229
  = { s with dstack := d, mem := m } := by simp [hd]
230
  rw [← this]; exact hr7
231
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans (RSteps.single hst6)).trans hs7,
232
- hr7', by simp [M.adv, isize, ufSize] at *; omega⟩
233
 
234
  theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
235
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .store))
236
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) (hw : s.mem.write? a v = none) :
237
  RExec code x (.trapped .badAddress) := by
238
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
239
- .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize 2 + 5),
240
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6, .store r0 0 r1, .addImm Reg.r4 8]) := hat
241
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
242
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
243
  rw [hufl] at hatr
244
  obtain ⟨f0, f1, f2, f3, f4, _⟩ := hatr
245
  have hk : 2 ≤ s.dstack.length := by simp [hd]
@@ -249,14 +249,14 @@ theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize
249
  have := hs.irvalid a
250
  rw [hvv] at this
251
  simpa using this
252
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
253
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
254
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
255
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
256
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
257
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
258
  exact RExec.of_steps ((hs1.trans hs2).trans hs3) (addr_trap (code := code) hr3 (rt := r2)
259
- (by simp) (n := c.M) hMlt (t := base + ufSize 2 + 5) (by simp [ufSize]; omega) hax3 hge (by
260
  rw [← hMs]
261
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩))
262
 
 
16
  section Ops
17
 
18
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
20
 
21
  theorem ult_memSize {a : W} {n : Nat} (hn : n < 2 ^ 32) :
22
  a.ult (BitVec.ofNat 32 n) = decide (a.toNat < n) := by
 
65
 
66
  theorem sim_push_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
67
  (hr : r < c.nregs) (hLd : L.dLim = ofN (c.dBase + 4))
68
+ (hat : RAt code base (lowerInstr L base off g (.push r)))
69
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
70
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := s.regs r :: s.dstack } x' ∧
71
+ x'.pc = base + isize g (.push r : WordDialect.Instr 32) := by
72
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
73
+ obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfG_pass hg hs hLd hfit hpc hato
74
  have hst : step code x0 = .next (x0.mov r0 (s.regs r)) := by
75
  rw [rstep_of_fetch (by rw [hpc0]; exact f0), ld_reg hr0 hr r0 rfl]
76
  have hr1 : Rel0 c p s (x0.mov r0 (s.regs r)) := mov_rel0 hr0 r0 (scratch_ne r0 (by simp)) _
77
+ have hpc1 : (x0.mov r0 (s.regs r)).pc = base + ovfSize g + 1 := by simp [M.mov, M.setReg, M.adv, hpc0]
78
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
79
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
80
  have hv : (x0.mov r0 (s.regs r)).regs r0 = s.regs r := by simp [M.mov, M.setReg, M.adv]
81
  rw [hv] at hr2
82
  exact ⟨x2, (hs0.trans (RSteps.single hst)).trans hs2, hr2, by simp [isize]; omega⟩
83
 
84
+ theorem sim_push_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
85
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.push r)))
86
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
87
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
88
+ exact ovfG_trap hn hg hs hLd h hpc hato
89
 
90
  theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
91
+ {r : Nat} (hr : r < c.nregs) (hat : RAt code base (lowerInstr L base off g (.pop r)))
92
  {a : W} {d : List W} (hd : s.dstack = a :: d) :
93
  ∃ x', RSteps code x x' ∧
94
  Rel0 c p { s with dstack := d, regs := State.setReg s.regs r a } x' ∧
95
+ x'.pc = base + isize g (.pop r : WordDialect.Instr 32) := by
96
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
97
  .store Reg.r5 (4 * (r : Int)) r0]) := hat
98
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
99
+ have hufl := uf_length L (need g 1) base
100
  rw [hufl] at hatr
101
  obtain ⟨f0, f1, f2, _⟩ := hatr
102
  have hk : 1 ≤ s.dstack.length := by simp [hd]
103
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
104
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
105
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
106
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
 
114
  have e : s.dstack.drop 1 = d := by simp [hd]
115
  rw [e, hax3] at hr4'
116
  exact ⟨_, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4), hr4',
117
+ by simp [M.adv, isize]; omega⟩
118
 
119
  theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
120
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
121
  {a v : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = some v) :
122
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := v :: d } x' ∧
123
+ x'.pc = base + isize g (.load : WordDialect.Instr 32) := by
124
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
125
+ .bcc .ult r0 r1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6,
126
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
127
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
128
+ have hufl := uf_length L (need g 1) base
129
  rw [hufl] at hatr
130
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, _⟩ := hatr
131
  have hk : 1 ≤ s.dstack.length := by simp [hd]
 
135
  have := hs.irvalid a
136
  rw [hvv] at this
137
  simpa using this.symm
138
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
139
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
140
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
141
  obtain ⟨x3, hs3, hr3, hpc3, hax3, ho3, hm3⟩ := addr_pass (code := code) hr2 (rt := r1) (by simp)
142
+ (n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hlt (by
143
  rw [← hMs]
144
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
145
  obtain ⟨x4, hs4, hr4, hpc4, hax4, _, _⟩ := idx_steps hr3 hax3
 
153
  simp [hd, M.mov, M.setReg, M.adv]
154
  rw [e] at hr6
155
  exact ⟨x6, ((((hs1.trans hs2).trans hs3).trans hs4).trans (RSteps.single hst5)).trans hs6, hr6,
156
+ by simp [M.mov, M.setReg, M.adv, isize] at *; omega⟩
157
 
158
  theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
159
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
160
  {a : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = none) :
161
  RExec code x (.trapped .badAddress) := by
162
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
163
+ .bcc .ult r0 r1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6,
164
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
165
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
166
+ have hufl := uf_length L (need g 1) base
167
  rw [hufl] at hatr
168
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
169
  have hk : 1 ≤ s.dstack.length := by simp [hd]
 
173
  have := hs.irvalid a
174
  rw [hvv] at this
175
  simpa using this
176
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
177
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
178
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
179
  exact RExec.of_steps (hs1.trans hs2) (addr_trap (code := code) hr2 (rt := r1) (by simp)
180
+ (n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hge (by
181
  rw [← hMs]
182
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩))
183
 
184
  theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
185
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
186
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) {m : Memory 32}
187
  (hw : s.mem.write? a v = some m) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, mem := m } x' ∧
189
+ x'.pc = base + isize g (.store : WordDialect.Instr 32) := by
190
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
191
+ .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize (need g 2) + 5),
192
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6, .store r0 0 r1, .addImm Reg.r4 8]) := hat
193
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
194
+ have hufl := uf_length L (need g 2) base
195
  rw [hufl] at hatr
196
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, f8, _⟩ := hatr
197
  have hk : 2 ≤ s.dstack.length := by simp [hd]
 
204
  have := hs.irvalid a
205
  rw [hv] at this
206
  simpa using this.symm
207
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
212
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
213
  obtain ⟨x4, hs4, hr4, hpc4, hax4, ho4, hm4⟩ := addr_pass (code := code) hr3 (rt := r2) (by simp)
214
+ (n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hlt (by
215
  rw [← hMs]
216
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩)
217
  have hcx4 : x4.regs r1 = v := by rw [ho4 r1 (by decide), hv3]
 
229
  = { s with dstack := d, mem := m } := by simp [hd]
230
  rw [← this]; exact hr7
231
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans (RSteps.single hst6)).trans hs7,
232
+ hr7', by simp [M.adv, isize] at *; omega⟩
233
 
234
  theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
235
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
236
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) (hw : s.mem.write? a v = none) :
237
  RExec code x (.trapped .badAddress) := by
238
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
239
+ .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize (need g 2) + 5),
240
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r6, .store r0 0 r1, .addImm Reg.r4 8]) := hat
241
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
242
+ have hufl := uf_length L (need g 2) base
243
  rw [hufl] at hatr
244
  obtain ⟨f0, f1, f2, f3, f4, _⟩ := hatr
245
  have hk : 2 ≤ s.dstack.length := by simp [hd]
 
249
  have := hs.irvalid a
250
  rw [hvv] at this
251
  simpa using this
252
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
253
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
254
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
255
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
256
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
257
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
258
  exact RExec.of_steps ((hs1.trans hs2).trans hs3) (addr_trap (code := code) hr3 (rt := r2)
259
+ (by simp) (n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hge (by
260
  rw [← hMs]
261
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩))
262
 
backend/cortexm/CM/SimOps.lean CHANGED
@@ -16,40 +16,40 @@ open Reg
16
 
17
  /-- Operand-count trap: any lowering that starts with `uf n` exits with `stackUnderflow`. -/
18
  theorem sim_uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
- {L : Layout} {base n : Nat} {rest : List (Instr Nat)} (hg : Geom c) (hs : Rel0 c p s x)
20
- (hL : L.dEnd = ofN c.dEnd) (hn : 0 < n) (hn3 : n ≤ 3) (hk : s.dstack.length < n)
21
- (hpc : x.pc = base) (hat : RAt code base (uf L n base ++ rest)) :
22
  RExec code x (.trapped .stackUnderflow) :=
23
- uf_trap hg hs hL hn hn3 hk hpc (rat_append.mp hat).1
24
 
25
  macro "mid_tac" : tactic =>
26
  `(tactic| (intro m a b ha hb
27
  simp [rseq, exec, M.arith, M.mov, M.setReg, M.adv, ha, hb, MidSpec]))
28
 
29
  theorem sim_bin_instr {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
30
- {L : Layout} {base : Nat} {off : Nat → Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
31
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (mid : List (Instr Nat))
32
  (rr : Reg) (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
33
  (hmid : MidSpec mid rr f) (hstr : ∀ j ∈ mid, j.straightR = true)
34
- (hlow : lowerInstr L base off i = uf L 2 base ++
35
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4]))
36
- (hsize : isize i = 3 + (4 + mid.length))
37
- (hat : RAt code base (lowerInstr L base off i)) {b a : W} {d : List W}
38
  (hd : s.dstack = b :: a :: d) :
39
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
40
- x'.pc = base + isize i := by
41
  rw [hlow] at hat
42
  obtain ⟨x', h1, h2, h3⟩ := sim_bin_ok hg hL hs hpc mid rr hrr f hmid hstr hat hd
43
  exact ⟨x', h1, h2, by rw [h3, hsize]; omega⟩
44
 
45
  theorem sim_uf2_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
46
- {L : Layout} {base : Nat} {off : Nat → Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
47
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (rest : List (Instr Nat))
48
- (hlow : lowerInstr L base off i = uf L 2 base ++ rest)
49
- (hat : RAt code base (lowerInstr L base off i)) (hk : s.dstack.length < 2) :
50
- RExec code x (.trapped .stackUnderflow) := by
51
  rw [hlow] at hat
52
- exact sim_uf_trap hg hs hL (by decide) (by decide) hk hpc hat
53
 
54
  /-! ### Middle computations -/
55
 
@@ -155,87 +155,87 @@ theorem midspec_rotr : MidSpec [.ror r0 r1] r0 Word.rotr := by
155
 
156
  section Ops
157
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
158
- {base : Nat} {off : Nat → Nat}
159
 
160
  theorem sim_add_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
161
- (hat : RAt code base (lowerInstr L base off .add)) {b a : W} {d : List W}
162
  (hd : s.dstack = b :: a :: d) :
163
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a + b) :: d } x' ∧
164
- x'.pc = base + isize (.add : WordDialect.Instr 32) :=
165
  sim_bin_instr hg hL hs hpc .add [.add r0 r1] r0 (by simp) (· + ·) midspec_add
166
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
167
 
168
  theorem sim_sub_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
169
- (hat : RAt code base (lowerInstr L base off .sub)) {b a : W} {d : List W}
170
  (hd : s.dstack = b :: a :: d) :
171
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a - b) :: d } x' ∧
172
- x'.pc = base + isize (.sub : WordDialect.Instr 32) :=
173
  sim_bin_instr hg hL hs hpc .sub [.sub r0 r1] r0 (by simp) (· - ·) midspec_sub
174
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
175
 
176
  theorem sim_mul_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
177
- (hat : RAt code base (lowerInstr L base off .mul)) {b a : W} {d : List W}
178
  (hd : s.dstack = b :: a :: d) :
179
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a * b) :: d } x' ∧
180
- x'.pc = base + isize (.mul : WordDialect.Instr 32) :=
181
  sim_bin_instr hg hL hs hpc .mul [.mul r0 r1] r0 (by simp) (· * ·) midspec_mul
182
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
183
 
184
  theorem sim_and_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
185
- (hat : RAt code base (lowerInstr L base off .and)) {b a : W} {d : List W}
186
  (hd : s.dstack = b :: a :: d) :
187
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a &&& b) :: d } x' ∧
188
- x'.pc = base + isize (.and : WordDialect.Instr 32) :=
189
  sim_bin_instr hg hL hs hpc .and [.and r0 r1] r0 (by simp) (· &&& ·) midspec_and
190
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
191
 
192
  theorem sim_or_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
193
- (hat : RAt code base (lowerInstr L base off .or)) {b a : W} {d : List W}
194
  (hd : s.dstack = b :: a :: d) :
195
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ||| b) :: d } x' ∧
196
- x'.pc = base + isize (.or : WordDialect.Instr 32) :=
197
  sim_bin_instr hg hL hs hpc .or [.or r0 r1] r0 (by simp) (· ||| ·) midspec_or
198
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
199
 
200
  theorem sim_xor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
201
- (hat : RAt code base (lowerInstr L base off .xor)) {b a : W} {d : List W}
202
  (hd : s.dstack = b :: a :: d) :
203
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ^^^ b) :: d } x' ∧
204
- x'.pc = base + isize (.xor : WordDialect.Instr 32) :=
205
  sim_bin_instr hg hL hs hpc .xor [.xor r0 r1] r0 (by simp) (· ^^^ ·) midspec_xor
206
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
207
 
208
  theorem sim_shl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
209
- (hat : RAt code base (lowerInstr L base off .shl)) {b a : W} {d : List W}
210
  (hd : s.dstack = b :: a :: d) :
211
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shl a b :: d } x' ∧
212
- x'.pc = base + isize (.shl : WordDialect.Instr 32) :=
213
  sim_bin_instr hg hL hs hpc .shl _ r0 (by simp) Word.shl midspec_shl
214
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
215
 
216
  theorem sim_shr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
217
- (hat : RAt code base (lowerInstr L base off .shr)) {b a : W} {d : List W}
218
  (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shr a b :: d } x' ∧
220
- x'.pc = base + isize (.shr : WordDialect.Instr 32) :=
221
  sim_bin_instr hg hL hs hpc .shr _ r0 (by simp) Word.shr midspec_shr
222
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
223
 
224
  theorem sim_rotl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
225
- (hat : RAt code base (lowerInstr L base off .rotl)) {b a : W} {d : List W}
226
  (hd : s.dstack = b :: a :: d) :
227
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotl a b :: d } x' ∧
228
- x'.pc = base + isize (.rotl : WordDialect.Instr 32) :=
229
  sim_bin_instr hg hL hs hpc .rotl _ r0 (by simp) Word.rotl midspec_rotl
230
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
231
 
232
  theorem sim_rotr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
233
- (hat : RAt code base (lowerInstr L base off .rotr)) {b a : W} {d : List W}
234
  (hd : s.dstack = b :: a :: d) :
235
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotr a b :: d } x' ∧
236
- x'.pc = base + isize (.rotr : WordDialect.Instr 32) :=
237
  sim_bin_instr hg hL hs hpc .rotr _ r0 (by simp) Word.rotr midspec_rotr
238
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
239
 
240
  end Ops
241
 
 
16
 
17
  /-- Operand-count trap: any lowering that starts with `uf n` exits with `stackUnderflow`. -/
18
  theorem sim_uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
+ {L : Layout} {base n : Nat} {g : Facts} {rest : List (Instr Nat)} (hg : Geom c) (hs : Rel0 c p s x)
20
+ (hL : L.dEnd = ofN c.dEnd) (hn : 0 < n) (hn3 : n ≤ 3) (hgd : g.lo ≤ s.dstack.length)
21
+ (hk : s.dstack.length < n) (hpc : x.pc = base) (hat : RAt code base (uf L (need g n) base ++ rest)) :
22
  RExec code x (.trapped .stackUnderflow) :=
23
+ uf_trap hg hs hL hn hn3 hgd hk hpc (rat_append.mp hat).1
24
 
25
  macro "mid_tac" : tactic =>
26
  `(tactic| (intro m a b ha hb
27
  simp [rseq, exec, M.arith, M.mov, M.setReg, M.adv, ha, hb, MidSpec]))
28
 
29
  theorem sim_bin_instr {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
30
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
31
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (mid : List (Instr Nat))
32
  (rr : Reg) (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
33
  (hmid : MidSpec mid rr f) (hstr : ∀ j ∈ mid, j.straightR = true)
34
+ (hlow : lowerInstr L base off g i = uf L (need g 2) base ++
35
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4]))
36
+ (hsize : isize g i = ufSize (need g 2) + (4 + mid.length))
37
+ (hat : RAt code base (lowerInstr L base off g i)) {b a : W} {d : List W}
38
  (hd : s.dstack = b :: a :: d) :
39
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
40
+ x'.pc = base + isize g i := by
41
  rw [hlow] at hat
42
  obtain ⟨x', h1, h2, h3⟩ := sim_bin_ok hg hL hs hpc mid rr hrr f hmid hstr hat hd
43
  exact ⟨x', h1, h2, by rw [h3, hsize]; omega⟩
44
 
45
  theorem sim_uf2_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
46
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
47
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (rest : List (Instr Nat))
48
+ (hlow : lowerInstr L base off g i = uf L (need g 2) base ++ rest)
49
+ (hat : RAt code base (lowerInstr L base off g i)) (hgd : g.lo ≤ s.dstack.length)
50
+ (hk : s.dstack.length < 2) : RExec code x (.trapped .stackUnderflow) := by
51
  rw [hlow] at hat
52
+ exact sim_uf_trap hg hs hL (by decide) (by decide) hgd hk hpc hat
53
 
54
  /-! ### Middle computations -/
55
 
 
155
 
156
  section Ops
157
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
158
+ {base : Nat} {off : Nat → Nat} {g : Facts}
159
 
160
  theorem sim_add_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
161
+ (hat : RAt code base (lowerInstr L base off g .add)) {b a : W} {d : List W}
162
  (hd : s.dstack = b :: a :: d) :
163
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a + b) :: d } x' ∧
164
+ x'.pc = base + isize g (.add : WordDialect.Instr 32) :=
165
  sim_bin_instr hg hL hs hpc .add [.add r0 r1] r0 (by simp) (· + ·) midspec_add
166
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
167
 
168
  theorem sim_sub_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
169
+ (hat : RAt code base (lowerInstr L base off g .sub)) {b a : W} {d : List W}
170
  (hd : s.dstack = b :: a :: d) :
171
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a - b) :: d } x' ∧
172
+ x'.pc = base + isize g (.sub : WordDialect.Instr 32) :=
173
  sim_bin_instr hg hL hs hpc .sub [.sub r0 r1] r0 (by simp) (· - ·) midspec_sub
174
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
175
 
176
  theorem sim_mul_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
177
+ (hat : RAt code base (lowerInstr L base off g .mul)) {b a : W} {d : List W}
178
  (hd : s.dstack = b :: a :: d) :
179
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a * b) :: d } x' ∧
180
+ x'.pc = base + isize g (.mul : WordDialect.Instr 32) :=
181
  sim_bin_instr hg hL hs hpc .mul [.mul r0 r1] r0 (by simp) (· * ·) midspec_mul
182
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
183
 
184
  theorem sim_and_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
185
+ (hat : RAt code base (lowerInstr L base off g .and)) {b a : W} {d : List W}
186
  (hd : s.dstack = b :: a :: d) :
187
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a &&& b) :: d } x' ∧
188
+ x'.pc = base + isize g (.and : WordDialect.Instr 32) :=
189
  sim_bin_instr hg hL hs hpc .and [.and r0 r1] r0 (by simp) (· &&& ·) midspec_and
190
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
191
 
192
  theorem sim_or_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
193
+ (hat : RAt code base (lowerInstr L base off g .or)) {b a : W} {d : List W}
194
  (hd : s.dstack = b :: a :: d) :
195
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ||| b) :: d } x' ∧
196
+ x'.pc = base + isize g (.or : WordDialect.Instr 32) :=
197
  sim_bin_instr hg hL hs hpc .or [.or r0 r1] r0 (by simp) (· ||| ·) midspec_or
198
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
199
 
200
  theorem sim_xor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
201
+ (hat : RAt code base (lowerInstr L base off g .xor)) {b a : W} {d : List W}
202
  (hd : s.dstack = b :: a :: d) :
203
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ^^^ b) :: d } x' ∧
204
+ x'.pc = base + isize g (.xor : WordDialect.Instr 32) :=
205
  sim_bin_instr hg hL hs hpc .xor [.xor r0 r1] r0 (by simp) (· ^^^ ·) midspec_xor
206
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
207
 
208
  theorem sim_shl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
209
+ (hat : RAt code base (lowerInstr L base off g .shl)) {b a : W} {d : List W}
210
  (hd : s.dstack = b :: a :: d) :
211
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shl a b :: d } x' ∧
212
+ x'.pc = base + isize g (.shl : WordDialect.Instr 32) :=
213
  sim_bin_instr hg hL hs hpc .shl _ r0 (by simp) Word.shl midspec_shl
214
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
215
 
216
  theorem sim_shr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
217
+ (hat : RAt code base (lowerInstr L base off g .shr)) {b a : W} {d : List W}
218
  (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shr a b :: d } x' ∧
220
+ x'.pc = base + isize g (.shr : WordDialect.Instr 32) :=
221
  sim_bin_instr hg hL hs hpc .shr _ r0 (by simp) Word.shr midspec_shr
222
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
223
 
224
  theorem sim_rotl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
225
+ (hat : RAt code base (lowerInstr L base off g .rotl)) {b a : W} {d : List W}
226
  (hd : s.dstack = b :: a :: d) :
227
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotl a b :: d } x' ∧
228
+ x'.pc = base + isize g (.rotl : WordDialect.Instr 32) :=
229
  sim_bin_instr hg hL hs hpc .rotl _ r0 (by simp) Word.rotl midspec_rotl
230
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
231
 
232
  theorem sim_rotr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
233
+ (hat : RAt code base (lowerInstr L base off g .rotr)) {b a : W} {d : List W}
234
  (hd : s.dstack = b :: a :: d) :
235
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotr a b :: d } x' ∧
236
+ x'.pc = base + isize g (.rotr : WordDialect.Instr 32) :=
237
  sim_bin_instr hg hL hs hpc .rotr _ r0 (by simp) Word.rotr midspec_rotr
238
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
239
 
240
  end Ops
241
 
backend/cortexm/CM/SimStack.lean CHANGED
@@ -64,51 +64,53 @@ theorem not_step (hs : Rel0 c p s x) (hf : code[x.pc]? = some (.not r0)) :
64
 
65
  end Steps
66
 
67
- /-- Placement of `ovfD L base ++ [i0, i1, i2]`. -/
68
- theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {base : Nat} {i0 i1 i2 : Instr Nat}
69
- (hat : RAt code base (ovfD L base ++ [i0, i1, i2])) :
70
- RAt code base (ovfD L base) ∧ code[base + 3]? = some i0 ∧ code[base + 3 + 1]? = some i1 ∧
71
- code[base + 3 + 1 + 1]? = some i2 := by
72
  obtain ⟨hato, hatr⟩ := rat_append.mp hat
73
- have hl : (ovfD L base).length = 3 := rfl
74
- rw [hl] at hatr
75
  obtain ⟨f0, f1, f2, _⟩ := hatr
76
  exact ⟨hato, f0, f1, f2⟩
77
 
78
- /-- Placement of `uf L n base ++ ovfD L (base + ufSize n) ++ [i0, i1, i2]`. -/
79
- theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {base n : Nat} (hn : 0 < n)
80
  {i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
81
- (hat : RAt code base (uf L n base ++ ovfD L (base + ufSize n) ++ rest)) :
82
- RAt code base (uf L n base) ∧ RAt code (base + 3) (ovfD L (base + 3)) ∧
83
- code[base + 6]? = some i0 ∧ code[base + 6 + 1]? = some i1 ∧ code[base + 6 + 1 + 1]? = some i2 := by
 
 
84
  subst hrest
85
- rw [ufSize_pos hn] at hat
86
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
87
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
88
- have hufl : (uf L n base).length = 3 := by rw [uf_eq L hn]; rfl
89
  rw [hufl] at hato
90
- have hl : (uf L n base ++ ovfD L (base + 3)).length = 6 := by simp [hufl, ovfD]
 
91
  rw [hl] at hatr
92
  obtain ⟨f0, f1, f2, _⟩ := hatr
93
- exact ⟨hatuf, hato, f0, f1, f2⟩
 
94
 
95
  section Ops
96
 
97
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
98
- {L : Layout} {base : Nat} {off : Nat → Nat}
99
 
100
  theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
101
- (hat : RAt code base (lowerInstr L base off .not)) {a : W} {d : List W}
102
  (hd : s.dstack = a :: d) :
103
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (~~~a) :: d } x' ∧
104
- x'.pc = base + isize (.not : WordDialect.Instr 32) := by
105
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .not r0, .store Reg.r4 0 r0]) := hat
106
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
107
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
108
  rw [hufl] at hatr
109
  obtain ⟨f0, f1, f2, _⟩ := hatr
110
  have hk : 1 ≤ s.dstack.length := by simp [hd]
111
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
112
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
113
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
114
  obtain ⟨x3, hs3, hr3, hpc3, hv3⟩ := not_step (code := code) hr2 (fetch_cast f1 (by omega))
@@ -116,57 +118,57 @@ theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
116
  (rs := r0) (disp := 0) (by simp) (fetch_cast f2 (by omega))
117
  have e : s.dstack.set 0 (x3.regs r0) = (~~~a) :: d := by simp [hd, hv3, hv2]
118
  rw [e] at hr4
119
- exact ⟨x4, ((hs1.trans hs2).trans hs3).trans hs4, hr4, by simp [isize, ufSize]; omega⟩
120
 
121
  theorem sim_dup_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
122
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .dup)) {a : W}
123
  {d : List W} (hd : s.dstack = a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
124
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: a :: d } x' ∧
125
- x'.pc = base + isize (.dup : WordDialect.Instr 32) := by
126
- obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := 1) (by decide) rfl hat
127
  have hk : 1 ≤ s.dstack.length := by simp [hd]
128
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
129
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
130
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
131
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
132
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
133
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
134
  rw [hv2, hd] at hr3
135
- exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize, ufSize]; omega⟩
136
 
137
- theorem sim_dup_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
138
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .dup)) {a : W}
139
  {d : List W} (hd : s.dstack = a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
140
  RExec code x .overflow := by
141
- obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := 1) (by decide) rfl hat
142
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) (by simp [hd]) hpc hatuf
143
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
144
 
145
  theorem sim_drop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
146
- (hat : RAt code base (lowerInstr L base off .drop)) {a : W} {d : List W}
147
  (hd : s.dstack = a :: d) :
148
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
149
- x'.pc = base + isize (.drop : WordDialect.Instr 32) := by
150
- have hat' : RAt code base (uf L 1 base ++ [.addImm Reg.r4 4]) := hat
151
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
152
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
153
  rw [hufl] at hatr
154
  obtain ⟨f0, _⟩ := hatr
155
  have hk : 1 ≤ s.dstack.length := by simp [hd]
156
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
157
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := adj_step (code := code) hg hr1 (n := 1) (by simp [hd])
158
  (δ := 4) (by simp) (fetch_cast f0 (by omega))
159
  have e : (s.dstack).drop 1 = d := by simp [hd]
160
  rw [e] at hr2
161
- exact ⟨x2, hs1.trans hs2, hr2, by simp [isize, ufSize]; omega⟩
162
 
163
  theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
164
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.word w)))
165
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
166
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := w :: s.dstack } x' ∧
167
- x'.pc = base + isize (.word w : WordDialect.Instr 32) := by
168
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
169
- obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfD_pass hg hs hLd hfit hpc hato
170
  obtain ⟨x1, hs1, hr1, hpc1, hv1, _⟩ := movimm_step (code := code) hr0 (rd := r0) (by simp)
171
  (v := w) (by rw [hpc0]; exact f0)
172
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
@@ -174,37 +176,37 @@ theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W
174
  rw [hv1] at hr2
175
  exact ⟨x2, (hs0.trans hs1).trans hs2, hr2, by simp [isize]; omega⟩
176
 
177
- theorem sim_word_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
178
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.word w)))
179
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
180
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
181
- exact ovfD_trap hg hs hLd h hpc hato
182
 
183
  theorem sim_ptr_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
184
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.ptr q)))
185
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
186
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := q.toWord :: s.dstack } x' ∧
187
- x'.pc = base + isize (.ptr q : WordDialect.Instr 32) :=
188
- sim_word_ok (L := L) (off := off) hg hs hpc q.toWord hLd hat hfit
189
 
190
- theorem sim_ptr_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
191
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.ptr q)))
192
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow :=
193
- sim_word_ovf (L := L) (off := off) hg hs hpc q.toWord hLd hat h
194
 
195
  theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
196
- (hat : RAt code base (lowerInstr L base off .swap)) {b a : W} {d : List W}
197
  (hd : s.dstack = b :: a :: d) :
198
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: d } x' ∧
199
- x'.pc = base + isize (.swap : WordDialect.Instr 32) := by
200
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
201
  .store Reg.r4 0 r1, .store Reg.r4 4 r0]) := hat
202
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
203
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
204
  rw [hufl] at hatr
205
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
206
  have hk : 2 ≤ s.dstack.length := by simp [hd]
207
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -220,45 +222,45 @@ theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
220
  have e : (s.dstack.set 0 (x3.regs r1)).set 1 (x4.regs r0) = a :: b :: d := by
221
  simp [hd, hv3, hreg4, hax3]
222
  rw [e] at hr5'
223
- exact ⟨x5, (((hs1.trans hs2).trans hs3).trans hs4).trans hs5, hr5', by simp [isize, ufSize]; omega⟩
224
 
225
  theorem sim_over_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
226
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .over)) {b a : W}
227
  {d : List W} (hd : s.dstack = b :: a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
228
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: a :: d } x' ∧
229
- x'.pc = base + isize (.over : WordDialect.Instr 32) := by
230
- obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := 2) (by decide) rfl hat
231
  have hk : 2 ≤ s.dstack.length := by simp [hd]
232
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
233
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
234
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 1) (v := a)
235
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f0 (by omega))
236
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
237
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
238
  rw [hv2, hd] at hr3
239
- exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize, ufSize]; omega⟩
240
 
241
- theorem sim_over_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
242
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .over)) {b a : W}
243
  {d : List W} (hd : s.dstack = b :: a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
244
  RExec code x .overflow := by
245
- obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := 2) (by decide) rfl hat
246
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) (by simp [hd]) hpc hatuf
247
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
248
 
249
  theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
250
- (hat : RAt code base (lowerInstr L base off .rot)) {cc b a : W} {d : List W}
251
  (hd : s.dstack = cc :: b :: a :: d) :
252
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: cc :: b :: d } x' ∧
253
- x'.pc = base + isize (.rot : WordDialect.Instr 32) := by
254
- have hat' : RAt code base (uf L 3 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
255
  .load r2 Reg.r4 8, .store Reg.r4 0 r2, .store Reg.r4 4 r0, .store Reg.r4 8 r1]) := hat
256
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
257
- have hufl : (uf L 3 base).length = 3 := by simp [uf]
258
  rw [hufl] at hatr
259
  obtain ⟨f0, f1, f2, f3, f4, f5, _⟩ := hatr
260
  have hk : 3 ≤ s.dstack.length := by simp [hd]
261
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
262
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
263
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
264
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := b)
@@ -284,7 +286,7 @@ theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
284
  simp [hd, hv4, hreg5, hreg6, hax4, hcx4]
285
  rw [e] at hr7'
286
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans hs6).trans hs7, hr7',
287
- by simp [isize, ufSize]; omega⟩
288
 
289
  end Ops
290
 
 
64
 
65
  end Steps
66
 
67
+ /-- Placement of `ovf L g base ++ [i0, i1, i2]`. -/
68
+ theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {g : Facts} {base : Nat}
69
+ {i0 i1 i2 : Instr Nat} (hat : RAt code base (ovf L g base ++ [i0, i1, i2])) :
70
+ RAt code base (ovf L g base) ∧ code[base + ovfSize g]? = some i0 ∧
71
+ code[base + ovfSize g + 1]? = some i1 ∧ code[base + ovfSize g + 1 + 1]? = some i2 := by
72
  obtain ⟨hato, hatr⟩ := rat_append.mp hat
73
+ rw [ovf_length] at hatr
 
74
  obtain ⟨f0, f1, f2, _⟩ := hatr
75
  exact ⟨hato, f0, f1, f2⟩
76
 
77
+ /-- Placement of `uf L n base ++ ovf L g (base + ufSize n) ++ [i0, i1, i2]`. -/
78
+ theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {g : Facts} {base n : Nat}
79
  {i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
80
+ (hat : RAt code base (uf L n base ++ ovf L g (base + ufSize n) ++ rest)) :
81
+ RAt code base (uf L n base) ∧ RAt code (base + ufSize n) (ovf L g (base + ufSize n)) ∧
82
+ code[base + ufSize n + ovfSize g]? = some i0 ∧
83
+ code[base + ufSize n + ovfSize g + 1]? = some i1 ∧
84
+ code[base + ufSize n + ovfSize g + 1 + 1]? = some i2 := by
85
  subst hrest
 
86
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
87
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
88
+ have hufl := uf_length L n base
89
  rw [hufl] at hato
90
+ have hl : (uf L n base ++ ovf L g (base + ufSize n)).length = ufSize n + ovfSize g := by
91
+ simp [hufl, ovf_length]
92
  rw [hl] at hatr
93
  obtain ⟨f0, f1, f2, _⟩ := hatr
94
+ exact ⟨hatuf, hato, by simpa [Nat.add_assoc] using f0, by simpa [Nat.add_assoc] using f1,
95
+ by simpa [Nat.add_assoc] using f2⟩
96
 
97
  section Ops
98
 
99
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
100
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
101
 
102
  theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
103
+ (hat : RAt code base (lowerInstr L base off g .not)) {a : W} {d : List W}
104
  (hd : s.dstack = a :: d) :
105
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (~~~a) :: d } x' ∧
106
+ x'.pc = base + isize g (.not : WordDialect.Instr 32) := by
107
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .not r0, .store Reg.r4 0 r0]) := hat
108
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
109
+ have hufl := uf_length L (need g 1) base
110
  rw [hufl] at hatr
111
  obtain ⟨f0, f1, f2, _⟩ := hatr
112
  have hk : 1 ≤ s.dstack.length := by simp [hd]
113
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
114
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
115
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
116
  obtain ⟨x3, hs3, hr3, hpc3, hv3⟩ := not_step (code := code) hr2 (fetch_cast f1 (by omega))
 
118
  (rs := r0) (disp := 0) (by simp) (fetch_cast f2 (by omega))
119
  have e : s.dstack.set 0 (x3.regs r0) = (~~~a) :: d := by simp [hd, hv3, hv2]
120
  rw [e] at hr4
121
+ exact ⟨x4, ((hs1.trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
122
 
123
  theorem sim_dup_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
124
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .dup)) {a : W}
125
  {d : List W} (hd : s.dstack = a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
126
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: a :: d } x' ∧
127
+ x'.pc = base + isize g (.dup : WordDialect.Instr 32) := by
128
+ obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := need g 1) rfl hat
129
  have hk : 1 ≤ s.dstack.length := by simp [hd]
130
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
131
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
132
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
133
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
134
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
135
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
136
  rw [hv2, hd] at hr3
137
+ exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
138
 
139
+ theorem sim_dup_ovf (hn : g.noOvf = false) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
140
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .dup)) {a : W}
141
  {d : List W} (hd : s.dstack = a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
142
  RExec code x .overflow := by
143
+ obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := need g 1) rfl hat
144
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by simp [hd]) hpc hatuf
145
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
146
 
147
  theorem sim_drop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
148
+ (hat : RAt code base (lowerInstr L base off g .drop)) {a : W} {d : List W}
149
  (hd : s.dstack = a :: d) :
150
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
151
+ x'.pc = base + isize g (.drop : WordDialect.Instr 32) := by
152
+ have hat' : RAt code base (uf L (need g 1) base ++ [.addImm Reg.r4 4]) := hat
153
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
154
+ have hufl := uf_length L (need g 1) base
155
  rw [hufl] at hatr
156
  obtain ⟨f0, _⟩ := hatr
157
  have hk : 1 ≤ s.dstack.length := by simp [hd]
158
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
159
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := adj_step (code := code) hg hr1 (n := 1) (by simp [hd])
160
  (δ := 4) (by simp) (fetch_cast f0 (by omega))
161
  have e : (s.dstack).drop 1 = d := by simp [hd]
162
  rw [e] at hr2
163
+ exact ⟨x2, hs1.trans hs2, hr2, by simp [isize]; omega⟩
164
 
165
  theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
166
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.word w)))
167
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
168
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := w :: s.dstack } x' ∧
169
+ x'.pc = base + isize g (.word w : WordDialect.Instr 32) := by
170
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
171
+ obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfG_pass hg hs hLd hfit hpc hato
172
  obtain ⟨x1, hs1, hr1, hpc1, hv1, _⟩ := movimm_step (code := code) hr0 (rd := r0) (by simp)
173
  (v := w) (by rw [hpc0]; exact f0)
174
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
 
176
  rw [hv1] at hr2
177
  exact ⟨x2, (hs0.trans hs1).trans hs2, hr2, by simp [isize]; omega⟩
178
 
179
+ theorem sim_word_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
180
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.word w)))
181
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
182
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
183
+ exact ovfG_trap hn hg hs hLd h hpc hato
184
 
185
  theorem sim_ptr_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
186
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.ptr q)))
187
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := q.toWord :: s.dstack } x' ∧
189
+ x'.pc = base + isize g (.ptr q : WordDialect.Instr 32) :=
190
+ sim_word_ok (L := L) (off := off) (g := g) hg hs hpc q.toWord hLd hat hfit
191
 
192
+ theorem sim_ptr_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
193
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.ptr q)))
194
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow :=
195
+ sim_word_ovf (L := L) (off := off) (g := g) hn hg hs hpc q.toWord hLd hat h
196
 
197
  theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
198
+ (hat : RAt code base (lowerInstr L base off g .swap)) {b a : W} {d : List W}
199
  (hd : s.dstack = b :: a :: d) :
200
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: d } x' ∧
201
+ x'.pc = base + isize g (.swap : WordDialect.Instr 32) := by
202
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
203
  .store Reg.r4 0 r1, .store Reg.r4 4 r0]) := hat
204
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
205
+ have hufl := uf_length L (need g 2) base
206
  rw [hufl] at hatr
207
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
208
  have hk : 2 ≤ s.dstack.length := by simp [hd]
209
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
210
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
211
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
212
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
222
  have e : (s.dstack.set 0 (x3.regs r1)).set 1 (x4.regs r0) = a :: b :: d := by
223
  simp [hd, hv3, hreg4, hax3]
224
  rw [e] at hr5'
225
+ exact ⟨x5, (((hs1.trans hs2).trans hs3).trans hs4).trans hs5, hr5', by simp [isize]; omega⟩
226
 
227
  theorem sim_over_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
228
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .over)) {b a : W}
229
  {d : List W} (hd : s.dstack = b :: a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
230
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: a :: d } x' ∧
231
+ x'.pc = base + isize g (.over : WordDialect.Instr 32) := by
232
+ obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := need g 2) rfl hat
233
  have hk : 2 ≤ s.dstack.length := by simp [hd]
234
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
235
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
236
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 1) (v := a)
237
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f0 (by omega))
238
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
239
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
240
  rw [hv2, hd] at hr3
241
+ exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
242
 
243
+ theorem sim_over_ovf (hn : g.noOvf = false) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
244
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .over)) {b a : W}
245
  {d : List W} (hd : s.dstack = b :: a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
246
  RExec code x .overflow := by
247
+ obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := need g 2) rfl hat
248
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by simp [hd]) hpc hatuf
249
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
250
 
251
  theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
252
+ (hat : RAt code base (lowerInstr L base off g .rot)) {cc b a : W} {d : List W}
253
  (hd : s.dstack = cc :: b :: a :: d) :
254
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: cc :: b :: d } x' ∧
255
+ x'.pc = base + isize g (.rot : WordDialect.Instr 32) := by
256
+ have hat' : RAt code base (uf L (need g 3) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
257
  .load r2 Reg.r4 8, .store Reg.r4 0 r2, .store Reg.r4 4 r0, .store Reg.r4 8 r1]) := hat
258
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
259
+ have hufl := uf_length L (need g 3) base
260
  rw [hufl] at hatr
261
  obtain ⟨f0, f1, f2, f3, f4, f5, _⟩ := hatr
262
  have hk : 3 ≤ s.dstack.length := by simp [hd]
263
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
264
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
265
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
266
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := b)
 
286
  simp [hd, hv4, hreg5, hreg6, hax4, hcx4]
287
  rw [e] at hr7'
288
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans hs6).trans hs7, hr7',
289
+ by simp [isize]; omega⟩
290
 
291
  end Ops
292
 
backend/cortexm/CM/SimStep.lean CHANGED
@@ -53,10 +53,13 @@ theorem shape3 {l : List W} (h : 3 ≤ l.length) : ∃ cc y v d, l = cc :: y ::
53
  | nil => simp at h
54
  | cons v d => exact ⟨cc, y, v, d, rfl⟩
55
 
56
- theorem lowerInstr_uf (L : Layout) (base : Nat) (off : Nat → Nat) (i : WordDialect.Instr 32)
57
  (h : 0 < i.pops) :
58
- ∃ rest, lowerInstr L base off i = uf L i.pops base ++ rest ∧ i.pops ≤ 3 := by
59
- cases i <;> first | exact ⟨_, rfl, by simp [Instr.pops]⟩ | exact absurd h (by simp [Instr.pops])
 
 
 
60
 
61
  theorem Rel0.setPc {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (h : Rel0 c p s x) (n : Nat) :
62
  Rel0 c p { s with pc := n } x :=
@@ -78,14 +81,15 @@ theorem sim_trapped {code : List (Instr Nat)} {t : Trap} (h : RExec code x (.tra
78
  Sim c p code x (.trapped t) := h
79
 
80
  theorem rel_fall {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i) {s' : State 32}
81
- {x' : M} (h0 : Rel0 c p s' x') (hpc : x'.pc = offs p s.pc + isize i) :
82
  Rel c p { s' with pc := s.pc + 1 } x' :=
83
- ⟨h0.setPc _, by rw [hpc, offs_succ hi]⟩
84
 
85
  theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
86
  (hLd : L.dLim = ofN (c.dBase + 4)) (hLr : L.rGap = ofN (4 * c.rcap - 8))
87
  (hLa : L.aEnd = ofN c.aEnd) (hLal : L.aLim = ofN (c.aBase + 4))
88
- (hsz : ∀ k, offs p k < 2 ^ 32) (hs : Rel c p s x)
 
89
  {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i)
90
  (hreg : ∀ r, (i = .push r ∨ i = .pop r) → r < c.nregs) :
91
  Sim c p (lowerProg L p) x (WordDialect.exec i s) ∨
@@ -93,27 +97,39 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
93
  have nfD : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → ¬ Fits c s := fun h hf => h hf.1
94
  have nfR : ¬ s.rstack.length + 2 ≤ c.rcap → ¬ Fits c s := fun h hf => h hf.2.1
95
  have nfA : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd → ¬ Fits c s := fun h hf => h hf.2.2
96
- have hpc : x.pc = offs p s.pc := hs.2
97
  have hs0 : Rel0 c p s x := hs.1
98
  have hat := lowerProg_at L p s.pc i hi
 
 
 
 
 
 
 
 
 
 
 
99
  by_cases hk : s.dstack.length < i.pops
100
  · rw [exec_underflow i s hk]
101
- obtain ⟨rest, hlow, h3⟩ := lowerInstr_uf L (offs p s.pc) (offs p) i (by omega)
 
102
  rw [hlow] at hat
103
- exact .inl <| sim_trapped (sim_uf_trap hg hs0 hL (by omega) h3 hk hpc hat)
104
  · have hk' : i.pops ≤ s.dstack.length := by omega
105
  cases i with
106
  | word w =>
107
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
108
  rotate_left
109
- · exact .inr ⟨nfD hf, sim_word_ovf hg hs0 hpc w hLd hat hf⟩
110
  obtain ⟨x', hst, h0, hpc'⟩ := sim_word_ok hg hs0 hpc w hLd hat hf
111
  rw [exec_word]
112
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
113
  | ptr q =>
114
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
115
  rotate_left
116
- · exact .inr ⟨nfD hf, sim_ptr_ovf hg hs0 hpc q hLd hat hf⟩
117
  obtain ⟨x', hst, h0, hpc'⟩ := sim_ptr_ok hg hs0 hpc q hLd hat hf
118
  rw [exec_ptr]
119
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -238,8 +254,9 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
238
  simp only [hc', Bool.false_eq_true, if_false] at hpc'
239
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
240
  | call t =>
241
- have hret : offs p s.pc + isize (.call t : WordDialect.Instr 32) = offs p (s.pc + 1) := by
242
- rw [offs_succ hi]
 
243
  by_cases hf : s.rstack.length + 2 ≤ c.rcap
244
  rotate_left
245
  · exact .inr ⟨nfR hf, sim_call_ovf hg hs0 hpc hLr hat hf⟩
@@ -259,7 +276,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
259
  | push r =>
260
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
261
  rotate_left
262
- · exact .inr ⟨nfD hf, sim_push_ovf hg hs0 hpc hLd hat hf⟩
263
  obtain ⟨x', hst, h0, hpc'⟩ := sim_push_ok hg hs0 hpc (hreg r (Or.inl rfl)) hLd hat hf
264
  rw [exec_push]
265
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -272,7 +289,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
272
  obtain ⟨a, d, hd⟩ := shape1 (by simpa [Instr.pops] using hk')
273
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
274
  rotate_left
275
- · exact .inr ⟨nfD hf, sim_dup_ovf hg hL hs0 hpc hLd hat hd hf⟩
276
  obtain ⟨x', hst, h0, hpc'⟩ := sim_dup_ok hg hL hs0 hpc hLd hat hd hf
277
  rw [exec_dup hd]
278
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -290,7 +307,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
290
  obtain ⟨b, a, d, hd⟩ := shape2 (by simpa [Instr.pops] using hk')
291
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
292
  rotate_left
293
- · exact .inr ⟨nfD hf, sim_over_ovf hg hL hs0 hpc hLd hat hd hf⟩
294
  obtain ⟨x', hst, h0, hpc'⟩ := sim_over_ok hg hL hs0 hpc hLd hat hd hf
295
  rw [exec_over hd]
296
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -320,7 +337,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
320
  | cons a as =>
321
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
322
  rotate_left
323
- · exact .inr ⟨nfD hf, sim_fromr_ovf hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
324
  obtain ⟨x', hst, h0, hpc'⟩ := sim_fromr_ok hg hLa hLd hs0 hpc hat ha hf
325
  have e : WordDialect.exec WordDialect.Instr.fromr s =
326
  .next { s with pc := s.pc + 1, dstack := a :: s.dstack, astack := as } := by
@@ -337,7 +354,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
337
  | cons a as =>
338
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
339
  rotate_left
340
- · exact .inr ⟨nfD hf, sim_rfetch_ovf hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
341
  obtain ⟨x', hst, h0, hpc'⟩ := sim_rfetch_ok hg hLa hLd hs0 hpc hat ha hf
342
  have e : WordDialect.exec WordDialect.Instr.rfetch s = s.fall (a :: s.dstack) := by
343
  simp [WordDialect.exec, ha]
 
53
  | nil => simp at h
54
  | cons v d => exact ⟨cc, y, v, d, rfl⟩
55
 
56
+ theorem lowerInstr_uf (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts) (i : WordDialect.Instr 32)
57
  (h : 0 < i.pops) :
58
+ ∃ rest, lowerInstr L base off g i = uf L (need g i.pops) base ++ rest ∧ i.pops ≤ 3 := by
59
+ cases i <;> first
60
+ | exact ⟨_, rfl, by simp [Instr.pops]⟩
61
+ | exact ⟨_, List.append_assoc _ _ _, by simp [Instr.pops]⟩
62
+ | exact absurd h (by simp [Instr.pops])
63
 
64
  theorem Rel0.setPc {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (h : Rel0 c p s x) (n : Nat) :
65
  Rel0 c p { s with pc := n } x :=
 
81
  Sim c p code x (.trapped t) := h
82
 
83
  theorem rel_fall {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i) {s' : State 32}
84
+ {x' : M} (h0 : Rel0 c p s' x') (hpc : x'.pc = offs c.facts p s.pc + isize (c.facts s.pc) i) :
85
  Rel c p { s' with pc := s.pc + 1 } x' :=
86
+ ⟨h0.setPc _, by rw [hpc, offs_succ c.facts hi]⟩
87
 
88
  theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
89
  (hLd : L.dLim = ofN (c.dBase + 4)) (hLr : L.rGap = ofN (4 * c.rcap - 8))
90
  (hLa : L.aEnd = ofN c.aEnd) (hLal : L.aLim = ofN (c.aBase + 4))
91
+ (hLf : L.facts = c.facts) (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hs : Rel c p s x)
92
+ (hgd : c.cert s.pc ≤ s.dstack.length) (hub : s.dstack.length ≤ c.ub s.pc)
93
  {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i)
94
  (hreg : ∀ r, (i = .push r ∨ i = .pop r) → r < c.nregs) :
95
  Sim c p (lowerProg L p) x (WordDialect.exec i s) ∨
 
97
  have nfD : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → ¬ Fits c s := fun h hf => h hf.1
98
  have nfR : ¬ s.rstack.length + 2 ≤ c.rcap → ¬ Fits c s := fun h hf => h hf.2.1
99
  have nfA : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd → ¬ Fits c s := fun h hf => h hf.2.2
100
+ have hpc : x.pc = offs c.facts p s.pc := hs.2
101
  have hs0 : Rel0 c p s x := hs.1
102
  have hat := lowerProg_at L p s.pc i hi
103
+ rw [hLf] at hat
104
+ -- Where the stack may be full, the overflow guard is there: the bound left it out only where
105
+ -- one more word fits.
106
+ have hnov : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → (c.facts s.pc).noOvf = false := by
107
+ intro hf
108
+ cases h : (c.facts s.pc).noOvf
109
+ · rfl
110
+ · exfalso; apply hf
111
+ simp only [Cfg.facts, decide_eq_true_eq] at h
112
+ unfold Cfg.dCap at h
113
+ omega
114
  by_cases hk : s.dstack.length < i.pops
115
  · rw [exec_underflow i s hk]
116
+ obtain ⟨rest, hlow, h3⟩ := lowerInstr_uf L (offs c.facts p s.pc) (offs c.facts p) (c.facts s.pc) i
117
+ (by omega)
118
  rw [hlow] at hat
119
+ exact .inl <| sim_trapped (sim_uf_trap hg hs0 hL (by omega) h3 hgd hk hpc hat)
120
  · have hk' : i.pops ≤ s.dstack.length := by omega
121
  cases i with
122
  | word w =>
123
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
124
  rotate_left
125
+ · exact .inr ⟨nfD hf, sim_word_ovf (hnov hf) hg hs0 hpc w hLd hat hf⟩
126
  obtain ⟨x', hst, h0, hpc'⟩ := sim_word_ok hg hs0 hpc w hLd hat hf
127
  rw [exec_word]
128
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
129
  | ptr q =>
130
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
131
  rotate_left
132
+ · exact .inr ⟨nfD hf, sim_ptr_ovf (hnov hf) hg hs0 hpc q hLd hat hf⟩
133
  obtain ⟨x', hst, h0, hpc'⟩ := sim_ptr_ok hg hs0 hpc q hLd hat hf
134
  rw [exec_ptr]
135
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
254
  simp only [hc', Bool.false_eq_true, if_false] at hpc'
255
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
256
  | call t =>
257
+ have hret : offs c.facts p s.pc + isize (c.facts s.pc) (.call t : WordDialect.Instr 32) =
258
+ offs c.facts p (s.pc + 1) := by
259
+ rw [offs_succ c.facts hi]
260
  by_cases hf : s.rstack.length + 2 ≤ c.rcap
261
  rotate_left
262
  · exact .inr ⟨nfR hf, sim_call_ovf hg hs0 hpc hLr hat hf⟩
 
276
  | push r =>
277
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
278
  rotate_left
279
+ · exact .inr ⟨nfD hf, sim_push_ovf (hnov hf) hg hs0 hpc hLd hat hf⟩
280
  obtain ⟨x', hst, h0, hpc'⟩ := sim_push_ok hg hs0 hpc (hreg r (Or.inl rfl)) hLd hat hf
281
  rw [exec_push]
282
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
289
  obtain ⟨a, d, hd⟩ := shape1 (by simpa [Instr.pops] using hk')
290
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
291
  rotate_left
292
+ · exact .inr ⟨nfD hf, sim_dup_ovf (hnov hf) hg hL hs0 hpc hLd hat hd hf⟩
293
  obtain ⟨x', hst, h0, hpc'⟩ := sim_dup_ok hg hL hs0 hpc hLd hat hd hf
294
  rw [exec_dup hd]
295
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
307
  obtain ⟨b, a, d, hd⟩ := shape2 (by simpa [Instr.pops] using hk')
308
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
309
  rotate_left
310
+ · exact .inr ⟨nfD hf, sim_over_ovf (hnov hf) hg hL hs0 hpc hLd hat hd hf⟩
311
  obtain ⟨x', hst, h0, hpc'⟩ := sim_over_ok hg hL hs0 hpc hLd hat hd hf
312
  rw [exec_over hd]
313
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
337
  | cons a as =>
338
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
339
  rotate_left
340
+ · exact .inr ⟨nfD hf, sim_fromr_ovf (hnov hf) hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
341
  obtain ⟨x', hst, h0, hpc'⟩ := sim_fromr_ok hg hLa hLd hs0 hpc hat ha hf
342
  have e : WordDialect.exec WordDialect.Instr.fromr s =
343
  .next { s with pc := s.pc + 1, dstack := a :: s.dstack, astack := as } := by
 
354
  | cons a as =>
355
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
356
  rotate_left
357
+ · exact .inr ⟨nfD hf, sim_rfetch_ovf (hnov hf) hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
358
  obtain ⟨x', hst, h0, hpc'⟩ := sim_rfetch_ok hg hLa hLd hs0 hpc hat ha hf
359
  have e : WordDialect.exec WordDialect.Instr.rfetch s = s.fall (a :: s.dstack) := by
360
  simp [WordDialect.exec, ha]
backend/cortexm/CMMain.lean CHANGED
@@ -13,7 +13,8 @@ For each program it
13
  3. runs the image on the emulated Stellaris LM3S6965 evaluation board, a Cortex-M3 with 256 KiB
14
  of flash and 64 KiB of SRAM (`qemu-system-arm -M lm3s6965evb`). It takes the initial stack
15
  pointer and reset vector from the vector table, copies `.data` from flash to SRAM, prints
16
- through UART0 and stops through semihosting. The emulated flash ignores writes, so a program
 
17
  that ran on the flash copy of `.data` instead of the RAM copy would fail the comparison,
18
  4. runs the same IR program under the Lean semantics at width 32 (`WordDialect.run`), and
19
  5. compares the exit status and the dumped data stack, IR memory and virtual registers.
@@ -23,8 +24,13 @@ samples and generated programs narrowed to 32-bit words, 32-bit edge cases, the
23
  and overflow programs, and Forth source files compiled at width 32. `check` also runs the
24
  hand-written data-processing programs of `CM.DataOps`.
25
 
26
- Usage: `cmc check [fuzzCount]`, `cmc emit <sample>`, `cmc forth <file.fs> [memWords]`,
27
- `cmc emit-forth <file.fs> [memWords]`.
 
 
 
 
 
28
  -/
29
 
30
  open WordDialect
@@ -43,12 +49,23 @@ def rBase : Nat := 0x20009000
43
  def rcap : Nat := 4096
44
  def rEnd : Nat := rBase + 4 * rcap
45
 
46
- def runtimeFor (s : Sample32) : CM.Emit.Runtime :=
47
- { dEnd := dEnd, capacity := capacity, rEnd := rEnd, rcap := rcap, memImage := s.mem,
48
- nregs := s.nregs, aEnd := aEnd, acap := acap }
49
-
50
- def asmFor (s : Sample32) : String :=
51
- CM.Emit.program (runtimeFor s) (CM.lowerProg (runtimeFor s).layout s.prog)
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  /-- The vector table and code in flash from address 0 (where a Cortex-M reads its initial stack
54
  pointer and reset vector); `.data` in the first 4 KiB of SRAM, loaded into flash after the code
@@ -64,8 +81,8 @@ def linkerScript : String :=
64
 
65
  def workDir : String := "/tmp/cmc"
66
 
67
- /-- Assemble, link and run one assembly file; the UART output and the exit status. -/
68
- def runAsm (name asm : String) : IO (Except String (String × UInt32)) := do
69
  IO.FS.createDirAll workDir
70
  let base := s!"{workDir}/{name}"
71
  IO.FS.writeFile (base ++ ".s") asm
@@ -77,21 +94,28 @@ def runAsm (name asm : String) : IO (Except String (String × UInt32)) := do
77
  let l ← IO.Process.output
78
  { cmd := "ld.lld", args := #["-T", workDir ++ "/link.ld", "-o", base, base ++ ".o"] }
79
  if l.exitCode != 0 then return .error s!"ld.lld failed: {l.stderr}"
80
- let child ← IO.Process.spawn
81
- { cmd := "qemu-system-arm",
82
- args := #["-machine", "lm3s6965evb", "-kernel", base, "-display", "none", "-serial", "stdio",
83
- "-monitor", "none", "-semihosting-config", "enable=on,target=native"],
84
- stdout := .piped, stderr := .null, stdin := .null }
85
- let out ← readAll child.stdout ByteArray.empty
86
- let code ← child.wait
87
- match String.fromUTF8? out with
88
- | some t => return .ok (t, code)
89
- | none => return .error "UART output is not text"
90
-
91
- def runNative : Runner32 := fun s => do
92
- match ← runAsm s.name (asmFor s) with
 
 
 
 
 
 
 
93
  | .error e => return .error e
94
- | .ok (out, code) => return (if code != 0 then .ok (.trap code.toNat) else parseHexDump s out)
95
 
96
  /-! ## Hand-written Cortex-M programs (`CM.DataOps`) -/
97
 
@@ -106,7 +130,7 @@ def isaAsm (code : List (CM.Instr Nat)) : String :=
106
  CM.Emit.body code ++ s!".Lhalt:\n\t{CM.Emit.la "r12" "rbuf"}\n" ++
107
  String.join (isaRegs.zipIdx.map fun (x, k) => s!"\tstr {CM.Emit.regName x}, [r12, #{4 * k}]\n") ++
108
  CM.Emit.uartOn r ++ s!"\t{CM.Emit.la "r7" "rbuf"}\n\tmovs r9, #12\n\tbl putws\n" ++
109
- "\tmovs r1, #0\n\tb .Lexit\n" ++ CM.Emit.devices r ++
110
  "\t.data\n\t.balign 4\nrbuf:\n\t.zero 48\nexitblk:\n\t.word 0, 0\n"
111
 
112
  def checkIsaProg (name : String) (code : List (CM.Instr Nat)) : IO Bool := do
@@ -114,14 +138,15 @@ def checkIsaProg (name : String) (code : List (CM.Instr Nat)) : IO Bool := do
114
  (·.map BitVec.toNat)
115
  let got ← runAsm name (isaAsm code)
116
  match model, got with
117
- | some exp, .ok (out, 0) =>
118
- match hexWords out with
119
- | some g =>
 
 
120
  if exp == g then IO.println s!"PASS {name} {g}"; return true
121
  else IO.println s!"FAIL {name}\n lean: {exp}\n target: {g}"; return false
122
- | none => IO.println s!"ERROR {name}: malformed output {out}"; return false
123
  | none, _ => IO.println s!"ERROR {name}: the model did not halt"; return false
124
- | _, .ok (_, c) => IO.println s!"ERROR {name}: exit {c}"; return false
125
  | _, .error e => IO.println s!"ERROR {name}: {e}"; return false
126
 
127
  /-- A pseudo-random program over `r0 … r11`: initialise all twelve (some to small values, so
@@ -167,16 +192,19 @@ def parseMem (rest : List String) : Option Nat :=
167
  | [m] => m.toNat?
168
  | _ => none
169
 
170
- def main (args : List String) : IO UInt32 := do
 
 
 
171
  match args with
172
  | ["emit", name] =>
173
  match allSamples32.find? (·.name == name) with
174
- | some s => IO.println (asmFor s); return 0
175
  | none => IO.eprintln "unknown sample"; return 1
176
  | "forth" :: path :: rest =>
177
  match parseMem rest with
178
  | none => IO.eprintln "usage: cmc forth <file.fs> [memWords]"; return 2
179
- | some m => return (if ← check32 runNative (← forthFileSample32 path m) then 0 else 1)
180
  | "emit-forth" :: path :: rest =>
181
  match parseMem rest with
182
  | none => IO.eprintln "usage: cmc emit-forth <file.fs> [memWords]"; return 2
@@ -184,10 +212,33 @@ def main (args : List String) : IO UInt32 := do
184
  let s ← forthFileSample32 path m
185
  match s.buildError with
186
  | some e => IO.eprintln e; return 1
187
- | none => IO.println (asmFor s); return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  | "check" :: rest =>
189
  let count := match rest with | [n] => n.toNat! | _ => 200
190
- let ok ← checkAll32 runNative count
 
191
  let isa ← checkIsa 100
192
- return (if ok && isa then 0 else 1)
193
- | _ => IO.eprintln "usage: cmc check [fuzzCount] | cmc emit <sample> | cmc forth <file.fs> [memWords] | cmc emit-forth <file.fs> [memWords]"; return 2
 
13
  3. runs the image on the emulated Stellaris LM3S6965 evaluation board, a Cortex-M3 with 256 KiB
14
  of flash and 64 KiB of SRAM (`qemu-system-arm -M lm3s6965evb`). It takes the initial stack
15
  pointer and reset vector from the vector table, copies `.data` from flash to SRAM, prints
16
+ through UART0 and ends the run there (an `EXIT` line and the status, then `wfi`; the harness
17
+ reads up to that line and stops the emulator). The emulated flash ignores writes, so a program
18
  that ran on the flash copy of `.data` instead of the RAM copy would fail the comparison,
19
  4. runs the same IR program under the Lean semantics at width 32 (`WordDialect.run`), and
20
  5. compares the exit status and the dumped data stack, IR memory and virtual registers.
 
24
  and overflow programs, and Forth source files compiled at width 32. `check` also runs the
25
  hand-written data-processing programs of `CM.DataOps`.
26
 
27
+ For a real board, `cmc image` writes the ELF, an Intel HEX file and the UART transcript a correct
28
+ run prints; `cmc verify` checks a serial log captured from the board (`docs/HARDWARE.md`).
29
+
30
+ Usage: `cmc check [fuzzCount]`, `cmc image <file.fs> [memWords]`,
31
+ `cmc verify <file.fs> <serial.log> [memWords]`, `cmc emit <sample>`, `cmc forth <file.fs> [memWords]`,
32
+ `cmc emit-forth <file.fs> [memWords]`, `cmc stats <file.fs> [memWords]` (the guards the depth
33
+ certificates leave out); `--no-opt` with any of them lowers with every guard.
34
  -/
35
 
36
  open WordDialect
 
49
  def rcap : Nat := 4096
50
  def rEnd : Nat := rBase + 4 * rcap
51
 
52
+ /-- The runtime for one program. With `opt` the lowering uses the checked stack-depth
53
+ certificate `certTable` and the checked upper bounds `upperTable` (`WordDialect.Depth`), which
54
+ decide the guards left out; their checks are all the correctness theorem needs, so the analyses
55
+ are not trusted. Without it every guard stays. -/
56
+ def runtimeFor (s : Sample32) (opt : Bool := true) : CM.Emit.Runtime :=
57
+ let r : CM.Emit.Runtime :=
58
+ { dEnd := dEnd, capacity := capacity, rEnd := rEnd, rcap := rcap, memImage := s.mem,
59
+ nregs := s.nregs, aEnd := aEnd, acap := acap }
60
+ if opt then
61
+ let tbl := certTable s.prog
62
+ let up := upperTable s.prog r.dCap
63
+ { r with cert := fun k => tbl.getD k 0, ub := fun k => upperAt up r.dCap k }
64
+ else r
65
+
66
+ def asmFor (s : Sample32) (opt : Bool := true) : String :=
67
+ let r := runtimeFor s opt
68
+ CM.Emit.program r (CM.lowerProg r.layout s.prog)
69
 
70
  /-- The vector table and code in flash from address 0 (where a Cortex-M reads its initial stack
71
  pointer and reset vector); `.data` in the first 4 KiB of SRAM, loaded into flash after the code
 
81
 
82
  def workDir : String := "/tmp/cmc"
83
 
84
+ /-- Assemble and link one assembly file; the ELF's path. -/
85
+ def buildElf (name asm : String) : IO (Except String String) := do
86
  IO.FS.createDirAll workDir
87
  let base := s!"{workDir}/{name}"
88
  IO.FS.writeFile (base ++ ".s") asm
 
94
  let l ← IO.Process.output
95
  { cmd := "ld.lld", args := #["-T", workDir ++ "/link.ld", "-o", base, base ++ ".o"] }
96
  if l.exitCode != 0 then return .error s!"ld.lld failed: {l.stderr}"
97
+ return .ok base
98
+
99
+ /-- Build, run on the emulated board, and read its UART up to the end of the run (the `EXIT`
100
+ line and the status). The emulator is then stopped: the board itself sleeps for good. -/
101
+ def runAsm (name asm : String) : IO (Except String String) := do
102
+ match ← buildElf name asm with
103
+ | .error e => return .error e
104
+ | .ok elf =>
105
+ let child ← IO.Process.spawn
106
+ { cmd := "qemu-system-arm",
107
+ args := #["-machine", "lm3s6965evb", "-kernel", elf, "-display", "none", "-serial", "stdio",
108
+ "-monitor", "none"],
109
+ stdout := .piped, stderr := .null, stdin := .null }
110
+ let out ← readUntilExit child.stdout
111
+ child.kill
112
+ let _ ← child.wait
113
+ return .ok out
114
+
115
+ def runNative (opt : Bool := true) : Runner32 := fun s => do
116
+ match ← runAsm s.name (asmFor s opt) with
117
  | .error e => return .error e
118
+ | .ok out => return parseTranscript s out
119
 
120
  /-! ## Hand-written Cortex-M programs (`CM.DataOps`) -/
121
 
 
130
  CM.Emit.body code ++ s!".Lhalt:\n\t{CM.Emit.la "r12" "rbuf"}\n" ++
131
  String.join (isaRegs.zipIdx.map fun (x, k) => s!"\tstr {CM.Emit.regName x}, [r12, #{4 * k}]\n") ++
132
  CM.Emit.uartOn r ++ s!"\t{CM.Emit.la "r7" "rbuf"}\n\tmovs r9, #12\n\tbl putws\n" ++
133
+ "\tmovs r1, #0\n\tb .Lfinish\n" ++ CM.Emit.devices r ++
134
  "\t.data\n\t.balign 4\nrbuf:\n\t.zero 48\nexitblk:\n\t.word 0, 0\n"
135
 
136
  def checkIsaProg (name : String) (code : List (CM.Instr Nat)) : IO Bool := do
 
138
  (·.map BitVec.toNat)
139
  let got ← runAsm name (isaAsm code)
140
  match model, got with
141
+ | some exp, .ok out =>
142
+ let ls := transcriptLines out
143
+ let i := ls.findIdx (· == exitMarker)
144
+ match hexWords (String.intercalate "\n" (ls.take i)), hexWords (ls.getD (i + 1) "") with
145
+ | some g, some [0] =>
146
  if exp == g then IO.println s!"PASS {name} {g}"; return true
147
  else IO.println s!"FAIL {name}\n lean: {exp}\n target: {g}"; return false
148
+ | _, _ => IO.println s!"ERROR {name}: malformed output {out}"; return false
149
  | none, _ => IO.println s!"ERROR {name}: the model did not halt"; return false
 
150
  | _, .error e => IO.println s!"ERROR {name}: {e}"; return false
151
 
152
  /-- A pseudo-random program over `r0 … r11`: initialise all twelve (some to small values, so
 
192
  | [m] => m.toNat?
193
  | _ => none
194
 
195
+ def main (args0 : List String) : IO UInt32 := do
196
+ -- `--no-opt` keeps every guard (the lowering without depth certificates).
197
+ let opt := !args0.contains "--no-opt"
198
+ let args := args0.filter (· != "--no-opt")
199
  match args with
200
  | ["emit", name] =>
201
  match allSamples32.find? (·.name == name) with
202
+ | some s => IO.println (asmFor s opt); return 0
203
  | none => IO.eprintln "unknown sample"; return 1
204
  | "forth" :: path :: rest =>
205
  match parseMem rest with
206
  | none => IO.eprintln "usage: cmc forth <file.fs> [memWords]"; return 2
207
+ | some m => return (if ← check32 (runNative opt) (← forthFileSample32 path m) then 0 else 1)
208
  | "emit-forth" :: path :: rest =>
209
  match parseMem rest with
210
  | none => IO.eprintln "usage: cmc emit-forth <file.fs> [memWords]"; return 2
 
212
  let s ← forthFileSample32 path m
213
  match s.buildError with
214
  | some e => IO.eprintln e; return 1
215
+ | none => IO.println (asmFor s opt); return 0
216
+ | "image" :: path :: rest =>
217
+ match parseMem rest with
218
+ | none => IO.eprintln "usage: cmc image <file.fs> [memWords]"; return 2
219
+ | some m =>
220
+ let s ← forthFileSample32 path m
221
+ if let some e := s.buildError then IO.eprintln e; return 1
222
+ match ← buildElf s.name (asmFor s opt) with
223
+ | .error e => IO.eprintln e; return 1
224
+ | .ok elf => writeImage s elf s.name
225
+ | "verify" :: path :: log :: rest =>
226
+ match parseMem rest with
227
+ | none => IO.eprintln "usage: cmc verify <file.fs> <serial.log> [memWords]"; return 2
228
+ | some m => verifyLog (← forthFileSample32 path m) log
229
+ | "stats" :: path :: rest =>
230
+ match parseMem rest with
231
+ | none => IO.eprintln "usage: cmc stats <file.fs> [memWords]"; return 2
232
+ | some m =>
233
+ let s ← forthFileSample32 path m
234
+ if let some e := s.buildError then IO.eprintln e; return 1
235
+ let r := runtimeFor s
236
+ IO.println (guardStats s r.cert r.ub r.dCap)
237
+ return 0
238
  | "check" :: rest =>
239
  let count := match rest with | [n] => n.toNat! | _ => 200
240
+ let ok ← checkAll32 (runNative opt) count
241
+ let okc ← checkCapacity32 (runNative opt) capacity
242
  let isa ← checkIsa 100
243
+ return (if ok && okc && isa then 0 else 1)
244
+ | _ => IO.eprintln "usage: cmc check [fuzzCount] | cmc emit <sample> | cmc forth <file.fs> [memWords] | cmc emit-forth <file.fs> [memWords] | cmc image <file.fs> [memWords] | cmc verify <file.fs> <serial.log> [memWords]"; return 2
backend/cortexm0/CM0/Boot.lean CHANGED
@@ -4,7 +4,7 @@ import CM0.Init
4
  # CM0.Boot
5
 
6
  Booting from flash, proved. A Cortex-M runs from flash: the vector table and code are there, and
7
- `.data` (IR memory, the register file and the semihosting block) is linked to RAM with its load
8
  address in flash. The reset handler first copies `.data` to RAM with the ten-instruction loop
9
  `Emit.copyCode`, printed from the model like the lowered program, then runs the prologue.
10
 
@@ -260,15 +260,15 @@ theorem copy_holds {r : Runtime} {ld : Loader} {lma : Nat} {x0 : M} (h : FlashHo
260
  copy loop runs to its end; from there the prologue runs, and the lowered code reaches the outcome
261
  the IR reaches from `State.init` on the memory image, or exits with `overflow`. -/
262
  theorem boot_correct (r : Runtime) (ld : Loader) (lma : Nat) (p : Prog 32)
263
- (hlen : 36 * p.length < 2 ^ 32) (hreg : RegsOk (cfgOf r ld) p) {o : Outcome 32}
264
- (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M}
265
  (h : FlashHolds r ld lma x0) (hpc : x0.pc = 0) :
266
  ∃ x1, RSteps (copyCode (ofN lma) (ofN ld.mb) (dataWords r)) x0 x1 ∧ x1.pc = 10 ∧
267
  rseq (prologueCode r ld) x1 = .next { entryState r ld x1 with pc := x1.pc + 8 } ∧
268
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x1) o ∨
269
  RExec (lowerProg r.layout p) (entryState r ld x1) .overflow) := by
270
  obtain ⟨x1, hs, hpc1, hh⟩ := copy_holds h hpc
271
- exact ⟨x1, hs, hpc1, binary_correct r ld p hlen hreg hx hh⟩
272
 
273
  end Emit
274
  end CM0
 
4
  # CM0.Boot
5
 
6
  Booting from flash, proved. A Cortex-M runs from flash: the vector table and code are there, and
7
+ `.data` (IR memory, the register file and the two-word status block) is linked to RAM with its load
8
  address in flash. The reset handler first copies `.data` to RAM with the ten-instruction loop
9
  `Emit.copyCode`, printed from the model like the lowered program, then runs the prologue.
10
 
 
260
  copy loop runs to its end; from there the prologue runs, and the lowered code reaches the outcome
261
  the IR reaches from `State.init` on the memory image, or exits with `overflow`. -/
262
  theorem boot_correct (r : Runtime) (ld : Loader) (lma : Nat) (p : Prog 32)
263
+ (hlen : 36 * p.length < 2 ^ 32) (hreg : RegsOk (cfgOf r ld) p) (hok : certOk p r.cert = true)
264
+ (hub : UbSound p r.dCap r.ub) {o : Outcome 32} (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M}
265
  (h : FlashHolds r ld lma x0) (hpc : x0.pc = 0) :
266
  ∃ x1, RSteps (copyCode (ofN lma) (ofN ld.mb) (dataWords r)) x0 x1 ∧ x1.pc = 10 ∧
267
  rseq (prologueCode r ld) x1 = .next { entryState r ld x1 with pc := x1.pc + 8 } ∧
268
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x1) o ∨
269
  RExec (lowerProg r.layout p) (entryState r ld x1) .overflow) := by
270
  obtain ⟨x1, hs, hpc1, hh⟩ := copy_holds h hpc
271
+ exact ⟨x1, hs, hpc1, binary_correct r ld p hlen hreg hok hub hx hh⟩
272
 
273
  end Emit
274
  end CM0
backend/cortexm0/CM0/Correct.lean CHANGED
@@ -25,6 +25,11 @@ Hypotheses of both (all explicit):
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
 
 
 
 
 
28
  * `hsz` code indices fit in 32 bits;
29
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
30
  -/
@@ -44,15 +49,30 @@ def Final (c : Cfg) (p : Prog 32) (code : List (Instr Nat)) (x : M) : Outcome 32
44
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
45
  | .trapped t => RExec code x (.trapped t)
46
 
47
- theorem offs_ge {p : Prog 32} {k : Nat} (h : p.length ≤ k) : offs p k = offs p p.length := by
48
- simp [offs, List.take_of_length_le h, List.take_length]
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
51
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
52
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
53
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
54
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
55
- {s : State 32} {x : M} (hs : Rel c p s x) :
 
 
56
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
57
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
58
  cases hi : p[s.pc]? with
@@ -65,43 +85,48 @@ theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
65
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
66
  · omega
67
  obtain ⟨f0, _⟩ := lowerProg_stub L p
68
- have hpc : x.pc = offs p p.length := by rw [hs.2, offs_ge hge]
 
69
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
70
  | some i =>
71
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
72
  rw [hst]
73
- exact sim_exec hg hL hMs hLd hLr hLa hLal hsz hs hi (fun r hr => hreg s.pc i hi r hr)
74
 
75
  /-- Whole-program preservation, with no capacity hypothesis: the ARMv6-M code reaches the IR
76
  outcome, or exits with `overflow` because a stack was full. -/
77
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
78
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
79
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
80
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
81
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
82
- ∀ {x : M}, Rel c p s x →
83
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
84
  induction h with
85
  | @halt s s' hst =>
86
- intro x hs
87
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
88
  rw [hst] at this
89
  rcases this with this | ⟨_, h6⟩
90
  · exact .inl this
91
  · exact .inr h6
92
  | @trap s t hst =>
93
- intro x hs
94
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
95
  rw [hst] at this
96
  rcases this with this | ⟨_, h6⟩
97
  · exact .inl this
98
  · exact .inr h6
99
  | @next s s' o hst _ ih =>
100
- intro x hs
101
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
102
  rw [hst] at this
103
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
104
- · rcases ih hrel with hih | h6
105
  · left
106
  cases o with
107
  | next _ => exact hih.elim
@@ -117,31 +142,35 @@ every reachable state), no overflow guard fires and the outcome is exactly the I
117
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
118
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
119
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
120
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
121
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
122
- ∀ {x : M}, Rel c p s x → (∀ s', Steps p s s' → Fits c s') →
123
  Final c p (lowerProg L p) x o := by
124
  induction h with
125
  | @halt s s' hst =>
126
- intro x hs hb
127
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
128
  rw [hst] at this
129
  rcases this with this | ⟨hnf, _⟩
130
  · exact this
131
  · exact absurd (hb s .refl) hnf
132
  | @trap s t hst =>
133
- intro x hs hb
134
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
135
  rw [hst] at this
136
  rcases this with this | ⟨hnf, _⟩
137
  · exact this
138
  · exact absurd (hb s .refl) hnf
139
  | @next s s' o hst _ ih =>
140
- intro x hs hb
141
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
142
  rw [hst] at this
143
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
144
- · have hih := ih hrel (fun s'' hss => hb s'' (Steps.cons hst hss))
145
  cases o with
146
  | next _ => exact hih.elim
147
  | halted r5 =>
@@ -159,7 +188,7 @@ theorem init_rel {c : Cfg} {p : Prog 32} {s0 : State 32} {x0 : M} (hg : Geom c)
159
  (h13 : x0.regs Reg.r8 = ofN c.mb) (h12 : x0.regs Reg.r9 = ofN c.sp0)
160
  (hsp : x0.regs Reg.sp = ofN c.sp0) (hbp : x0.regs Reg.r6 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
161
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
162
- (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs p s0.pc) : Rel c p s0 x0 :=
163
  ⟨{ r4 := by simpa [hd] using h15
164
  r5 := h14
165
  r8 := h13
 
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
28
+ * `hLf`, `hok`, `I` the code was lowered with the configuration's facts: its lower-bound
29
+ certificate passes `certOk`, and its upper bound `c.ub` is implied by an
30
+ invariant `I` kept by every step within the data stack's capacity (`hIs`,
31
+ `hIb`; `WordDialect.UbSound`); the runs carry `DepthInv` and `I`, so every
32
+ underflow or overflow guard the lowering left out would have passed;
33
  * `hsz` code indices fit in 32 bits;
34
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
35
  -/
 
49
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
50
  | .trapped t => RExec code x (.trapped t)
51
 
52
+ theorem offs_ge (cf : Nat → Facts) {p : Prog 32} {k : Nat} (h : p.length ≤ k) :
53
+ offs cf p k = offs cf p p.length := by
54
+ induction p generalizing cf k with
55
+ | nil => cases k <;> simp [offs]
56
+ | cons i is ih =>
57
+ cases k with
58
+ | zero => simp at h
59
+ | succ k => simp only [List.length_cons, offs]; rw [ih _ (by simp at h; omega)]
60
+
61
+ /-- A related state is within the data stack's capacity. -/
62
+ theorem cap_of_rel {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hs : Rel c p s x) :
63
+ s.dstack.length ≤ c.dCap := by
64
+ have := hs.1.capD
65
+ unfold Cfg.dCap
66
+ omega
67
 
68
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
69
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
70
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
71
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
72
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
73
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
74
+ {s : State 32} {x : M} (hs : Rel c p s x) (hdi : DepthInv c.cert s)
75
+ (hub : s.dstack.length ≤ c.ub s.pc) :
76
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
77
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
78
  cases hi : p[s.pc]? with
 
85
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
86
  · omega
87
  obtain ⟨f0, _⟩ := lowerProg_stub L p
88
+ rw [hLf] at f0
89
+ have hpc : x.pc = offs c.facts p p.length := by rw [hs.2, offs_ge _ hge]
90
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
91
  | some i =>
92
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
93
  rw [hst]
94
+ exact sim_exec hg hL hMs hLd hLr hLa hLal hLf hsz hs hdi.depth hub hi (fun r hr => hreg s.pc i hi r hr)
95
 
96
  /-- Whole-program preservation, with no capacity hypothesis: the ARMv6-M code reaches the IR
97
  outcome, or exits with `overflow` because a stack was full. -/
98
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
99
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
100
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
101
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
102
+ {I : State 32 → Prop}
103
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
104
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
105
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
106
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
107
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s →
108
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
109
  induction h with
110
  | @halt s s' hst =>
111
+ intro x hs hdi hbi
112
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
113
  rw [hst] at this
114
  rcases this with this | ⟨_, h6⟩
115
  · exact .inl this
116
  · exact .inr h6
117
  | @trap s t hst =>
118
+ intro x hs hdi hbi
119
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
120
  rw [hst] at this
121
  rcases this with this | ⟨_, h6⟩
122
  · exact .inl this
123
  · exact .inr h6
124
  | @next s s' o hst _ ih =>
125
+ intro x hs hdi hbi
126
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
127
  rw [hst] at this
128
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
129
+ · rcases ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) with hih | h6
130
  · left
131
  cases o with
132
  | next _ => exact hih.elim
 
142
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
143
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
144
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
145
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
146
+ {I : State 32 → Prop}
147
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
148
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
149
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
150
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
151
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s → (∀ s', Steps p s s' → Fits c s') →
152
  Final c p (lowerProg L p) x o := by
153
  induction h with
154
  | @halt s s' hst =>
155
+ intro x hs hdi hbi hb
156
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
157
  rw [hst] at this
158
  rcases this with this | ⟨hnf, _⟩
159
  · exact this
160
  · exact absurd (hb s .refl) hnf
161
  | @trap s t hst =>
162
+ intro x hs hdi hbi hb
163
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
164
  rw [hst] at this
165
  rcases this with this | ⟨hnf, _⟩
166
  · exact this
167
  · exact absurd (hb s .refl) hnf
168
  | @next s s' o hst _ ih =>
169
+ intro x hs hdi hbi hb
170
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
171
  rw [hst] at this
172
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
173
+ · have hih := ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) (fun s'' hss => hb s'' (Steps.cons hst hss))
174
  cases o with
175
  | next _ => exact hih.elim
176
  | halted r5 =>
 
188
  (h13 : x0.regs Reg.r8 = ofN c.mb) (h12 : x0.regs Reg.r9 = ofN c.sp0)
189
  (hsp : x0.regs Reg.sp = ofN c.sp0) (hbp : x0.regs Reg.r6 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
190
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
191
+ (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs c.facts p s0.pc) : Rel c p s0 x0 :=
192
  ⟨{ r4 := by simpa [hd] using h15
193
  r5 := h14
194
  r8 := h13
backend/cortexm0/CM0/Emit.lean CHANGED
@@ -19,12 +19,13 @@ RAM with `copyCode` (proved in `CM0/Boot.lean`), runs the prologue, then jumps o
19
  pool to the lowered code. The rest of the runtime (`epilogue`) is hand-written assembly. It
20
  * implements `exitHalt` as: write `depth`, the data stack, IR memory and the virtual register
21
  file to the UART (the nRF51 UART at `uartBase`, waiting for `EVENTS_TXDRDY` after each byte),
22
- one word per line as eight hexadecimal digits, then stop with status 0,
23
- * implements `exitTrap t` as stopping with status `code t`, and `exitOvf` (stack overflow) with
24
  status 6.
25
 
26
- The machine is stopped through semihosting (`bkpt 0xab`, operation `SYS_EXIT_EXTENDED`); on a
27
- board running without a debugger, that one stub is replaced by whatever signals the end of a run.
 
28
  -/
29
 
30
  namespace WordDialect
@@ -148,9 +149,20 @@ def instr (k : Nat) (i : Instr Nat) : String := instrP "" k i
148
  def body (code : List (Instr Nat)) : String :=
149
  String.intercalate "\n" (code.zipIdx.map fun (i, k) => s!"{lbl k}:\n\t{instr k i}") ++ "\n"
150
 
 
 
 
 
 
 
 
 
 
 
 
151
  /-- Data-stack placement (`capacity` words ending at `dEnd`), return-stack placement (`rcap`
152
  entries ending at `rEnd`, the stack `sp` points into), IR memory image, register-file size,
153
- auxiliary-stack placement (`acap` words ending at `aEnd`), and the UART address. The three
154
  stacks are sections the linker places at fixed addresses (`cm0c` uses a linker script). -/
155
  structure Runtime where
156
  dEnd : Nat
@@ -162,6 +174,19 @@ structure Runtime where
162
  aEnd : Nat
163
  acap : Nat
164
  uartBase : Nat := 0x40002000
 
 
 
 
 
 
 
 
 
 
 
 
 
165
 
166
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
167
 
@@ -169,14 +194,18 @@ def Runtime.rBase (r : Runtime) : Nat := r.rEnd - 4 * r.rcap
169
 
170
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
171
 
 
 
 
172
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
173
  def Runtime.layout (r : Runtime) : Layout :=
174
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
175
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
176
- aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4) }
 
177
 
178
  /-- The `.data` image: IR memory, the register file (`nregs + 1` words) and the two-word
179
- semihosting parameter block, in the order `epilogue` lays them out. The image is linked into
180
  flash and copied to RAM at reset. -/
181
  def dataImage (r : Runtime) : List Nat := r.memImage ++ List.replicate (r.nregs + 3) 0
182
 
@@ -214,14 +243,96 @@ def prologue (r : Runtime) : String :=
214
  s!"\t{la "r5" "regfile"}\n\t{li "r4" r.dEnd}\n\t{li "r6" r.aEnd}\n" ++
215
  "\tb .L0\n\t.ltorg\n"
216
 
217
- /-- Output and exit routines, entered only from `exitHalt`, `exitTrap` and `exitOvf`, so they
218
- may use any register. `putc` writes `r0` to the UART; `putw` writes `r6` as eight hexadecimal
219
- digits and a newline; `putws` writes the `r5` words at address `r4`. `.Lexit` stops the machine
220
- through semihosting with status `r1`. -/
221
- def devices (r : Runtime) : String :=
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  "\t.thumb_func\nputc:\n" ++
223
- s!"\t{la "r2" (hex r.uartBase)}\n\t{la "r1" "0x51C"}\n\tstr r0, [r2, r1]\n\t{la "r1" "0x11C"}\n" ++
224
- "1:\tldr r3, [r2, r1]\n\tcmp r3, #0\n\tbeq 1b\n\tmovs r3, #0\n\tstr r3, [r2, r1]\n\tbx lr\n" ++
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  "\t.thumb_func\nputw:\n\tmov r10, lr\n\tmovs r7, #28\n" ++
226
  "2:\tmov r0, r6\n\tlsrs r0, r7\n\tmovs r1, #15\n\tands r0, r1\n\tcmp r0, #10\n\tbhs 3f\n" ++
227
  "\tadds r0, #48\n\tb 4f\n3:\tadds r0, #87\n4:\tbl putc\n" ++
@@ -229,13 +340,16 @@ def devices (r : Runtime) : String :=
229
  "\t.thumb_func\nputws:\n\tmov r9, lr\n" ++
230
  "5:\tcmp r5, #0\n\tbeq 6f\n\tldr r6, [r4]\n\tadds r4, #4\n\tbl putw\n\tsubs r5, #1\n\tb 5b\n" ++
231
  "6:\tbx r9\n" ++
232
- s!".Lexit:\n\t{la "r0" "exitblk"}\n\t{la "r2" "0x20026"}\n" ++
233
- "\tstr r2, [r0]\n\tstr r1, [r0, #4]\n\tmov r1, r0\n\tmovs r0, #0x20\n\tbkpt 0xab\n7:\tb 7b\n"
 
 
 
 
 
234
 
235
- /-- Turn on the UART (`ENABLE = 4`) and its transmitter (`TASKS_STARTTX`). -/
236
- def uartOn (r : Runtime) : String :=
237
- s!"\t{la "r2" (hex r.uartBase)}\n\t{la "r1" "0x500"}\n\tmovs r3, #4\n\tstr r3, [r2, r1]\n" ++
238
- "\tmovs r3, #1\n\tstr r3, [r2, #8]\n"
239
 
240
  def epilogue (r : Runtime) : String :=
241
  let m := r.memImage.length
@@ -245,7 +359,7 @@ def epilogue (r : Runtime) : String :=
245
  "\tbl putw\n\tbl putws\n" ++
246
  s!"\tmov r4, r8\n\t{li "r5" m}\n\tbl putws\n" ++
247
  s!"\tmov r4, r11\n\t{li "r5" r.nregs}\n\tbl putws\n" ++
248
- "\tmovs r1, #0\n\tb .Lexit\n" ++
249
  String.join ((List.range 6).map fun k => s!".Ltrap{k + 1}:\n\tmovs r1, #{k + 1}\n\tb .Lexit\n") ++
250
  devices r ++ "\t.ltorg\n" ++
251
  "\t.data\n\t.balign 4\nirmem:\n" ++
 
19
  pool to the lowered code. The rest of the runtime (`epilogue`) is hand-written assembly. It
20
  * implements `exitHalt` as: write `depth`, the data stack, IR memory and the virtual register
21
  file to the UART (the nRF51 UART at `uartBase`, waiting for `EVENTS_TXDRDY` after each byte),
22
+ one word per line as eight hexadecimal digits, then end with status 0,
23
+ * implements `exitTrap t` as ending with status `code t`, and `exitOvf` (stack overflow) with
24
  status 6.
25
 
26
+ A run ends on the UART, the same way on the emulator and on a board, with no debugger: after the
27
+ dump (if any) the runtime prints a line `EXIT` and the status, stores the status at `exitblk`, and
28
+ sleeps. Before printing it starts the crystal and sets up the UART as a board needs (`uartInit`).
29
  -/
30
 
31
  namespace WordDialect
 
149
  def body (code : List (Instr Nat)) : String :=
150
  String.intercalate "\n" (code.zipIdx.map fun (i, k) => s!"{lbl k}:\n\t{instr k i}") ++ "\n"
151
 
152
+ /-- The chip family the runtime's device code is written for. The lowered program and its proofs
153
+ do not depend on it; only the hand-written set-up, output and end-of-run code does. -/
154
+ inductive Soc where
155
+ /-- Nordic nRF51/nRF52 (BBC micro:bit): the UART at `uartBase`. -/
156
+ | nrf
157
+ /-- Microchip SAM D21 (SAM D21 Curiosity Nano, `ATSAMD21G17D`): SERCOM5 as a USART on
158
+ PA22 (TX, pad 0) and PB22 (RX, pad 2), the debugger's virtual COM port; the yellow LED on PB10;
159
+ the switch SW0 on PB11. -/
160
+ | samd21
161
+ deriving DecidableEq, Repr
162
+
163
  /-- Data-stack placement (`capacity` words ending at `dEnd`), return-stack placement (`rcap`
164
  entries ending at `rEnd`, the stack `sp` points into), IR memory image, register-file size,
165
+ auxiliary-stack placement (`acap` words ending at `aEnd`), the UART address and its pins. The three
166
  stacks are sections the linker places at fixed addresses (`cm0c` uses a linker script). -/
167
  structure Runtime where
168
  dEnd : Nat
 
174
  aEnd : Nat
175
  acap : Nat
176
  uartBase : Nat := 0x40002000
177
+ /-- The UART pins as the nRF `PSEL` registers take them, and the TX pin's number in GPIO
178
+ port 0. The defaults are the BBC micro:bit V1's (TX P0.24, RX P0.25). -/
179
+ txPin : Nat := 24
180
+ rxPsel : Nat := 25
181
+ /-- The chip family of the board (see `Soc`). -/
182
+ soc : Soc := .nrf
183
+ /-- The stack-depth certificate the code is lowered with (`WordDialect.Depth`); the driver
184
+ passes `safeCert` of the program. The default claims nothing and keeps every guard. -/
185
+ cert : Nat → Nat := fun _ => 0
186
+ /-- The upper bound on the data-stack depth the code is lowered with; the driver passes
187
+ `upperTable` of the program against `dCap` (`WordDialect.Depth`). An overflow guard is left out
188
+ where `ub k + 1 ≤ dCap`; the default (`2^32` everywhere) shows no room, so every guard stays. -/
189
+ ub : Nat → Nat := fun _ => 2 ^ 32
190
 
191
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
192
 
 
194
 
195
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
196
 
197
+ /-- The data stack's capacity in words. -/
198
+ def Runtime.dCap (r : Runtime) : Nat := (r.dEnd - r.dBase) / 4
199
+
200
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
201
  def Runtime.layout (r : Runtime) : Layout :=
202
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
203
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
204
+ aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4), cert := r.cert,
205
+ ub := r.ub, dCap := r.dCap }
206
 
207
  /-- The `.data` image: IR memory, the register file (`nregs + 1` words) and the two-word
208
+ status block `exitblk`, in the order `epilogue` lays them out. The image is linked into
209
  flash and copied to RAM at reset. -/
210
  def dataImage (r : Runtime) : List Nat := r.memImage ++ List.replicate (r.nregs + 3) 0
211
 
 
243
  s!"\t{la "r5" "regfile"}\n\t{li "r4" r.dEnd}\n\t{li "r6" r.aEnd}\n" ++
244
  "\tb .L0\n\t.ltorg\n"
245
 
246
+ /-- Bring up the UART as a board needs it (the emulator needs none of it): start the 16 MHz
247
+ crystal (`TASKS_HFCLKSTART`, waiting a bounded time for `EVENTS_HFCLKSTARTED`, since the
248
+ internal RC oscillator is too loose for a serial line), make the TX pin an output that idles
249
+ high, select the pins, set 115200 baud (`BAUDRATE = 0x01D7E000`), enable the UART and start
250
+ its transmitter. Uses `r0 … r3`. -/
251
+ def uartInit (r : Runtime) : String :=
252
+ "\t.thumb_func\nuart_init:\n" ++
253
+ s!"\t{la "r2" "0x40000000"}\n\tmovs r3, #1\n\tstr r3, [r2]\n" ++
254
+ s!"\t{la "r1" "0x100000"}\n\t{la "r0" "0x100"}\n" ++
255
+ "9:\tldr r3, [r2, r0]\n\tcmp r3, #0\n\tbne 8f\n\tsubs r1, #1\n\tbne 9b\n8:\n" ++
256
+ s!"\t{la "r2" "0x50000000"}\n\t{la "r0" "0x508"}\n\t{la "r3" (hex (2 ^ r.txPin))}\n\tstr r3, [r2, r0]\n" ++
257
+ s!"\t{la "r0" (hex (0x700 + 4 * r.txPin))}\n\tmovs r3, #1\n\tstr r3, [r2, r0]\n" ++
258
+ s!"\t{la "r2" (hex r.uartBase)}\n" ++
259
+ s!"\t{la "r0" "0x50C"}\n\t{la "r3" (hex r.txPin)}\n\tstr r3, [r2, r0]\n" ++
260
+ s!"\t{la "r0" "0x514"}\n\t{la "r3" (hex r.rxPsel)}\n\tstr r3, [r2, r0]\n" ++
261
+ s!"\t{la "r0" "0x524"}\n\t{la "r3" "0x01D7E000"}\n\tstr r3, [r2, r0]\n" ++
262
+ s!"\t{la "r0" "0x500"}\n\tmovs r3, #4\n\tstr r3, [r2, r0]\n" ++
263
+ "\tmovs r3, #1\n\tstr r3, [r2, #8]\n\tbx lr\n"
264
+
265
+ /-- SAM D21 bring-up (register addresses and fields from the SAM D21/DA1 data sheet,
266
+ DS40001882G): run the CPU and GCLK generator 0 from the 8 MHz internal oscillator undivided
267
+ (`SYSCTRL.OSC8M.PRESC := 0`; at reset it is divided by 8, too slow for 115200 baud), clock
268
+ SERCOM5 (`PM.APBCMASK` bit 7, `GCLK.CLKCTRL := CLKEN | GEN0 | ID 0x19`), hand PA22 and PB22 to
269
+ peripheral function D (SERCOM5 pads 0 and 2), and make SERCOM5 a USART with the internal clock,
270
+ LSB first, TX on pad 0, RX on pad 2, 16x oversampling, 8 data bits, no parity, one stop bit,
271
+ `BAUD = 65536 · (1 - 16 · 115200 / 8000000) = 50436`. Waits are bounded. Uses `r0 … r3`. -/
272
+ def uartInitSamd21 : String :=
273
+ "\t.thumb_func\nuart_init:\n" ++
274
+ -- SYSCTRL.OSC8M (0x40000820): clear PRESC (bits 9:8)
275
+ s!"\t{la "r2" "0x40000800"}\n\tldr r3, [r2, #0x20]\n\t{la "r1" "0x300"}\n\tbics r3, r1\n\tstr r3, [r2, #0x20]\n" ++
276
+ -- PM.APBCMASK (0x40000420): SERCOM5 clock on
277
+ s!"\t{la "r2" "0x40000400"}\n\tldr r3, [r2, #0x20]\n\tmovs r1, #0x80\n\torrs r3, r1\n\tstr r3, [r2, #0x20]\n" ++
278
+ -- GCLK.CLKCTRL (0x40000C02, 16 bits): SERCOM5_CORE from generator 0; wait for STATUS.SYNCBUSY
279
+ s!"\t{la "r2" "0x40000C00"}\n\t{la "r3" "0x4019"}\n\tstrh r3, [r2, #2]\n" ++
280
+ s!"\t{la "r1" "0x100000"}\n9:\tldrb r3, [r2, #1]\n\tlsls r3, r3, #24\n\tbpl 8f\n\tsubs r1, #1\n\tbne 9b\n8:\n" ++
281
+ -- PORT group A (0x41004400): PA22 -> function D (PMUX11 low nibble, PINCFG22.PMUXEN)
282
+ s!"\t{la "r2" "0x41004400"}\n" ++
283
+ "\tmovs r1, #0x3B\n\tldrb r3, [r2, r1]\n\tmovs r0, #0x0F\n\tbics r3, r0\n\tmovs r0, #3\n\torrs r3, r0\n\tstrb r3, [r2, r1]\n" ++
284
+ "\tmovs r1, #0x56\n\tldrb r3, [r2, r1]\n\tmovs r0, #1\n\torrs r3, r0\n\tstrb r3, [r2, r1]\n" ++
285
+ -- PORT group B (0x41004480): PB22 -> function D
286
+ "\tadds r2, #0x80\n" ++
287
+ "\tmovs r1, #0x3B\n\tldrb r3, [r2, r1]\n\tmovs r0, #0x0F\n\tbics r3, r0\n\tmovs r0, #3\n\torrs r3, r0\n\tstrb r3, [r2, r1]\n" ++
288
+ "\tmovs r1, #0x56\n\tldrb r3, [r2, r1]\n\tmovs r0, #1\n\torrs r3, r0\n\tstrb r3, [r2, r1]\n" ++
289
+ -- SERCOM5 (0x42001C00): CTRLA, CTRLB (wait SYNCBUSY), BAUD, then ENABLE (wait SYNCBUSY)
290
+ s!"\t{la "r2" "0x42001C00"}\n\t{la "r3" "0x40200004"}\n\tstr r3, [r2]\n" ++
291
+ s!"\t{la "r3" "0x00030000"}\n\tstr r3, [r2, #4]\n" ++
292
+ s!"\t{la "r1" "0x100000"}\n7:\tldr r3, [r2, #0x1C]\n\tcmp r3, #0\n\tbeq 6f\n\tsubs r1, #1\n\tbne 7b\n6:\n" ++
293
+ s!"\t{la "r3" "50436"}\n\tstrh r3, [r2, #0x0C]\n" ++
294
+ s!"\t{la "r3" "0x40200006"}\n\tstr r3, [r2]\n" ++
295
+ s!"\t{la "r1" "0x100000"}\n5:\tldr r3, [r2, #0x1C]\n\tcmp r3, #0\n\tbeq 4f\n\tsubs r1, #1\n\tbne 5b\n4:\n" ++
296
+ "\tbx lr\n"
297
+
298
+ /-- SAM D21 `putc`: wait for `INTFLAG.DRE`, write `DATA`, then wait for `INTFLAG.TXC`, so the
299
+ last byte is on the wire before the run ends. -/
300
+ def putcSamd21 : String :=
301
  "\t.thumb_func\nputc:\n" ++
302
+ s!"\t{la "r2" "0x42001C00"}\n" ++
303
+ "1:\tldrb r3, [r2, #0x18]\n\tlsls r3, r3, #31\n\tbeq 1b\n\tstrh r0, [r2, #0x28]\n" ++
304
+ "2:\tldrb r3, [r2, #0x18]\n\tlsls r3, r3, #30\n\tbpl 2b\n\tbx lr\n"
305
+
306
+ /-- SAM D21 end of run, after the transcript, with the status in `r6`: light the yellow LED
307
+ (PB10, active low) when the status is 0, then wait for the switch SW0 (PB11, input with the
308
+ internal pull-up) to be released and pressed, and reset the chip (`AIRCR.SYSRESETREQ`), so each
309
+ press runs the program again and prints a fresh transcript. -/
310
+ def finishSamd21 : String :=
311
+ s!"\t{la "r2" "0x41004480"}\n\tcmp r6, #0\n\tbne 1f\n" ++
312
+ s!"\t{la "r3" "0x400"}\n\tstr r3, [r2, #0x08]\n\tstr r3, [r2, #0x14]\n1:\n" ++
313
+ "\tmovs r1, #0x4B\n\tmovs r3, #6\n\tstrb r3, [r2, r1]\n" ++
314
+ s!"\t{la "r3" "0x800"}\n\tstr r3, [r2, #0x18]\n" ++
315
+ "2:\tldr r0, [r2, #0x20]\n\ttst r0, r3\n\tbeq 2b\n" ++
316
+ "3:\tldr r0, [r2, #0x20]\n\ttst r0, r3\n\tbne 3b\n" ++
317
+ s!"\t{la "r1" "0xE000ED0C"}\n\t{la "r0" "0x05FA0004"}\n\tstr r0, [r1]\n4:\tb 4b\n"
318
+
319
+ /-- Output and end-of-run routines, entered only from `exitHalt`, `exitTrap` and `exitOvf`, so
320
+ they may use any register. `putc` writes `r0` to the UART; `putw` writes `r6` as eight
321
+ hexadecimal digits and a newline; `putws` writes the `r5` words at address `r4`.
322
+
323
+ The end of a run (`.Lexit` with the status in `r1`, entered with the UART not yet set up;
324
+ `.Lfinish` with the status in `r6` and the UART set up) needs no debugger: the status goes to
325
+ the two words at `exitblk` (the status and the marker `0xE0D0F1A1`, for a debugger that wants
326
+ to read it), then the UART gets the line `EXIT` and the status as a word line, and the core
327
+ sleeps (`wfi`) for good. -/
328
+ def devices (r : Runtime) : String :=
329
+ (match r.soc with
330
+ | .nrf =>
331
+ uartInit r ++
332
+ "\t.thumb_func\nputc:\n" ++
333
+ s!"\t{la "r2" (hex r.uartBase)}\n\t{la "r1" "0x51C"}\n\tstr r0, [r2, r1]\n\t{la "r1" "0x11C"}\n" ++
334
+ "1:\tldr r3, [r2, r1]\n\tcmp r3, #0\n\tbeq 1b\n\tmovs r3, #0\n\tstr r3, [r2, r1]\n\tbx lr\n"
335
+ | .samd21 => uartInitSamd21 ++ putcSamd21) ++
336
  "\t.thumb_func\nputw:\n\tmov r10, lr\n\tmovs r7, #28\n" ++
337
  "2:\tmov r0, r6\n\tlsrs r0, r7\n\tmovs r1, #15\n\tands r0, r1\n\tcmp r0, #10\n\tbhs 3f\n" ++
338
  "\tadds r0, #48\n\tb 4f\n3:\tadds r0, #87\n4:\tbl putc\n" ++
 
340
  "\t.thumb_func\nputws:\n\tmov r9, lr\n" ++
341
  "5:\tcmp r5, #0\n\tbeq 6f\n\tldr r6, [r4]\n\tadds r4, #4\n\tbl putw\n\tsubs r5, #1\n\tb 5b\n" ++
342
  "6:\tbx r9\n" ++
343
+ ".Lexit:\n\tmov r6, r1\n\tbl uart_init\n" ++
344
+ s!".Lfinish:\n\t{la "r0" "exitblk"}\n\tstr r6, [r0]\n\t{la "r1" "0xE0D0F1A1"}\n\tstr r1, [r0, #4]\n" ++
345
+ String.join ("EXIT\n".toList.map fun ch => s!"\tmovs r0, #{ch.toNat}\n\tbl putc\n") ++
346
+ "\tbl putw\n" ++
347
+ (match r.soc with
348
+ | .nrf => "7:\twfi\n\tb 7b\n"
349
+ | .samd21 => finishSamd21)
350
 
351
+ /-- Set up the UART for the halt dump. -/
352
+ def uartOn (_r : Runtime) : String := "\tbl uart_init\n"
 
 
353
 
354
  def epilogue (r : Runtime) : String :=
355
  let m := r.memImage.length
 
359
  "\tbl putw\n\tbl putws\n" ++
360
  s!"\tmov r4, r8\n\t{li "r5" m}\n\tbl putws\n" ++
361
  s!"\tmov r4, r11\n\t{li "r5" r.nregs}\n\tbl putws\n" ++
362
+ "\tmovs r6, #0\n\tb .Lfinish\n" ++
363
  String.join ((List.range 6).map fun k => s!".Ltrap{k + 1}:\n\tmovs r1, #{k + 1}\n\tb .Lexit\n") ++
364
  devices r ++ "\t.ltorg\n" ++
365
  "\t.data\n\t.balign 4\nirmem:\n" ++
backend/cortexm0/CM0/Guard.lean CHANGED
@@ -40,7 +40,7 @@ theorem uf_cond {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hg : Geom c) (hs
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
- theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
@@ -62,19 +62,38 @@ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Ins
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
- /-- Too few operands: the guard exits with `stackUnderflow`. -/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
67
- {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
68
- (hn : 0 < n) (hn3 : n ≤ 3) (hk : s.dstack.length < n) (hpc : x.pc = base)
69
- (hat : RAt code base (uf L n base)) : RExec code x (.trapped .stackUnderflow) := by
70
- rw [uf_eq L hn] at hat
 
 
71
  obtain ⟨h1, h2, h3, _⟩ := hat
72
- let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 * n))
73
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
74
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
75
  have hholds : Cond.eval .ule (xa.regs r4) (xa.regs r0) = false := by
76
- have := uf_cond hg hs hL hn hn3
77
- have h : ¬ n ≤ s.dstack.length := by omega
78
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
79
  exact RExec.of_steps (RSteps.single hst1)
80
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
@@ -131,6 +150,29 @@ theorem ovfD_trap (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase
131
  rw [hra r4 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
132
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
135
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
136
  Cond.eval .uge (x.regs Reg.sp) (x.regs Reg.r9 - L.rGap) =
 
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
+ theorem uf_pass_pos {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
 
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
+ /-- The guard of an instruction popping `k` words, when the data stack is known to hold at least
66
+ `g` words: with enough operands it falls through, to `base + ufSize (need g k)` (at once when the
67
+ certificate made the guard empty). -/
68
+ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
69
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
70
+ (hL : L.dEnd = ofN c.dEnd) (hk3 : k ≤ 3) (hk : k ≤ s.dstack.length) (hpc : x.pc = base)
71
+ (hat : RAt code base (uf L (need g k) base)) :
72
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ufSize (need g k) ∧ x1.mem = x.mem ∧
73
+ (∀ r, r ≠ r0 → x1.regs r = x.regs r) := by
74
+ by_cases h0 : need g k = 0
75
+ · rw [h0]; exact ⟨x, .refl, hs, by simp [ufSize, hpc], rfl, fun _ _ => rfl⟩
76
+ · have hn : 0 < need g k := Nat.pos_of_ne_zero h0
77
+ have hle := need_le g k
78
+ obtain ⟨x1, a, b, hpc1, d, e⟩ := uf_pass_pos hg hs hL hn (by omega) (by omega) hpc hat
79
+ exact ⟨x1, a, b, by rw [hpc1, ufSize_pos hn], d, e⟩
80
+
81
+ /-- Too few operands: the guard exits with `stackUnderflow`. It is there, because the depth
82
+ certificate's bound `g.lo` is a true lower bound (`hgd`) and the stack holds fewer than `k` words. -/
83
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
84
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
85
+ (hL : L.dEnd = ofN c.dEnd) (hk0 : 0 < k) (hk3 : k ≤ 3) (hgd : g.lo ≤ s.dstack.length) (hk : s.dstack.length < k)
86
+ (hpc : x.pc = base) (hat : RAt code base (uf L (need g k) base)) :
87
+ RExec code x (.trapped .stackUnderflow) := by
88
+ rw [need_of_lt (by omega)] at hat
89
+ rw [uf_eq L hk0] at hat
90
  obtain ⟨h1, h2, h3, _⟩ := hat
91
+ let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 * k))
92
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
93
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
94
  have hholds : Cond.eval .ule (xa.regs r4) (xa.regs r0) = false := by
95
+ have := uf_cond hg hs hL hk0 hk3
96
+ have h : ¬ k ≤ s.dstack.length := by omega
97
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
98
  exact RExec.of_steps (RSteps.single hst1)
99
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
 
150
  rw [hra r4 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
151
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
152
 
153
+ /-- The data-stack guard where the facts keep it: with room for one more word, it falls through
154
+ to `base + ovfSize g` (at once when the bound left the guard out). -/
155
+ theorem ovfG_pass {g : Facts} (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase + 4))
156
+ (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) (hpc : x.pc = base)
157
+ (hat : RAt code base (ovf L g base)) :
158
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ovfSize g ∧ x1.mem = x.mem ∧
159
+ (∀ r, r ≠ r0 → x1.regs r = x.regs r) := by
160
+ unfold ovf at hat
161
+ unfold ovfSize
162
+ cases hn : g.noOvf
163
+ · simp only [hn, Bool.false_eq_true, if_false] at hat ⊢
164
+ exact ovfD_pass hg hs hLd hfit hpc hat
165
+ · exact ⟨x, .refl, hs, by simp [hpc], rfl, fun _ _ => rfl⟩
166
+
167
+ /-- Data stack full: the guard is there (the bound did not claim room) and exits with
168
+ `overflow`. -/
169
+ theorem ovfG_trap {g : Facts} (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x)
170
+ (hLd : L.dLim = ofN (c.dBase + 4)) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd)
171
+ (hpc : x.pc = base) (hat : RAt code base (ovf L g base)) : RExec code x .overflow := by
172
+ unfold ovf at hat
173
+ simp only [hn, Bool.false_eq_true, if_false] at hat
174
+ exact ovfD_trap hg hs hLd h hpc hat
175
+
176
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
177
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
178
  Cond.eval .uge (x.regs Reg.sp) (x.regs Reg.r9 - L.rGap) =
backend/cortexm0/CM0/Init.lean CHANGED
@@ -35,7 +35,9 @@ flash only (`copy_holds`, `boot_correct`).
35
 
36
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
37
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
38
- only about the program.
 
 
39
  -/
40
 
41
  namespace WordDialect
@@ -52,7 +54,8 @@ structure Loader where
52
  /-- The runtime placement for one run, as a `Cfg`. -/
53
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
54
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
55
- M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase }
 
56
 
57
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
58
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
@@ -78,36 +81,38 @@ theorem prologue_run (r : Runtime) (ld : Loader) (x0 : M) :
78
  .next { entryState r ld x0 with pc := x0.pc + 8 } := by
79
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
80
 
81
- theorem isize_le (i : WordDialect.Instr 32) : isize i ≤ 36 := by
82
- cases i <;> simp [isize, ufSize]
83
-
84
- theorem sum_isize_le : ∀ l : Prog 32, (l.map isize).sum ≤ 36 * l.length
85
- | [] => by simp
86
- | i :: l => by
87
- have := isize_le i
88
- have := sum_isize_le l
89
- simp only [List.map_cons, List.sum_cons, List.length_cons]
 
 
 
 
90
  omega
91
 
92
  /-- Code indices are bounded by the program length. -/
93
- theorem offs_lt {p : Prog 32} (h : 36 * p.length < 2 ^ 32) (k : Nat) : offs p k < 2 ^ 32 := by
94
- have h1 := sum_isize_le (p.take k)
95
- have h2 : (p.take k).length ≤ p.length := by rw [List.length_take]; omega
96
- simp only [offs]
97
- omega
98
 
99
  theorem layout_ok (r : Runtime) (ld : Loader) :
100
- r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
101
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
102
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
103
- ⟨rfl, rfl, rfl, rfl, rfl, rfl⟩
104
 
105
  /-- After the prologue, the machine is related to the IR's initial state. -/
106
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
107
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
108
  have hg := h.geom
109
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
110
- ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init])
111
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
112
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
113
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
@@ -128,14 +133,17 @@ theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p :
128
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
129
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
130
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 36 * p.length < 2 ^ 32)
131
- (hreg : RegsOk (cfgOf r ld) p) {o : Outcome 32}
 
132
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
133
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 8 } ∧
134
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
135
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
136
- obtain ⟨hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
 
137
  exact ⟨prologue_run r ld x0,
138
- lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal (offs_lt hlen) hreg hx (entry_rel r ld h p)⟩
 
139
 
140
  end Emit
141
  end CM0
 
35
 
36
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
37
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
38
+ only about the program, including `certOk` for the runtime's stack-depth certificate and
39
+ `UbSound` for its upper bound (the lowering leaves out the underflow and overflow guards they
40
+ cover).
41
  -/
42
 
43
  namespace WordDialect
 
54
  /-- The runtime placement for one run, as a `Cfg`. -/
55
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
56
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
57
+ M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase,
58
+ cert := r.cert, ub := r.ub }
59
 
60
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
61
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
 
81
  .next { entryState r ld x0 with pc := x0.pc + 8 } := by
82
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
83
 
84
+ theorem isize_le (g : Facts) (i : WordDialect.Instr 32) : isize g i ≤ 36 := by
85
+ have hu : ∀ k, ufSize (need g k) ≤ 3 := fun k => by unfold ufSize; split <;> omega
86
+ have hv : ovfSize g ≤ 3 := by unfold ovfSize; split <;> omega
87
+ have h1 := hu 1; have h2 := hu 2; have h3 := hu 3
88
+ cases i <;> simp only [isize] <;> omega
89
+
90
+ theorem offs_le (cf : Nat → Facts) : ∀ (p : Prog 32) (k : Nat), offs cf p k ≤ 36 * p.length
91
+ | [], k => by cases k <;> simp [offs]
92
+ | i :: l, 0 => by simp [offs]
93
+ | i :: l, k + 1 => by
94
+ have := isize_le (cf 0) i
95
+ have := offs_le (fun j => cf (j + 1)) l k
96
+ simp only [offs, List.length_cons]
97
  omega
98
 
99
  /-- Code indices are bounded by the program length. -/
100
+ theorem offs_lt (cf : Nat → Facts) {p : Prog 32} (h : 36 * p.length < 2 ^ 32) (k : Nat) :
101
+ offs cf p k < 2 ^ 32 :=
102
+ Nat.lt_of_le_of_lt (offs_le cf p k) h
 
 
103
 
104
  theorem layout_ok (r : Runtime) (ld : Loader) :
105
+ r.layout.facts = (cfgOf r ld).facts ∧ r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
106
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
107
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
108
+ ⟨funext fun _ => rfl, rfl, rfl, rfl, rfl, rfl, rfl⟩
109
 
110
  /-- After the prologue, the machine is related to the IR's initial state. -/
111
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
112
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
113
  have hg := h.geom
114
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
115
+ ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init, offs_zero])
116
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
117
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
118
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
 
133
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
134
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
135
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 36 * p.length < 2 ^ 32)
136
+ (hreg : RegsOk (cfgOf r ld) p) (hok : certOk p r.cert = true)
137
+ (hub : UbSound p r.dCap r.ub) {o : Outcome 32}
138
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
139
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 8 } ∧
140
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
141
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
142
+ obtain ⟨hLc, hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
143
+ obtain ⟨I, hI0, hIs, hIb⟩ := hub
144
  exact ⟨prologue_run r ld x0,
145
+ lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal hLc hok hIs hIb (offs_lt _ hlen)
146
+ hreg hx (entry_rel r ld h p) (DepthInv.init (certOk_entry hok) _) (hI0 _)⟩
147
 
148
  end Emit
149
  end CM0
backend/cortexm0/CM0/Isa.lean CHANGED
@@ -41,7 +41,7 @@ Scope and trust boundary:
41
  * `exitHalt` / `exitTrap t` stand for the runtime stubs that dump state and stop the machine;
42
  they are terminal here. `exitOvf` is the stub for a stack-overflow guard (status 6); it has no
43
  IR counterpart, since IR stacks are unbounded. There is no operating system: the stubs talk to
44
- a UART and stop the machine through semihosting (`CM0.Emit`).
45
 
46
  That the model matches the hardware is the stated assumption of this backend; `cm0c` tests it by
47
  running the emitted code on an emulated Cortex-M0 board (`qemu-system-arm -M microbit`).
 
41
  * `exitHalt` / `exitTrap t` stand for the runtime stubs that dump state and stop the machine;
42
  they are terminal here. `exitOvf` is the stub for a stack-overflow guard (status 6); it has no
43
  IR counterpart, since IR stacks are unbounded. There is no operating system: the stubs talk to
44
+ a UART and end the run there (`CM0.Emit`).
45
 
46
  That the model matches the hardware is the stated assumption of this backend; `cm0c` tests it by
47
  running the emitted code on an emulated Cortex-M0 board (`qemu-system-arm -M microbit`).
backend/cortexm0/CM0/Lower.lean CHANGED
@@ -1,4 +1,5 @@
1
  import CM0.Isa
 
2
 
3
  /-!
4
  # CM0.Lower
@@ -34,8 +35,11 @@ exits 6 (`exitOvf`). `tor` likewise checks `r6 ≥ aBase + 4` before growing the
34
  stack, and `fromr`/`rfetch` trap `returnUnderflow` when `r6 = aEnd` (empty). IR stacks are unbounded, so this exit has no IR counterpart: it reports that
35
  the run exceeded the target's stack capacity.
36
 
37
- Every instruction's code has a size that depends only on the instruction, so jump targets are
38
- absolute code indices computed from prefix sums (`offs`). One definition serves both the
 
 
 
39
  model and the assembly text.
40
  -/
41
 
@@ -51,6 +55,24 @@ structure Layout where
51
  rGap : W -- `4 rcap - 8`: a call has room iff `sp ≥ r9 - rGap`
52
  aEnd : W -- empty auxiliary stack: `r6 = aEnd`
53
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `r6 ≥ aLim`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  /-- Stack-underflow guard for `k` operands: continue when `r4 ≤ dEnd - 4k`. -/
56
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
@@ -60,10 +82,25 @@ def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
60
 
61
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
62
 
 
 
 
 
 
 
 
 
 
63
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
64
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
65
  [.movImm r0 L.dLim, .bcc .uge r4 r0 (base + 3), .exitOvf]
66
 
 
 
 
 
 
 
67
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
68
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
69
  [.movRR r0 r9, .movImm r1 L.rGap, .sub r0 r1, .bcc .uge sp r0 (base + 5), .exitOvf]
@@ -98,132 +135,146 @@ def sdivSeq (q : Nat) : List (Instr Nat) :=
98
  [.movRR r3 r10, .movImm r7 0#32, .bcc .sge r3 r7 (q + 26), .neg r2, .movRR r0 r2]
99
 
100
  /-- Code size of one IR instruction. -/
101
- def isize : WordDialect.Instr 32 → Nat
102
- | .word _ | .ptr _ => 6
103
- | .load => ufSize 1 + 8
104
- | .store => ufSize 2 + 9
105
- | .add | .sub | .mul | .and | .or | .xor => ufSize 2 + 5
106
- | .div => ufSize 2 + 21
107
- | .sdiv => ufSize 2 + 33
108
- | .not => ufSize 1 + 3
109
- | .shl | .shr => ufSize 2 + 8
110
- | .rotl => ufSize 2 + 6
111
- | .rotr => ufSize 2 + 5
112
- | .cmp _ => ufSize 2 + 7
113
- | .select => ufSize 3 + 7
114
  | .jmp _ => 1
115
- | .branch _ => ufSize 1 + 3
116
  | .call _ => 6
117
  | .ret => 3
118
- | .push _ => 6
119
- | .pop _ => ufSize 1 + 3
120
- | .dup => ufSize 1 + 6
121
- | .drop => ufSize 1 + 1
122
- | .swap => ufSize 2 + 4
123
- | .over => ufSize 2 + 6
124
- | .rot => ufSize 3 + 6
125
- | .tor => ufSize 1 + 7
126
- | .fromr => 10
127
- | .rfetch => 9
128
  | .halt => 1
129
 
130
  /-- Code for one IR instruction placed at code index `base`; `off t` is the code index of IR
131
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
132
- def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) : WordDialect.Instr 32 → List (Instr Nat)
133
- | .word w => ovfD L base ++ [.movImm r0 w, .addImm r4 (-4), .store r4 0 r0]
134
- | .ptr p => ovfD L base ++ [.movImm r0 p.toWord, .addImm r4 (-4), .store r4 0 r0]
 
135
  | .load =>
136
- let b0 := base + ufSize 1
137
- uf L 1 base ++
138
  [.load r0 r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r1 (b0 + 4),
139
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r8, .load r0 r0 0, .store r4 0 r0]
140
  | .store =>
141
- let b0 := base + ufSize 2
142
- uf L 2 base ++
143
  [.load r0 r4 0, .load r1 r4 4, .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (b0 + 5),
144
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r8, .store r0 0 r1, .addImm r4 8]
145
- | .add => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .add r0 r1, .store r4 4 r0, .addImm r4 4]
146
- | .sub => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .sub r0 r1, .store r4 4 r0, .addImm r4 4]
147
- | .mul => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .mul r0 r1, .store r4 4 r0, .addImm r4 4]
148
- | .and => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .and r0 r1, .store r4 4 r0, .addImm r4 4]
149
- | .or => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .or r0 r1, .store r4 4 r0, .addImm r4 4]
150
- | .xor => uf L 2 base ++ [.load r1 r4 0, .load r0 r4 4, .xor r0 r1, .store r4 4 r0, .addImm r4 4]
151
  | .div =>
152
- let b0 := base + ufSize 2
153
- uf L 2 base ++
154
  ([.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero] ++
155
  udivSeq (b0 + 4) ++ [.store r4 4 r0, .addImm r4 4])
156
  | .sdiv =>
157
- let b0 := base + ufSize 2
158
- uf L 2 base ++
159
  ([.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero] ++
160
  sdivSeq (b0 + 4) ++ [.store r4 4 r0, .addImm r4 4])
161
- | .not => uf L 1 base ++ [.load r0 r4 0, .not r0, .store r4 0 r0]
162
  | .shl =>
163
- uf L 2 base ++
164
  [.load r1 r4 0, .load r0 r4 4, .lsl r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
165
  .store r4 4 r0, .addImm r4 4]
166
  | .shr =>
167
- uf L 2 base ++
168
  [.load r1 r4 0, .load r0 r4 4, .lsr r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
169
  .store r4 4 r0, .addImm r4 4]
170
  | .rotl =>
171
- uf L 2 base ++
172
  [.load r1 r4 0, .load r0 r4 4, .neg r1, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
173
  | .rotr =>
174
- uf L 2 base ++
175
  [.load r1 r4 0, .load r0 r4 4, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
176
  | .cmp c =>
177
- let b0 := base + ufSize 2
178
- uf L 2 base ++
179
  [.load r1 r4 0, .load r0 r4 4, .movImm r2 1#32, .bcc c r0 r1 (b0 + 5), .movImm r2 0#32,
180
  .store r4 4 r2, .addImm r4 4]
181
  | .select =>
182
- let b0 := base + ufSize 3
183
- uf L 3 base ++
184
  [.load r1 r4 0, .load r0 r4 4, .load r3 r4 8, .beqz r1 (b0 + 5), .movRR r0 r3,
185
  .store r4 8 r0, .addImm r4 8]
186
  | .jmp t => [.jmp (off t)]
187
- | .branch t => uf L 1 base ++ [.load r0 r4 0, .addImm r4 4, .bnez r0 (off t)]
188
  | .call t => ovfR L base ++ [.call (off t)]
189
  | .ret => [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret]
190
- | .push r => ovfD L base ++ [.load r0 r5 (4 * (r : Int)), .addImm r4 (-4), .store r4 0 r0]
191
- | .pop r => uf L 1 base ++ [.load r0 r4 0, .addImm r4 4, .store r5 (4 * (r : Int)) r0]
192
  | .dup =>
193
- uf L 1 base ++ ovfD L (base + ufSize 1) ++ [.load r0 r4 0, .addImm r4 (-4), .store r4 0 r0]
194
- | .drop => uf L 1 base ++ [.addImm r4 4]
195
- | .swap => uf L 2 base ++ [.load r0 r4 0, .load r1 r4 4, .store r4 0 r1, .store r4 4 r0]
196
  | .over =>
197
- uf L 2 base ++ ovfD L (base + ufSize 2) ++ [.load r0 r4 4, .addImm r4 (-4), .store r4 0 r0]
198
  | .rot =>
199
- uf L 3 base ++
200
  [.load r0 r4 0, .load r1 r4 4, .load r2 r4 8, .store r4 0 r2, .store r4 4 r0,
201
  .store r4 8 r1]
202
  | .tor =>
203
- uf L 1 base ++ ovfA L (base + ufSize 1) ++
204
  [.load r0 r4 0, .addImm r4 4, .addImm r6 (-4), .store r6 0 r0]
205
  | .fromr =>
206
- emptyA L base ++ ovfD L (base + 3) ++
207
  [.load r0 r6 0, .addImm r6 4, .addImm r4 (-4), .store r4 0 r0]
208
  | .rfetch =>
209
- emptyA L base ++ ovfD L (base + 3) ++ [.load r0 r6 0, .addImm r4 (-4), .store r4 0 r0]
210
  | .halt => [.exitHalt]
211
 
212
- theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (i : WordDialect.Instr 32) :
213
- (lowerInstr L base off i).length = isize i := by
214
- cases i <;> simp [lowerInstr, isize, uf, ufSize, ovfD, ovfR, ovfA, emptyA, udivSeq, sdivSeq, udivCode] <;> (try split) <;> simp
 
 
 
 
 
 
 
215
 
216
- /-- Prefix sums of instruction sizes: `offs p k` is the code index of IR instruction `k`.
217
- For `k` past the end it is the index of the final bad-pc stub. -/
218
- def offs (p : Prog 32) (k : Nat) : Nat := ((p.take k).map isize).sum
 
 
 
 
219
 
220
- def lowerGo (L : Layout) (off : Nat → Nat) : Nat → List (WordDialect.Instr 32) → List (Instr Nat)
221
- | _, [] => [.exitTrap .badPc]
222
- | b, i :: is => lowerInstr L b off i ++ lowerGo L off (b + isize i) is
 
223
 
224
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
225
- IR program traps `badPc` exactly as the IR semantics does. -/
226
- def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs p) 0 p
 
227
 
228
  end CM0
229
  end WordDialect
 
1
  import CM0.Isa
2
+ import WordDialect.Depth
3
 
4
  /-!
5
  # CM0.Lower
 
35
  stack, and `fromr`/`rfetch` trap `returnUnderflow` when `r6 = aEnd` (empty). IR stacks are unbounded, so this exit has no IR counterpart: it reports that
36
  the run exceeded the target's stack capacity.
37
 
38
+ Two checked certificates (`WordDialect.Depth`) remove guards: where the data stack is known to
39
+ hold enough operands, the operand-count guard is left out, and where one more word is known to
40
+ fit, the overflow guard is. Every instruction's code has a size that depends only on the
41
+ instruction and those facts, so jump targets are absolute code indices computed from prefix sums
42
+ (`offs`). One definition serves both the
43
  model and the assembly text.
44
  -/
45
 
 
55
  rGap : W -- `4 rcap - 8`: a call has room iff `sp ≥ r9 - rGap`
56
  aEnd : W -- empty auxiliary stack: `r6 = aEnd`
57
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `r6 ≥ aLim`
58
+ /-- A depth certificate (`WordDialect.Depth`): at IR instruction `k` the data stack holds at
59
+ least `cert k` words, so an operand-count guard for at most that many words is left out. -/
60
+ cert : Nat → Nat := fun _ => 0
61
+ /-- An upper bound on the data-stack depth at each IR instruction (`WordDialect.Bound`), and
62
+ the data stack's capacity in words. Where `ub k + 1 ≤ dCap` the data-stack overflow guard is
63
+ left out. The default capacity `0` leaves every guard in. -/
64
+ ub : Nat → Nat := fun _ => 0
65
+ dCap : Nat := 0
66
+
67
+ /-- What the lowering knows at one IR instruction: a lower bound on the data-stack depth, and
68
+ whether one more word is known to fit. -/
69
+ structure Facts where
70
+ lo : Nat := 0
71
+ noOvf : Bool := false
72
+
73
+ /-- The facts at IR instruction `k`. -/
74
+ def Layout.facts (L : Layout) (k : Nat) : Facts :=
75
+ { lo := L.cert k, noOvf := decide (L.ub k + 1 ≤ L.dCap) }
76
 
77
  /-- Stack-underflow guard for `k` operands: continue when `r4 ≤ dEnd - 4k`. -/
78
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
 
82
 
83
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
84
 
85
+ /-- The operand count an instruction popping `k` words still has to check when the data stack is
86
+ known to hold at least `g` words: none if `k ≤ g`. -/
87
+ def need (g : Facts) (k : Nat) : Nat := if k ≤ g.lo then 0 else k
88
+
89
+ theorem need_le (g : Facts) (k : Nat) : need g k ≤ k := by unfold need; split <;> omega
90
+
91
+ theorem need_of_lt {g : Facts} {k : Nat} (h : g.lo < k) : need g k = k := by
92
+ unfold need; split <;> omega
93
+
94
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
95
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
96
  [.movImm r0 L.dLim, .bcc .uge r4 r0 (base + 3), .exitOvf]
97
 
98
+ /-- The data-stack overflow guard where it is needed: none when the facts say one more word fits. -/
99
+ def ovf (L : Layout) (g : Facts) (base : Nat) : List (Instr Nat) :=
100
+ if g.noOvf then [] else ovfD L base
101
+
102
+ def ovfSize (g : Facts) : Nat := if g.noOvf then 0 else 3
103
+
104
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
105
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
106
  [.movRR r0 r9, .movImm r1 L.rGap, .sub r0 r1, .bcc .uge sp r0 (base + 5), .exitOvf]
 
135
  [.movRR r3 r10, .movImm r7 0#32, .bcc .sge r3 r7 (q + 26), .neg r2, .movRR r0 r2]
136
 
137
  /-- Code size of one IR instruction. -/
138
+ def isize (g : Facts) : WordDialect.Instr 32 → Nat
139
+ | .word _ | .ptr _ => ovfSize g + 3
140
+ | .load => ufSize (need g 1) + 8
141
+ | .store => ufSize (need g 2) + 9
142
+ | .add | .sub | .mul | .and | .or | .xor => ufSize (need g 2) + 5
143
+ | .div => ufSize (need g 2) + 21
144
+ | .sdiv => ufSize (need g 2) + 33
145
+ | .not => ufSize (need g 1) + 3
146
+ | .shl | .shr => ufSize (need g 2) + 8
147
+ | .rotl => ufSize (need g 2) + 6
148
+ | .rotr => ufSize (need g 2) + 5
149
+ | .cmp _ => ufSize (need g 2) + 7
150
+ | .select => ufSize (need g 3) + 7
151
  | .jmp _ => 1
152
+ | .branch _ => ufSize (need g 1) + 3
153
  | .call _ => 6
154
  | .ret => 3
155
+ | .push _ => ovfSize g + 3
156
+ | .pop _ => ufSize (need g 1) + 3
157
+ | .dup => ufSize (need g 1) + ovfSize g + 3
158
+ | .drop => ufSize (need g 1) + 1
159
+ | .swap => ufSize (need g 2) + 4
160
+ | .over => ufSize (need g 2) + ovfSize g + 3
161
+ | .rot => ufSize (need g 3) + 6
162
+ | .tor => ufSize (need g 1) + 7
163
+ | .fromr => ovfSize g + 7
164
+ | .rfetch => ovfSize g + 6
165
  | .halt => 1
166
 
167
  /-- Code for one IR instruction placed at code index `base`; `off t` is the code index of IR
168
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
169
+ def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts) :
170
+ WordDialect.Instr 32 → List (Instr Nat)
171
+ | .word w => ovf L g base ++ [.movImm r0 w, .addImm r4 (-4), .store r4 0 r0]
172
+ | .ptr p => ovf L g base ++ [.movImm r0 p.toWord, .addImm r4 (-4), .store r4 0 r0]
173
  | .load =>
174
+ let b0 := base + ufSize (need g 1)
175
+ uf L (need g 1) base ++
176
  [.load r0 r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r1 (b0 + 4),
177
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r8, .load r0 r0 0, .store r4 0 r0]
178
  | .store =>
179
+ let b0 := base + ufSize (need g 2)
180
+ uf L (need g 2) base ++
181
  [.load r0 r4 0, .load r1 r4 4, .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (b0 + 5),
182
  .exitTrap .badAddress, .shlImm r0 2, .add r0 r8, .store r0 0 r1, .addImm r4 8]
183
+ | .add => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .add r0 r1, .store r4 4 r0, .addImm r4 4]
184
+ | .sub => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .sub r0 r1, .store r4 4 r0, .addImm r4 4]
185
+ | .mul => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .mul r0 r1, .store r4 4 r0, .addImm r4 4]
186
+ | .and => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .and r0 r1, .store r4 4 r0, .addImm r4 4]
187
+ | .or => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .or r0 r1, .store r4 4 r0, .addImm r4 4]
188
+ | .xor => uf L (need g 2) base ++ [.load r1 r4 0, .load r0 r4 4, .xor r0 r1, .store r4 4 r0, .addImm r4 4]
189
  | .div =>
190
+ let b0 := base + ufSize (need g 2)
191
+ uf L (need g 2) base ++
192
  ([.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero] ++
193
  udivSeq (b0 + 4) ++ [.store r4 4 r0, .addImm r4 4])
194
  | .sdiv =>
195
+ let b0 := base + ufSize (need g 2)
196
+ uf L (need g 2) base ++
197
  ([.load r1 r4 0, .load r0 r4 4, .bnez r1 (b0 + 4), .exitTrap .divideByZero] ++
198
  sdivSeq (b0 + 4) ++ [.store r4 4 r0, .addImm r4 4])
199
+ | .not => uf L (need g 1) base ++ [.load r0 r4 0, .not r0, .store r4 0 r0]
200
  | .shl =>
201
+ uf L (need g 2) base ++
202
  [.load r1 r4 0, .load r0 r4 4, .lsl r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
203
  .store r4 4 r0, .addImm r4 4]
204
  | .shr =>
205
+ uf L (need g 2) base ++
206
  [.load r1 r4 0, .load r0 r4 4, .lsr r0 r1, .sltiu r2 r1 32, .neg r2, .and r0 r2,
207
  .store r4 4 r0, .addImm r4 4]
208
  | .rotl =>
209
+ uf L (need g 2) base ++
210
  [.load r1 r4 0, .load r0 r4 4, .neg r1, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
211
  | .rotr =>
212
+ uf L (need g 2) base ++
213
  [.load r1 r4 0, .load r0 r4 4, .ror r0 r1, .store r4 4 r0, .addImm r4 4]
214
  | .cmp c =>
215
+ let b0 := base + ufSize (need g 2)
216
+ uf L (need g 2) base ++
217
  [.load r1 r4 0, .load r0 r4 4, .movImm r2 1#32, .bcc c r0 r1 (b0 + 5), .movImm r2 0#32,
218
  .store r4 4 r2, .addImm r4 4]
219
  | .select =>
220
+ let b0 := base + ufSize (need g 3)
221
+ uf L (need g 3) base ++
222
  [.load r1 r4 0, .load r0 r4 4, .load r3 r4 8, .beqz r1 (b0 + 5), .movRR r0 r3,
223
  .store r4 8 r0, .addImm r4 8]
224
  | .jmp t => [.jmp (off t)]
225
+ | .branch t => uf L (need g 1) base ++ [.load r0 r4 0, .addImm r4 4, .bnez r0 (off t)]
226
  | .call t => ovfR L base ++ [.call (off t)]
227
  | .ret => [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret]
228
+ | .push r => ovf L g base ++ [.load r0 r5 (4 * (r : Int)), .addImm r4 (-4), .store r4 0 r0]
229
+ | .pop r => uf L (need g 1) base ++ [.load r0 r4 0, .addImm r4 4, .store r5 (4 * (r : Int)) r0]
230
  | .dup =>
231
+ uf L (need g 1) base ++ ovf L g (base + ufSize (need g 1)) ++ [.load r0 r4 0, .addImm r4 (-4), .store r4 0 r0]
232
+ | .drop => uf L (need g 1) base ++ [.addImm r4 4]
233
+ | .swap => uf L (need g 2) base ++ [.load r0 r4 0, .load r1 r4 4, .store r4 0 r1, .store r4 4 r0]
234
  | .over =>
235
+ uf L (need g 2) base ++ ovf L g (base + ufSize (need g 2)) ++ [.load r0 r4 4, .addImm r4 (-4), .store r4 0 r0]
236
  | .rot =>
237
+ uf L (need g 3) base ++
238
  [.load r0 r4 0, .load r1 r4 4, .load r2 r4 8, .store r4 0 r2, .store r4 4 r0,
239
  .store r4 8 r1]
240
  | .tor =>
241
+ uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
242
  [.load r0 r4 0, .addImm r4 4, .addImm r6 (-4), .store r6 0 r0]
243
  | .fromr =>
244
+ emptyA L base ++ ovf L g (base + 3) ++
245
  [.load r0 r6 0, .addImm r6 4, .addImm r4 (-4), .store r4 0 r0]
246
  | .rfetch =>
247
+ emptyA L base ++ ovf L g (base + 3) ++ [.load r0 r6 0, .addImm r4 (-4), .store r4 0 r0]
248
  | .halt => [.exitHalt]
249
 
250
+ theorem uf_length (L : Layout) (k base : Nat) : (uf L k base).length = ufSize k := by
251
+ unfold uf ufSize; split <;> simp
252
+
253
+ theorem ovf_length (L : Layout) (g : Facts) (base : Nat) : (ovf L g base).length = ovfSize g := by
254
+ unfold ovf ovfSize; split <;> simp [ovfD]
255
+
256
+ theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts)
257
+ (i : WordDialect.Instr 32) : (lowerInstr L base off g i).length = isize g i := by
258
+ cases i <;> simp [lowerInstr, isize, uf_length, ovf_length, ovfR, ovfA, emptyA, udivSeq,
259
+ sdivSeq, udivCode] <;> omega
260
 
261
+ /-- Prefix sums of instruction sizes: `offs cf p k` is the code index of IR instruction `k`,
262
+ where `cf j` are the facts at instruction `j` (its guards depend on them). For `k` past
263
+ the end it is the index of the final bad-pc stub. -/
264
+ def offs (cf : Nat → Facts) : Prog 32 → Nat → Nat
265
+ | _, 0 => 0
266
+ | [], _ + 1 => 0
267
+ | i :: is, k + 1 => isize (cf 0) i + offs (fun j => cf (j + 1)) is k
268
 
269
+ def lowerGo (L : Layout) (off : Nat → Nat) :
270
+ (Nat → Facts) → Nat → List (WordDialect.Instr 32) → List (Instr Nat)
271
+ | _, _, [] => [.exitTrap .badPc]
272
+ | cf, b, i :: is => lowerInstr L b off (cf 0) i ++ lowerGo L off (fun j => cf (j + 1)) (b + isize (cf 0) i) is
273
 
274
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
275
+ IR program traps `badPc` exactly as the IR semantics does. Instruction `k` leaves out the
276
+ guards that `L.facts k` makes redundant. -/
277
+ def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs L.facts p) L.facts 0 p
278
 
279
  end CM0
280
  end WordDialect
backend/cortexm0/CM0/Rel.lean CHANGED
@@ -33,6 +33,17 @@ structure Cfg where
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  structure Geom (c : Cfg) : Prop where
38
  dEnd_lt : c.dEnd < 2 ^ 32
@@ -95,7 +106,7 @@ def MemRel (c : Cfg) (mem : Memory 32) (m : Memory 32) : Prop :=
95
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
96
 
97
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
98
- ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs p a))
99
 
100
  /-- The ARMv6-M memory's addressable set covers every region. -/
101
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
@@ -125,7 +136,7 @@ structure Rel0 (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop where
125
 
126
  /-- Full relation: everything in `Rel0`, and the ARMv6-M pc is the start of the IR pc's code. -/
127
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
128
- Rel0 c p s x ∧ x.pc = offs p s.pc
129
 
130
  /-- `Rel0` does not look at scratch registers or the pc. -/
131
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
 
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
36
+ /-- The depth certificate the code was lowered with (`Layout.cert`). -/
37
+ cert : Nat → Nat := fun _ => 0
38
+ /-- The upper bound on the data-stack depth the code was lowered with (`Layout.ub`). -/
39
+ ub : Nat → Nat := fun _ => 2 ^ 32
40
+
41
+ /-- The data stack's capacity in words. -/
42
+ def Cfg.dCap (c : Cfg) : Nat := (c.dEnd - c.dBase) / 4
43
+
44
+ /-- The facts the code was lowered with (`Layout.facts`). -/
45
+ def Cfg.facts (c : Cfg) (k : Nat) : Facts :=
46
+ { lo := c.cert k, noOvf := decide (c.ub k + 1 ≤ c.dCap) }
47
 
48
  structure Geom (c : Cfg) : Prop where
49
  dEnd_lt : c.dEnd < 2 ^ 32
 
106
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
107
 
108
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
109
+ ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs c.facts p a))
110
 
111
  /-- The ARMv6-M memory's addressable set covers every region. -/
112
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
 
136
 
137
  /-- Full relation: everything in `Rel0`, and the ARMv6-M pc is the start of the IR pc's code. -/
138
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
139
+ Rel0 c p s x ∧ x.pc = offs c.facts p s.pc
140
 
141
  /-- `Rel0` does not look at scratch registers or the pc. -/
142
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
backend/cortexm0/CM0/Run.lean CHANGED
@@ -63,11 +63,10 @@ theorem rstep_of_fetch {code : List (Instr Nat)} {m : M} {i : Instr Nat}
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
- theorem offs_cons (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
- offs (i :: is) (k + 1) = isize i + offs is k := by
68
- simp [offs, List.take_succ_cons]
69
 
70
- theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by simp [offs]
71
 
72
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
73
  induction seg generalizing pre with
@@ -77,66 +76,70 @@ theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) p
77
  have := ih (pre ++ [i])
78
  simpa [List.append_assoc] using this
79
 
80
- /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs ps k`. -/
 
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
- ∀ (ps : Prog 32) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps k)
85
- (lowerInstr L (pre.length + offs ps k) off i) := by
86
  intro ps
87
  induction ps with
88
- | nil => intro pre k i h; simp at h
89
  | cons j js ih =>
90
- intro pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
- have := rat_embed pre (lowerInstr L pre.length off j) (lowerGo L off (pre.length + isize j) js)
 
96
  simpa [List.append_assoc] using this
97
  | succ k =>
98
  simp only [List.getElem?_cons_succ] at h
99
- have := ih (pre ++ lowerInstr L pre.length off j) k i h
100
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
101
  simp [lowerInstr_length]
102
  rw [hl] at this
103
  simp only [lowerGo, offs_cons]
104
- have e : pre.length + (isize j + offs js k) = pre.length + isize j + offs js k := by omega
 
105
  rw [e]
106
  simpa [List.append_assoc] using this
107
 
108
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
109
  (h : p[k]? = some i) :
110
- RAt (lowerProg L p) (offs p k) (lowerInstr L (offs p k) (offs p) i) := by
111
- have := lowerGo_at L (offs p) p [] k i h
112
  simpa [lowerProg] using this
113
 
114
- /-- The final stub (bad-pc trap) sits at `offs p p.length`. -/
115
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
116
- ∀ (ps : Prog 32) (pre : List (Instr Nat)),
117
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps ps.length) [.exitTrap .badPc] := by
 
118
  intro ps
119
  induction ps with
120
  | nil =>
121
- intro pre
122
- simp only [lowerGo, List.length_nil, offs, List.take_nil, List.map_nil, List.sum_nil,
123
- Nat.add_zero]
124
  have := rat_embed pre [.exitTrap .badPc] []
125
  simpa using this
126
  | cons j js ih =>
127
- intro pre
128
- have := ih (pre ++ lowerInstr L pre.length off j)
129
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
130
  simp [lowerInstr_length]
131
  rw [hl] at this
132
  simp only [lowerGo, List.length_cons, offs_cons]
133
- have e : pre.length + (isize j + offs js js.length) = pre.length + isize j + offs js js.length := by omega
 
134
  rw [e]
135
  simpa [List.append_assoc] using this
136
 
137
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
138
- RAt (lowerProg L p) (offs p p.length) [.exitTrap .badPc] := by
139
- have := lowerGo_stub L (offs p) p []
140
  simpa [lowerProg] using this
141
 
142
  end CM0
 
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
+ theorem offs_cons (cf : Nat → Facts) (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
+ offs cf (i :: is) (k + 1) = isize (cf 0) i + offs (fun j => cf (j + 1)) is k := rfl
 
68
 
69
+ theorem offs_zero (cf : Nat → Facts) (p : Prog 32) : offs cf p 0 = 0 := by cases p <;> rfl
70
 
71
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
72
  induction seg generalizing pre with
 
76
  have := ih (pre ++ [i])
77
  simpa [List.append_assoc] using this
78
 
79
+ /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs cf ps k`, with
80
+ the guards for the facts `cf k`. -/
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps k)
85
+ (lowerInstr L (pre.length + offs cf ps k) off (cf k) i) := by
86
  intro ps
87
  induction ps with
88
+ | nil => intro cf pre k i h; simp at h
89
  | cons j js ih =>
90
+ intro cf pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
+ have := rat_embed pre (lowerInstr L pre.length off (cf 0) j)
96
+ (lowerGo L off (fun j => cf (j + 1)) (pre.length + isize (cf 0) j) js)
97
  simpa [List.append_assoc] using this
98
  | succ k =>
99
  simp only [List.getElem?_cons_succ] at h
100
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j) k i h
101
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
102
  simp [lowerInstr_length]
103
  rw [hl] at this
104
  simp only [lowerGo, offs_cons]
105
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js k) =
106
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js k := by omega
107
  rw [e]
108
  simpa [List.append_assoc] using this
109
 
110
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
111
  (h : p[k]? = some i) :
112
+ RAt (lowerProg L p) (offs L.facts p k) (lowerInstr L (offs L.facts p k) (offs L.facts p) (L.facts k) i) := by
113
+ have := lowerGo_at L (offs L.facts p) p L.facts [] k i h
114
  simpa [lowerProg] using this
115
 
116
+ /-- The final stub (bad-pc trap) sits at `offs cf p p.length`. -/
117
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
118
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)),
119
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps ps.length)
120
+ [.exitTrap .badPc] := by
121
  intro ps
122
  induction ps with
123
  | nil =>
124
+ intro cf pre
125
+ simp only [lowerGo, List.length_nil, offs_zero, Nat.add_zero]
 
126
  have := rat_embed pre [.exitTrap .badPc] []
127
  simpa using this
128
  | cons j js ih =>
129
+ intro cf pre
130
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j)
131
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
132
  simp [lowerInstr_length]
133
  rw [hl] at this
134
  simp only [lowerGo, List.length_cons, offs_cons]
135
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length) =
136
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length := by omega
137
  rw [e]
138
  simpa [List.append_assoc] using this
139
 
140
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
141
+ RAt (lowerProg L p) (offs L.facts p p.length) [.exitTrap .badPc] := by
142
+ have := lowerGo_stub L (offs L.facts p) p L.facts []
143
  simpa [lowerProg] using this
144
 
145
  end CM0
backend/cortexm0/CM0/SimAux.lean CHANGED
@@ -203,7 +203,7 @@ end Steps
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
- {base : Nat}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
@@ -305,32 +305,32 @@ end Guards
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
- {L : Layout} {base : Nat} {off : Nat → Nat}
309
 
310
  /-- Placement of the `tor` code. -/
311
- theorem xat_tor (hat : RAt code base (lowerInstr L base off .tor)) :
312
- RAt code base (uf L 1 base) ∧ RAt code (base + 3) (ovfA L (base + 3)) ∧
313
- RAt code (base + 6) [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r6 (-4),
314
  .store Reg.r6 0 r0] := by
315
- have hat' : RAt code base (uf L 1 base ++ ovfA L (base + 3) ++
316
  [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r6 (-4), .store Reg.r6 0 r0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
320
  rw [hufl] at hato
321
- have hl : (uf L 1 base ++ ovfA L (base + 3)).length = 6 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
- x'.pc = base + isize (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
@@ -343,39 +343,40 @@ theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
- by simp [isize, ufSize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
- /-- Placement of `emptyA L base ++ ovfD L (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
- (hat : RAt code base (emptyA L base ++ ovfD L (base + 3) ++ rest)) :
359
- RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovfD L (base + 3)) ∧
360
- RAt code (base + 6) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
- have hl : (emptyA L base ++ ovfD L (base + 3)).length = 6 := rfl
366
- rw [hl] at hatr
 
367
  exact ⟨hate, hato, hatr⟩
368
 
369
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
370
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
371
  {a : W} {as : List W} (hd : s.astack = a :: as)
372
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
373
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
374
- x'.pc = base + isize (.fromr : WordDialect.Instr 32) := by
375
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
376
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
377
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
378
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
379
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
380
  (by simp) (fetch_cast f0 (by omega))
381
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
@@ -386,30 +387,30 @@ theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = o
386
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
387
 
388
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
389
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr)) (he : s.astack = []) :
390
  RExec code x (.trapped .returnUnderflow) :=
391
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r6 0,
392
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
393
 
394
- theorem sim_fromr_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
395
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
396
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
397
  RExec code x .overflow := by
398
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
399
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
400
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
401
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
402
 
403
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
404
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
405
  {a : W} {as : List W} (hd : s.astack = a :: as)
406
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
407
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
408
- x'.pc = base + isize (.rfetch : WordDialect.Instr 32) := by
409
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
410
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
411
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
412
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
413
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
414
  (by simp) (fetch_cast f0 (by omega))
415
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
@@ -418,19 +419,19 @@ theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim =
418
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
419
 
420
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
421
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch)) (he : s.astack = []) :
422
  RExec code x (.trapped .returnUnderflow) :=
423
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r6 0,
424
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
425
 
426
- theorem sim_rfetch_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
427
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
428
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
429
  RExec code x .overflow := by
430
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
431
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
432
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
433
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
434
 
435
  end Ops
436
 
 
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
+ {base : Nat} {g : Facts}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
 
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
309
 
310
  /-- Placement of the `tor` code. -/
311
+ theorem xat_tor (hat : RAt code base (lowerInstr L base off g .tor)) :
312
+ RAt code base (uf L (need g 1) base) ∧ RAt code (base + ufSize (need g 1)) (ovfA L (base + ufSize (need g 1))) ∧
313
+ RAt code (base + ufSize (need g 1) + 3) [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r6 (-4),
314
  .store Reg.r6 0 r0] := by
315
+ have hat' : RAt code base (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
316
  [.load r0 Reg.r4 0, .addImm Reg.r4 4, .addImm Reg.r6 (-4), .store Reg.r6 0 r0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
+ have hufl := uf_length L (need g 1) base
320
  rw [hufl] at hato
321
+ have hl : (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1))).length = ufSize (need g 1) + 3 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
+ x'.pc = base + isize g (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
 
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
+ by simp [isize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
+ /-- Placement of `emptyA L base ++ ovf L g (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
+ (hat : RAt code base (emptyA L base ++ ovf L g (base + 3) ++ rest)) :
359
+ RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovf L g (base + 3)) ∧
360
+ RAt code (base + 3 + ovfSize g) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
+ have hl : (emptyA L base ++ ovf L g (base + 3)).length = 3 + ovfSize g := by
366
+ simp [ovf_length, emptyA]; omega
367
+ rw [hl, ← Nat.add_assoc] at hatr
368
  exact ⟨hate, hato, hatr⟩
369
 
370
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
371
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
372
  {a : W} {as : List W} (hd : s.astack = a :: as)
373
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
374
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
375
+ x'.pc = base + isize g (.fromr : WordDialect.Instr 32) := by
376
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
377
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
378
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
379
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
380
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
381
  (by simp) (fetch_cast f0 (by omega))
382
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
 
387
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
388
 
389
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
390
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr)) (he : s.astack = []) :
391
  RExec code x (.trapped .returnUnderflow) :=
392
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r6 0,
393
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
394
 
395
+ theorem sim_fromr_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
396
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
397
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
398
  RExec code x .overflow := by
399
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
400
  .addImm Reg.r6 4, .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
401
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
402
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
403
 
404
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
405
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
406
  {a : W} {as : List W} (hd : s.astack = a :: as)
407
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
408
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
409
+ x'.pc = base + isize g (.rfetch : WordDialect.Instr 32) := by
410
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
411
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
412
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
413
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
414
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := r0)
415
  (by simp) (fetch_cast f0 (by omega))
416
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
 
419
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
420
 
421
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
422
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch)) (he : s.astack = []) :
423
  RExec code x (.trapped .returnUnderflow) :=
424
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load r0 Reg.r6 0,
425
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat).1
426
 
427
+ theorem sim_rfetch_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
428
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
429
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
430
  RExec code x .overflow := by
431
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load r0 Reg.r6 0,
432
  .addImm Reg.r4 (-4), .store Reg.r4 0 r0]) hat
433
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
434
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
435
 
436
  end Ops
437
 
backend/cortexm0/CM0/SimBin.lean CHANGED
@@ -28,23 +28,23 @@ theorem scratch_ne (r : Reg) (h : r = r0 ∨ r = r1 ∨ r = r2 ∨ r = r3) :
28
  rcases h with rfl | rfl | rfl | rfl <;> decide
29
 
30
  theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
- {L : Layout} {base : Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
32
  (hpc : x.pc = base) (mid : List (Instr Nat)) (rr : Reg)
33
  (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
34
  (hmid : MidSpec mid rr f) (hstr : ∀ i ∈ mid, i.straightR = true)
35
- (hat : RAt code base (uf L 2 base ++
36
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4])))
37
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
38
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
39
- x'.pc = base + 3 + (4 + mid.length) := by
40
  have hk : 2 ≤ s.dstack.length := by simp [hd]
41
  obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
42
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
43
  rw [hufl] at hatrest
44
  obtain ⟨hatA, hatB⟩ := rat_append.mp hatrest
45
  obtain ⟨hatLd, hatMid⟩ := rat_append.mp hatA
46
  obtain ⟨f0, f1, _⟩ := hatLd
47
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
48
  have hrcx := scratch_ne r1 (by simp)
49
  have hrax := scratch_ne r0 (by simp)
50
  -- load r1, [r4 + 0]
@@ -53,14 +53,14 @@ theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (
53
  have hst0 : RSteps code x1 x2 := RSteps.single (by
54
  rw [rstep_of_fetch (m := x1) (by rw [hpc1]; exact f0), e0, hx2])
55
  have hr2 : Rel0 c p s x2 := by rw [hx2]; exact mov_rel0 hr1 r1 hrcx b
56
- have hpc2 : x2.pc = base + 3 + 1 := by simp [hx2, M.mov, M.setReg, M.adv, hpc1]
57
  -- load r0, [r4 + 4]
58
  have e1 := ld_stack hr2 (j := 1) (v := a) (by simp [hd]) r0 (disp := 4) (by simp)
59
  obtain ⟨x3, hx3⟩ : ∃ x3, x3 = x2.mov r0 a := ⟨_, rfl⟩
60
  have hst1 : RSteps code x2 x3 := RSteps.single (by
61
  rw [rstep_of_fetch (m := x2) (by rw [hpc2]; exact f1), e1, hx3])
62
  have hr3 : Rel0 c p s x3 := by rw [hx3]; exact mov_rel0 hr2 r0 hrax a
63
- have hpc3 : x3.pc = base + 3 + 2 := by simp [hx3, M.mov, M.setReg, M.adv, hpc2]
64
  have hax : x3.regs r0 = a := by simp [hx3, M.mov, M.setReg, M.adv]
65
  have hcx : x3.regs r1 = b := by simp [hx3, hx2, M.mov, M.setReg, M.adv]
66
  -- mid
@@ -71,12 +71,12 @@ theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (
71
  have hlen : 1 < s.dstack.length := by simp [hd]
72
  obtain ⟨mem', e2, hr5⟩ := st_stack hg hr4 (j := 1) hlen rr (disp := 4) (by simp)
73
  obtain ⟨st, adj, _⟩ := hatB
74
- have hpc4' : x4.pc = base + 3 + (2 + mid.length) := by rw [hpc4, hpc3]; omega
75
  obtain ⟨x5, hx5⟩ : ∃ x5, x5 = ({ x4.adv with mem := mem' } : M) := ⟨_, rfl⟩
76
  have hst2 : RSteps code x4 x5 := RSteps.single (by
77
  rw [rstep_of_fetch (m := x4) (fetch_cast st (by rw [hpc4']; simp; omega)), e2, hx5])
78
  rw [← hx5] at hr5
79
- have hpc5 : x5.pc = base + 3 + (2 + mid.length + 1) := by
80
  simp [hx5, M.adv]; omega
81
  -- adjust r4
82
  have hlen5 : 1 ≤ ({ s with dstack := s.dstack.set 1 (x4.regs rr) } : State 32).dstack.length := by
 
28
  rcases h with rfl | rfl | rfl | rfl <;> decide
29
 
30
  theorem sim_bin_ok {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
+ {L : Layout} {base : Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
32
  (hpc : x.pc = base) (mid : List (Instr Nat)) (rr : Reg)
33
  (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
34
  (hmid : MidSpec mid rr f) (hstr : ∀ i ∈ mid, i.straightR = true)
35
+ (hat : RAt code base (uf L (need g 2) base ++
36
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4])))
37
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
38
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
39
+ x'.pc = base + ufSize (need g 2) + (4 + mid.length) := by
40
  have hk : 2 ≤ s.dstack.length := by simp [hd]
41
  obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
42
+ have hufl := uf_length L (need g 2) base
43
  rw [hufl] at hatrest
44
  obtain ⟨hatA, hatB⟩ := rat_append.mp hatrest
45
  obtain ⟨hatLd, hatMid⟩ := rat_append.mp hatA
46
  obtain ⟨f0, f1, _⟩ := hatLd
47
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
48
  have hrcx := scratch_ne r1 (by simp)
49
  have hrax := scratch_ne r0 (by simp)
50
  -- load r1, [r4 + 0]
 
53
  have hst0 : RSteps code x1 x2 := RSteps.single (by
54
  rw [rstep_of_fetch (m := x1) (by rw [hpc1]; exact f0), e0, hx2])
55
  have hr2 : Rel0 c p s x2 := by rw [hx2]; exact mov_rel0 hr1 r1 hrcx b
56
+ have hpc2 : x2.pc = base + ufSize (need g 2) + 1 := by simp [hx2, M.mov, M.setReg, M.adv, hpc1]
57
  -- load r0, [r4 + 4]
58
  have e1 := ld_stack hr2 (j := 1) (v := a) (by simp [hd]) r0 (disp := 4) (by simp)
59
  obtain ⟨x3, hx3⟩ : ∃ x3, x3 = x2.mov r0 a := ⟨_, rfl⟩
60
  have hst1 : RSteps code x2 x3 := RSteps.single (by
61
  rw [rstep_of_fetch (m := x2) (by rw [hpc2]; exact f1), e1, hx3])
62
  have hr3 : Rel0 c p s x3 := by rw [hx3]; exact mov_rel0 hr2 r0 hrax a
63
+ have hpc3 : x3.pc = base + ufSize (need g 2) + 2 := by simp [hx3, M.mov, M.setReg, M.adv, hpc2]
64
  have hax : x3.regs r0 = a := by simp [hx3, M.mov, M.setReg, M.adv]
65
  have hcx : x3.regs r1 = b := by simp [hx3, hx2, M.mov, M.setReg, M.adv]
66
  -- mid
 
71
  have hlen : 1 < s.dstack.length := by simp [hd]
72
  obtain ⟨mem', e2, hr5⟩ := st_stack hg hr4 (j := 1) hlen rr (disp := 4) (by simp)
73
  obtain ⟨st, adj, _⟩ := hatB
74
+ have hpc4' : x4.pc = base + ufSize (need g 2) + (2 + mid.length) := by rw [hpc4, hpc3]; omega
75
  obtain ⟨x5, hx5⟩ : ∃ x5, x5 = ({ x4.adv with mem := mem' } : M) := ⟨_, rfl⟩
76
  have hst2 : RSteps code x4 x5 := RSteps.single (by
77
  rw [rstep_of_fetch (m := x4) (fetch_cast st (by rw [hpc4']; simp; omega)), e2, hx5])
78
  rw [← hx5] at hr5
79
+ have hpc5 : x5.pc = base + ufSize (need g 2) + (2 + mid.length + 1) := by
80
  simp [hx5, M.adv]; omega
81
  -- adjust r4
82
  have hlen5 : 1 ≤ ({ s with dstack := s.dstack.set 1 (x4.regs rr) } : State 32).dstack.length := by
backend/cortexm0/CM0/SimCtl.lean CHANGED
@@ -14,19 +14,24 @@ namespace CM0
14
 
15
  open Reg
16
 
17
- theorem offs_succ {p : Prog 32} {k : Nat} {i : WordDialect.Instr 32} (h : p[k]? = some i) :
18
- offs p (k + 1) = offs p k + isize i := by
19
- have hk : k < p.length := (List.getElem?_eq_some_iff.mp h).1
20
- have hi : p[k] = i := (List.getElem?_eq_some_iff.mp h).2
21
- simp [offs, List.take_succ, h, List.sum_append]
 
 
 
 
 
22
 
23
  section Ctl
24
 
25
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
26
- {L : Layout} {base : Nat} {off : Nat → Nat}
27
 
28
  theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
29
- (hat : RAt code base (lowerInstr L base off (.jmp t))) :
30
  ∃ x', RSteps code x x' ∧ Rel0 c p s x' ∧ x'.pc = off t := by
31
  have hat' : RAt code base [.jmp (off t)] := hat
32
  obtain ⟨f0, _⟩ := hat'
@@ -35,18 +40,18 @@ theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
35
 
36
  /-- `branch t`: both outcomes. -/
37
  theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
38
- (hpc : x.pc = base) {t : Nat} (hat : RAt code base (lowerInstr L base off (.branch t)))
39
  {cc : W} {d : List W} (hd : s.dstack = cc :: d) :
40
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
41
- x'.pc = (if Word.isTrue cc then off t else base + isize (.branch t : WordDialect.Instr 32)) := by
42
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
43
  .bnez r0 (off t)]) := hat
44
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
45
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
46
  rw [hufl] at hatr
47
  obtain ⟨f0, f1, f2, _⟩ := hatr
48
  have hk : 1 ≤ s.dstack.length := by simp [hd]
49
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
50
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
51
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
52
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
@@ -60,7 +65,7 @@ theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
60
  simp [exec, hax3, hc]
61
  refine ⟨x3.adv, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4),
62
  hr3.congr rfl rfl rfl rfl rfl rfl rfl, ?_⟩
63
- simp [hc, Word.isTrue, M.adv, hpc3, isize, ufSize]; omega
64
  · have hst4 : step code x3 = .next { x3 with pc := off t } := by
65
  rw [rstep_of_fetch (m := x3) (fetch_cast f2 (by omega))]
66
  simp [exec, hax3, hc]
@@ -69,7 +74,7 @@ theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
69
  simp [hc, Word.isTrue]
70
 
71
  theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
72
- (hat : RAt code base (lowerInstr L base off .halt)) : RExec code x (.halted x) := by
73
  have hat' : RAt code base [.exitHalt] := hat
74
  obtain ⟨f0, _⟩ := hat'
75
  exact RExec.halt (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
@@ -78,7 +83,7 @@ theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
78
  (`sp`). -/
79
  theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
80
  (hat : RAt code base [.call (off t)])
81
- (hret : base + 1 = offs p (s.pc + 1)) (hfitR : s.rstack.length + 2 ≤ c.rcap) :
82
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
83
  x'.pc = off t := by
84
  obtain ⟨f0, _⟩ := hat
@@ -170,9 +175,9 @@ theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t :
170
  · simp only [List.length_cons]; omega
171
 
172
  theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
173
- (hat : RAt code base (lowerInstr L base off .ret)) {a : Nat} {rs : List Nat}
174
- (hr : s.rstack = a :: rs) (hsz : offs p a < 2 ^ 32) :
175
- ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := rs } x' ∧ x'.pc = offs p a := by
176
  have hat' : RAt code base [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
177
  obtain ⟨f0, f1, f3, _⟩ := hat'
178
  have hcapR := hs.capR
@@ -194,14 +199,14 @@ theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
194
  rw [hr] at hread
195
  simp only [List.length_cons, Nat.mul_zero, Nat.add_zero] at hread
196
  have hst3 : step code { x1 with pc := base + 2 } = .next { (({ x1 with pc := base + 2 } : M).setReg
197
- sp (ofN (c.sp0 - 4 * rs.length))) with pc := offs p a } := by
198
  rw [rstep_of_fetch (m := { x1 with pc := base + 2 }) f3]
199
  have hx1r : x1.regs sp = ofN (c.sp0 - 4 * (rs.length + 1)) := hrsp
200
  have hx1m : x1.mem = x.mem := rfl
201
  have hadd : ofN (c.sp0 - 4 * (rs.length + 1)) + 4#32 = ofN (c.sp0 - 4 * rs.length) := by
202
  show ofN _ + ofN 4 = _
203
  rw [ofN_add]; congr 1; omega
204
- have hv : (ofN (offs p a)).toNat = offs p a := by
205
  simp [ofN, BitVec.toNat_ofNat, Nat.mod_eq_of_lt hsz]
206
  simp only [exec]
207
  rw [hx1m, hx1r, hread]
@@ -230,7 +235,7 @@ theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
230
  omega
231
 
232
  theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
233
- (hat : RAt code base (lowerInstr L base off .ret)) (hr : s.rstack = []) :
234
  RExec code x (.trapped .returnUnderflow) := by
235
  have hat' : RAt code base [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
236
  obtain ⟨f0, f1, _⟩ := hat'
@@ -241,8 +246,8 @@ theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
241
 
242
  /-- `call t`: the return-stack guard, then the model's `call`. -/
243
  theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
244
- (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off (.call t)))
245
- (hret : base + isize (.call t : WordDialect.Instr 32) = offs p (s.pc + 1))
246
  (hfitR : s.rstack.length + 2 ≤ c.rcap) :
247
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
248
  x'.pc = off t := by
@@ -255,7 +260,7 @@ theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : N
255
  exact ⟨x', hs1.trans hs', hr', hpc'⟩
256
 
257
  theorem sim_call_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
258
- (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off (.call t)))
259
  (h : ¬ s.rstack.length + 2 ≤ c.rcap) : RExec code x .overflow := by
260
  have hat' : RAt code base (ovfR L base ++ [.call (off t)]) := hat
261
  exact ovfR_trap hg hs hLr h hpc (rat_append.mp hat').1
 
14
 
15
  open Reg
16
 
17
+ theorem offs_succ (cf : Nat → Facts) {p : Prog 32} {k : Nat} {i : WordDialect.Instr 32}
18
+ (h : p[k]? = some i) : offs cf p (k + 1) = offs cf p k + isize (cf k) i := by
19
+ induction p generalizing cf k with
20
+ | nil => simp at h
21
+ | cons j js ih =>
22
+ cases k with
23
+ | zero => simp at h; subst h; simp [offs_cons, offs_zero]
24
+ | succ k =>
25
+ simp only [List.getElem?_cons_succ] at h
26
+ rw [offs_cons, offs_cons, ih (fun j => cf (j + 1)) h]; omega
27
 
28
  section Ctl
29
 
30
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
31
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
32
 
33
  theorem sim_jmp_ok (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
34
+ (hat : RAt code base (lowerInstr L base off g (.jmp t))) :
35
  ∃ x', RSteps code x x' ∧ Rel0 c p s x' ∧ x'.pc = off t := by
36
  have hat' : RAt code base [.jmp (off t)] := hat
37
  obtain ⟨f0, _⟩ := hat'
 
40
 
41
  /-- `branch t`: both outcomes. -/
42
  theorem sim_branch_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
43
+ (hpc : x.pc = base) {t : Nat} (hat : RAt code base (lowerInstr L base off g (.branch t)))
44
  {cc : W} {d : List W} (hd : s.dstack = cc :: d) :
45
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
46
+ x'.pc = (if Word.isTrue cc then off t else base + isize g (.branch t : WordDialect.Instr 32)) := by
47
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
48
  .bnez r0 (off t)]) := hat
49
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
50
+ have hufl := uf_length L (need g 1) base
51
  rw [hufl] at hatr
52
  obtain ⟨f0, f1, f2, _⟩ := hatr
53
  have hk : 1 ≤ s.dstack.length := by simp [hd]
54
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
55
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
56
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
57
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
 
65
  simp [exec, hax3, hc]
66
  refine ⟨x3.adv, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4),
67
  hr3.congr rfl rfl rfl rfl rfl rfl rfl, ?_⟩
68
+ simp [hc, Word.isTrue, M.adv, hpc3, isize]; omega
69
  · have hst4 : step code x3 = .next { x3 with pc := off t } := by
70
  rw [rstep_of_fetch (m := x3) (fetch_cast f2 (by omega))]
71
  simp [exec, hax3, hc]
 
74
  simp [hc, Word.isTrue]
75
 
76
  theorem sim_halt (hs : Rel0 c p s x) (hpc : x.pc = base)
77
+ (hat : RAt code base (lowerInstr L base off g .halt)) : RExec code x (.halted x) := by
78
  have hat' : RAt code base [.exitHalt] := hat
79
  obtain ⟨f0, _⟩ := hat'
80
  exact RExec.halt (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
 
83
  (`sp`). -/
84
  theorem sim_call_core (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
85
  (hat : RAt code base [.call (off t)])
86
+ (hret : base + 1 = offs c.facts p (s.pc + 1)) (hfitR : s.rstack.length + 2 ≤ c.rcap) :
87
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
88
  x'.pc = off t := by
89
  obtain ⟨f0, _⟩ := hat
 
175
  · simp only [List.length_cons]; omega
176
 
177
  theorem sim_ret_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base)
178
+ (hat : RAt code base (lowerInstr L base off g .ret)) {a : Nat} {rs : List Nat}
179
+ (hr : s.rstack = a :: rs) (hsz : offs c.facts p a < 2 ^ 32) :
180
+ ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := rs } x' ∧ x'.pc = offs c.facts p a := by
181
  have hat' : RAt code base [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
182
  obtain ⟨f0, f1, f3, _⟩ := hat'
183
  have hcapR := hs.capR
 
199
  rw [hr] at hread
200
  simp only [List.length_cons, Nat.mul_zero, Nat.add_zero] at hread
201
  have hst3 : step code { x1 with pc := base + 2 } = .next { (({ x1 with pc := base + 2 } : M).setReg
202
+ sp (ofN (c.sp0 - 4 * rs.length))) with pc := offs c.facts p a } := by
203
  rw [rstep_of_fetch (m := { x1 with pc := base + 2 }) f3]
204
  have hx1r : x1.regs sp = ofN (c.sp0 - 4 * (rs.length + 1)) := hrsp
205
  have hx1m : x1.mem = x.mem := rfl
206
  have hadd : ofN (c.sp0 - 4 * (rs.length + 1)) + 4#32 = ofN (c.sp0 - 4 * rs.length) := by
207
  show ofN _ + ofN 4 = _
208
  rw [ofN_add]; congr 1; omega
209
+ have hv : (ofN (offs c.facts p a)).toNat = offs c.facts p a := by
210
  simp [ofN, BitVec.toNat_ofNat, Nat.mod_eq_of_lt hsz]
211
  simp only [exec]
212
  rw [hx1m, hx1r, hread]
 
235
  omega
236
 
237
  theorem sim_ret_trap (hs : Rel0 c p s x) (hpc : x.pc = base)
238
+ (hat : RAt code base (lowerInstr L base off g .ret)) (hr : s.rstack = []) :
239
  RExec code x (.trapped .returnUnderflow) := by
240
  have hat' : RAt code base [.bcc .ne sp r9 (base + 2), .exitTrap .returnUnderflow, .ret] := hat
241
  obtain ⟨f0, f1, _⟩ := hat'
 
246
 
247
  /-- `call t`: the return-stack guard, then the model's `call`. -/
248
  theorem sim_call_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
249
+ (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off g (.call t)))
250
+ (hret : base + isize g (.call t : WordDialect.Instr 32) = offs c.facts p (s.pc + 1))
251
  (hfitR : s.rstack.length + 2 ≤ c.rcap) :
252
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with rstack := (s.pc + 1) :: s.rstack } x' ∧
253
  x'.pc = off t := by
 
260
  exact ⟨x', hs1.trans hs', hr', hpc'⟩
261
 
262
  theorem sim_call_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {t : Nat}
263
+ (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hat : RAt code base (lowerInstr L base off g (.call t)))
264
  (h : ¬ s.rstack.length + 2 ≤ c.rcap) : RExec code x .overflow := by
265
  have hat' : RAt code base (ovfR L base ++ [.call (off t)]) := hat
266
  exact ovfR_trap hg hs hLr h hpc (rat_append.mp hat').1
backend/cortexm0/CM0/SimDiv.lean CHANGED
@@ -19,7 +19,7 @@ open Reg
19
  section Div
20
 
21
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
22
- {L : Layout} {base : Nat} {off : Nat → Nat}
23
 
24
  /-- `Rel0` ignores scratch registers. -/
25
  theorem rel0_scratch (hs : Rel0 c p s x) {x' : M} (hm : x'.mem = x.mem)
@@ -52,18 +52,18 @@ theorem zg_trap (hb : x.regs r1 = 0#32) {t : Nat}
52
  run a division sequence `seg` that leaves `f a b` in `r0` (`CM0/Divide.lean`), store and pop. -/
53
  theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
54
  (hpc : x.pc = base) (seg : List (Instr Nat)) (f : W → W → W)
55
- (hseg : ∀ (m : M) (a b : W), RAt code (base + ufSize 2 + 4) seg → m.pc = base + ufSize 2 + 4 →
56
  m.regs r0 = a → m.regs r1 = b → b ≠ 0#32 →
57
- ∃ m', RSteps code m m' ∧ m'.pc = base + ufSize 2 + 4 + seg.length ∧ m'.regs r0 = f a b ∧
58
  m'.mem = m.mem ∧ ∀ r, ¬ DivScratch r → m'.regs r = m.regs r)
59
- (hat : RAt code base (uf L 2 base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
60
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero] ++ seg ++ [.store Reg.r4 4 r0,
61
  .addImm Reg.r4 4])))
62
  {a b : W} {d : List W} (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
63
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
64
- x'.pc = base + (ufSize 2 + 4 + seg.length + 2) := by
65
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
66
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
67
  rw [hufl] at hatr
68
  obtain ⟨hat4s, hatend⟩ := rat_append.mp hatr
69
  obtain ⟨hat4, hatseg⟩ := rat_append.mp hat4s
@@ -71,47 +71,47 @@ theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x
71
  obtain ⟨f5, f6, _⟩ := hatend
72
  simp only [List.length_append, List.length_cons, List.length_nil] at hatseg f5 f6
73
  have hk : 2 ≤ s.dstack.length := by simp [hd]
74
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
75
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
76
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
77
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
78
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
79
  have hcx3 : x3.regs r1 = b := by rw [ho3 r1 (by decide), hv2]
80
  obtain ⟨x4, hs4, hr4, hpc4, hreg4, hm4⟩ := zg_pass (code := code) hr3 hcx3 hb
81
- (t := base + ufSize 2 + 4) (by simp [ufSize]; omega)
82
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
83
  have hax4 : x4.regs r0 = a := by rw [hreg4, hv3]
84
  have hcx4 : x4.regs r1 = b := by rw [hreg4, hcx3]
85
- have hpc4' : x4.pc = base + ufSize 2 + 4 := by simp [ufSize]; omega
86
  obtain ⟨x5, hs5, hpc5, hax5, hm5, hfr5⟩ := hseg x4 a b
87
- (by simpa [ufSize, Nat.add_assoc] using hatseg) hpc4' hax4 hcx4 hb
88
  have hr5 : Rel0 c p s x5 :=
89
  hr4.congr hm5 (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
90
  (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
91
  (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
92
  obtain ⟨x6, hs6, hr6, hpc6, _⟩ := st_step (code := code) hg hr5 (j := 1) (by simp [hd])
93
- (rs := r0) (disp := 4) (by simp) (fetch_cast f5 (by simp [ufSize] at hpc5 ⊢; omega))
94
  have hlen : 1 ≤ ({ s with dstack := s.dstack.set 1 (x5.regs r0) } : State 32).dstack.length := by
95
  simp [hd]
96
  obtain ⟨x7, hs7, hr7, hpc7, _⟩ := adj_step (code := code) hg hr6 (n := 1) hlen (δ := 4) (by simp)
97
- (fetch_cast f6 (by simp [ufSize] at hpc5 hpc6 ⊢; omega))
98
  have hr7' : Rel0 c p { s with dstack := (s.dstack.set 1 (x5.regs r0)).drop 1 } x7 := hr7
99
  have e : (s.dstack.set 1 (x5.regs r0)).drop 1 = f a b :: d := by simp [hd, hax5]
100
  rw [e] at hr7'
101
  exact ⟨x7, ((((hs1.trans hs2).trans hs3).trans hs4).trans (hs5.trans (hs6.trans hs7))), hr7', by
102
- simp [ufSize] at hpc7 hpc6 hpc5 ⊢; omega⟩
103
 
104
  theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
105
  (hpc : x.pc = base) (rest : List (Instr Nat))
106
- (hat : RAt code base (uf L 2 base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
107
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero] ++ rest)))
108
  {a : W} {d : List W} (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) := by
109
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
110
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
111
  rw [hufl] at hatr
112
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
113
  have hk : 2 ≤ s.dstack.length := by simp [hd]
114
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
115
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := 0#32)
116
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
117
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -121,12 +121,12 @@ theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
121
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
122
 
123
  theorem sim_div_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
124
- (hat : RAt code base (lowerInstr L base off .div)) {a b : W} {d : List W}
125
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
126
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.udiv b :: d } x' ∧
127
- x'.pc = base + isize (.div : WordDialect.Instr 32) := by
128
- have hat' : RAt code base (uf L 2 base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
129
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero] ++ udivSeq (base + ufSize 2 + 4) ++
130
  [.store Reg.r4 4 r0, .addImm Reg.r4 4])) := hat
131
  obtain ⟨x', hs', hr', hpc'⟩ := sim_divop_ok hg hL hs hpc _ BitVec.udiv
132
  (fun m a b hat hpc h0 h1 hb => by
@@ -134,18 +134,18 @@ theorem sim_div_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
134
  exact ⟨x', hs', hr', by rw [hpc']; simp [isize, udivSeq, udivCode]⟩
135
 
136
  theorem sim_div_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
137
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .div)) {a : W} {d : List W}
138
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
139
- sim_divop_zero hg hL hs hpc (udivSeq (base + ufSize 2 + 4) ++ [.store Reg.r4 4 r0, .addImm Reg.r4 4])
140
  (by simpa [lowerInstr, List.append_assoc] using hat) hd
141
 
142
  theorem sim_sdiv_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
143
- (hat : RAt code base (lowerInstr L base off .sdiv)) {a b : W} {d : List W}
144
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
145
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.sdiv b :: d } x' ∧
146
- x'.pc = base + isize (.sdiv : WordDialect.Instr 32) := by
147
- have hat' : RAt code base (uf L 2 base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
148
- .bnez r1 (base + ufSize 2 + 4), .exitTrap .divideByZero] ++ sdivSeq (base + ufSize 2 + 4) ++
149
  [.store Reg.r4 4 r0, .addImm Reg.r4 4])) := hat
150
  obtain ⟨x', hs', hr', hpc'⟩ := sim_divop_ok hg hL hs hpc _ BitVec.sdiv
151
  (fun m a b hat hpc h0 h1 hb => by
@@ -153,26 +153,26 @@ theorem sim_sdiv_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
153
  exact ⟨x', hs', hr', by rw [hpc']; simp [isize, sdivSeq, udivCode]⟩
154
 
155
  theorem sim_sdiv_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
156
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .sdiv)) {a : W} {d : List W}
157
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
158
- sim_divop_zero hg hL hs hpc (sdivSeq (base + ufSize 2 + 4) ++ [.store Reg.r4 4 r0, .addImm Reg.r4 4])
159
  (by simpa [lowerInstr, List.append_assoc] using hat) hd
160
 
161
  theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
162
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .select)) {cc y v : W}
163
  {d : List W} (hd : s.dstack = cc :: y :: v :: d) :
164
  ∃ x', RSteps code x x' ∧
165
  Rel0 c p { s with dstack := (if Word.isTrue cc then v else y) :: d } x' ∧
166
- x'.pc = base + isize (.select : WordDialect.Instr 32) := by
167
- have hat' : RAt code base (uf L 3 base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
168
- .load r3 Reg.r4 8, .beqz r1 (base + ufSize 3 + 5), .movRR r0 r3, .store Reg.r4 8 r0,
169
  .addImm Reg.r4 8]) := hat
170
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
171
- have hufl : (uf L 3 base).length = 3 := by simp [uf]
172
  rw [hufl] at hatr
173
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
174
  have hk : 3 ≤ s.dstack.length := by simp [hd]
175
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
176
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
177
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
178
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := y)
@@ -181,13 +181,13 @@ theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
181
  (by simp [hd]) (rd := r3) (by simp) (disp := 8) (by simp) (fetch_cast f2 (by omega))
182
  have hcx4 : x4.regs r1 = cc := by rw [ho4 r1 (by decide), ho3 r1 (by decide), hv2]
183
  have hax4 : x4.regs r0 = y := by rw [ho4 r0 (by decide), hv3]
184
- -- after the branch (and the `mv` when `cc ≠ 0`), `r0` holds the result at `base + 3 + 5`
185
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
186
- x6.pc = base + 3 + 5 ∧ x6.regs r0 = (if Word.isTrue cc then v else y) := by
187
  by_cases hc : cc = 0#32
188
- · have hst : step code x4 = .next { x4 with pc := base + ufSize 3 + 5 } := by
189
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
190
- refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, by simp [ufSize], ?_⟩
191
  simp [hax4, Word.isTrue, hc]
192
  · have hst : step code x4 = .next x4.adv := by
193
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
@@ -210,24 +210,24 @@ theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s
210
  simp [hd, hval]
211
  rw [e] at hr8'
212
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
213
- by simp [isize, ufSize]; omega⟩
214
 
215
  /-- `cmp c`: `r2 := 1`, then `bcc c` skips `r2 := 0` exactly when the IR comparison holds. -/
216
  theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
217
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off (.cmp cd)))
218
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧
220
  Rel0 c p { s with dstack := Word.ofBool (cd.eval a b) :: d } x' ∧
221
- x'.pc = base + isize (.cmp cd : WordDialect.Instr 32) := by
222
- have hat' : RAt code base (uf L 2 base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
223
- .movImm r2 1#32, .bcc cd r0 r1 (base + ufSize 2 + 5), .movImm r2 0#32, .store Reg.r4 4 r2,
224
  .addImm Reg.r4 4]) := hat
225
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
226
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
227
  rw [hufl] at hatr
228
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
229
  have hk : 2 ≤ s.dstack.length := by simp [hd]
230
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
231
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
232
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
233
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -238,11 +238,11 @@ theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dE
238
  have hax4 : x4.regs r0 = a := by rw [ho4 r0 (by decide), hv3]
239
  have hcx4 : x4.regs r1 = b := by rw [ho4 r1 (by decide), hcx3]
240
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
241
- x6.pc = base + 3 + 5 ∧ x6.regs r2 = Word.ofBool (cd.eval a b) := by
242
  by_cases hc : cd.eval a b = true
243
- · have hst : step code x4 = .next { x4 with pc := base + ufSize 2 + 5 } := by
244
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hax4, hcx4, hc]
245
- refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, by simp [ufSize], ?_⟩
246
  simp [hv4, hc, Word.ofBool]
247
  · have hc' : cd.eval a b = false := by simpa using hc
248
  have hst : step code x4 = .next x4.adv := by
@@ -263,7 +263,7 @@ theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dE
263
  simp [hd, hval]
264
  rw [e] at hr8'
265
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
266
- by simp [isize, ufSize]; omega⟩
267
 
268
  end Div
269
 
 
19
  section Div
20
 
21
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
22
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
23
 
24
  /-- `Rel0` ignores scratch registers. -/
25
  theorem rel0_scratch (hs : Rel0 c p s x) {x' : M} (hm : x'.mem = x.mem)
 
52
  run a division sequence `seg` that leaves `f a b` in `r0` (`CM0/Divide.lean`), store and pop. -/
53
  theorem sim_divop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
54
  (hpc : x.pc = base) (seg : List (Instr Nat)) (f : W → W → W)
55
+ (hseg : ∀ (m : M) (a b : W), RAt code (base + ufSize (need g 2) + 4) seg → m.pc = base + ufSize (need g 2) + 4 →
56
  m.regs r0 = a → m.regs r1 = b → b ≠ 0#32 →
57
+ ∃ m', RSteps code m m' ∧ m'.pc = base + ufSize (need g 2) + 4 + seg.length ∧ m'.regs r0 = f a b ∧
58
  m'.mem = m.mem ∧ ∀ r, ¬ DivScratch r → m'.regs r = m.regs r)
59
+ (hat : RAt code base (uf L (need g 2) base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
60
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero] ++ seg ++ [.store Reg.r4 4 r0,
61
  .addImm Reg.r4 4])))
62
  {a b : W} {d : List W} (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
63
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
64
+ x'.pc = base + (ufSize (need g 2) + 4 + seg.length + 2) := by
65
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
66
+ have hufl := uf_length L (need g 2) base
67
  rw [hufl] at hatr
68
  obtain ⟨hat4s, hatend⟩ := rat_append.mp hatr
69
  obtain ⟨hat4, hatseg⟩ := rat_append.mp hat4s
 
71
  obtain ⟨f5, f6, _⟩ := hatend
72
  simp only [List.length_append, List.length_cons, List.length_nil] at hatseg f5 f6
73
  have hk : 2 ≤ s.dstack.length := by simp [hd]
74
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
75
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
76
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
77
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
78
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
79
  have hcx3 : x3.regs r1 = b := by rw [ho3 r1 (by decide), hv2]
80
  obtain ⟨x4, hs4, hr4, hpc4, hreg4, hm4⟩ := zg_pass (code := code) hr3 hcx3 hb
81
+ (t := base + ufSize (need g 2) + 4) (by omega)
82
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
83
  have hax4 : x4.regs r0 = a := by rw [hreg4, hv3]
84
  have hcx4 : x4.regs r1 = b := by rw [hreg4, hcx3]
85
+ have hpc4' : x4.pc = base + ufSize (need g 2) + 4 := by omega
86
  obtain ⟨x5, hs5, hpc5, hax5, hm5, hfr5⟩ := hseg x4 a b
87
+ (by simpa [Nat.add_assoc] using hatseg) hpc4' hax4 hcx4 hb
88
  have hr5 : Rel0 c p s x5 :=
89
  hr4.congr hm5 (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
90
  (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
91
  (hfr5 _ (by simp [DivScratch])) (hfr5 _ (by simp [DivScratch]))
92
  obtain ⟨x6, hs6, hr6, hpc6, _⟩ := st_step (code := code) hg hr5 (j := 1) (by simp [hd])
93
+ (rs := r0) (disp := 4) (by simp) (fetch_cast f5 (by omega))
94
  have hlen : 1 ≤ ({ s with dstack := s.dstack.set 1 (x5.regs r0) } : State 32).dstack.length := by
95
  simp [hd]
96
  obtain ⟨x7, hs7, hr7, hpc7, _⟩ := adj_step (code := code) hg hr6 (n := 1) hlen (δ := 4) (by simp)
97
+ (fetch_cast f6 (by omega))
98
  have hr7' : Rel0 c p { s with dstack := (s.dstack.set 1 (x5.regs r0)).drop 1 } x7 := hr7
99
  have e : (s.dstack.set 1 (x5.regs r0)).drop 1 = f a b :: d := by simp [hd, hax5]
100
  rw [e] at hr7'
101
  exact ⟨x7, ((((hs1.trans hs2).trans hs3).trans hs4).trans (hs5.trans (hs6.trans hs7))), hr7', by
102
+ omega⟩
103
 
104
  theorem sim_divop_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
105
  (hpc : x.pc = base) (rest : List (Instr Nat))
106
+ (hat : RAt code base (uf L (need g 2) base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
107
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero] ++ rest)))
108
  {a : W} {d : List W} (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) := by
109
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat
110
+ have hufl := uf_length L (need g 2) base
111
  rw [hufl] at hatr
112
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
113
  have hk : 2 ≤ s.dstack.length := by simp [hd]
114
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
115
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := 0#32)
116
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
117
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
121
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
122
 
123
  theorem sim_div_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
124
+ (hat : RAt code base (lowerInstr L base off g .div)) {a b : W} {d : List W}
125
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
126
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.udiv b :: d } x' ∧
127
+ x'.pc = base + isize g (.div : WordDialect.Instr 32) := by
128
+ have hat' : RAt code base (uf L (need g 2) base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
129
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero] ++ udivSeq (base + ufSize (need g 2) + 4) ++
130
  [.store Reg.r4 4 r0, .addImm Reg.r4 4])) := hat
131
  obtain ⟨x', hs', hr', hpc'⟩ := sim_divop_ok hg hL hs hpc _ BitVec.udiv
132
  (fun m a b hat hpc h0 h1 hb => by
 
134
  exact ⟨x', hs', hr', by rw [hpc']; simp [isize, udivSeq, udivCode]⟩
135
 
136
  theorem sim_div_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
137
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .div)) {a : W} {d : List W}
138
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
139
+ sim_divop_zero hg hL hs hpc (udivSeq (base + ufSize (need g 2) + 4) ++ [.store Reg.r4 4 r0, .addImm Reg.r4 4])
140
  (by simpa [lowerInstr, List.append_assoc] using hat) hd
141
 
142
  theorem sim_sdiv_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
143
+ (hat : RAt code base (lowerInstr L base off g .sdiv)) {a b : W} {d : List W}
144
  (hd : s.dstack = b :: a :: d) (hb : b ≠ 0#32) :
145
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a.sdiv b :: d } x' ∧
146
+ x'.pc = base + isize g (.sdiv : WordDialect.Instr 32) := by
147
+ have hat' : RAt code base (uf L (need g 2) base ++ ([.load r1 Reg.r4 0, .load r0 Reg.r4 4,
148
+ .bnez r1 (base + ufSize (need g 2) + 4), .exitTrap .divideByZero] ++ sdivSeq (base + ufSize (need g 2) + 4) ++
149
  [.store Reg.r4 4 r0, .addImm Reg.r4 4])) := hat
150
  obtain ⟨x', hs', hr', hpc'⟩ := sim_divop_ok hg hL hs hpc _ BitVec.sdiv
151
  (fun m a b hat hpc h0 h1 hb => by
 
153
  exact ⟨x', hs', hr', by rw [hpc']; simp [isize, sdivSeq, udivCode]⟩
154
 
155
  theorem sim_sdiv_zero (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
156
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .sdiv)) {a : W} {d : List W}
157
  (hd : s.dstack = 0#32 :: a :: d) : RExec code x (.trapped .divideByZero) :=
158
+ sim_divop_zero hg hL hs hpc (sdivSeq (base + ufSize (need g 2) + 4) ++ [.store Reg.r4 4 r0, .addImm Reg.r4 4])
159
  (by simpa [lowerInstr, List.append_assoc] using hat) hd
160
 
161
  theorem sim_select_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
162
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .select)) {cc y v : W}
163
  {d : List W} (hd : s.dstack = cc :: y :: v :: d) :
164
  ∃ x', RSteps code x x' ∧
165
  Rel0 c p { s with dstack := (if Word.isTrue cc then v else y) :: d } x' ∧
166
+ x'.pc = base + isize g (.select : WordDialect.Instr 32) := by
167
+ have hat' : RAt code base (uf L (need g 3) base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
168
+ .load r3 Reg.r4 8, .beqz r1 (base + ufSize (need g 3) + 5), .movRR r0 r3, .store Reg.r4 8 r0,
169
  .addImm Reg.r4 8]) := hat
170
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
171
+ have hufl := uf_length L (need g 3) base
172
  rw [hufl] at hatr
173
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
174
  have hk : 3 ≤ s.dstack.length := by simp [hd]
175
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
176
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
177
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
178
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := y)
 
181
  (by simp [hd]) (rd := r3) (by simp) (disp := 8) (by simp) (fetch_cast f2 (by omega))
182
  have hcx4 : x4.regs r1 = cc := by rw [ho4 r1 (by decide), ho3 r1 (by decide), hv2]
183
  have hax4 : x4.regs r0 = y := by rw [ho4 r0 (by decide), hv3]
184
+ -- after the branch (and the `mv` when `cc ≠ 0`), `r0` holds the result at `base + ufSize (need g 3) + 5`
185
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
186
+ x6.pc = base + ufSize (need g 3) + 5 ∧ x6.regs r0 = (if Word.isTrue cc then v else y) := by
187
  by_cases hc : cc = 0#32
188
+ · have hst : step code x4 = .next { x4 with pc := base + ufSize (need g 3) + 5 } := by
189
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
190
+ refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, rfl, ?_⟩
191
  simp [hax4, Word.isTrue, hc]
192
  · have hst : step code x4 = .next x4.adv := by
193
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hcx4, hc]
 
210
  simp [hd, hval]
211
  rw [e] at hr8'
212
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
213
+ by simp [isize]; omega⟩
214
 
215
  /-- `cmp c`: `r2 := 1`, then `bcc c` skips `r2 := 0` exactly when the IR comparison holds. -/
216
  theorem sim_cmp_ok (cd : WordDialect.Cond) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
217
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g (.cmp cd)))
218
  {b a : W} {d : List W} (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧
220
  Rel0 c p { s with dstack := Word.ofBool (cd.eval a b) :: d } x' ∧
221
+ x'.pc = base + isize g (.cmp cd : WordDialect.Instr 32) := by
222
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r1 Reg.r4 0, .load r0 Reg.r4 4,
223
+ .movImm r2 1#32, .bcc cd r0 r1 (base + ufSize (need g 2) + 5), .movImm r2 0#32, .store Reg.r4 4 r2,
224
  .addImm Reg.r4 4]) := hat
225
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
226
+ have hufl := uf_length L (need g 2) base
227
  rw [hufl] at hatr
228
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, _⟩ := hatr
229
  have hk : 2 ≤ s.dstack.length := by simp [hd]
230
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
231
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
232
  (by simp [hd]) (rd := r1) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
233
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
238
  have hax4 : x4.regs r0 = a := by rw [ho4 r0 (by decide), hv3]
239
  have hcx4 : x4.regs r1 = b := by rw [ho4 r1 (by decide), hcx3]
240
  obtain ⟨x6, hs6, hr6, hpc6, hval⟩ : ∃ x6, RSteps code x4 x6 ∧ Rel0 c p s x6 ∧
241
+ x6.pc = base + ufSize (need g 2) + 5 ∧ x6.regs r2 = Word.ofBool (cd.eval a b) := by
242
  by_cases hc : cd.eval a b = true
243
+ · have hst : step code x4 = .next { x4 with pc := base + ufSize (need g 2) + 5 } := by
244
  rw [rstep_of_fetch (m := x4) (fetch_cast f3 (by omega))]; simp [exec, hax4, hcx4, hc]
245
+ refine ⟨_, RSteps.single hst, hr4.congr rfl rfl rfl rfl rfl rfl rfl, rfl, ?_⟩
246
  simp [hv4, hc, Word.ofBool]
247
  · have hc' : cd.eval a b = false := by simpa using hc
248
  have hst : step code x4 = .next x4.adv := by
 
263
  simp [hd, hval]
264
  rw [e] at hr8'
265
  exact ⟨x8, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs6).trans hs7).trans hs8, hr8',
266
+ by simp [isize]; omega⟩
267
 
268
  end Div
269
 
backend/cortexm0/CM0/SimMemOps.lean CHANGED
@@ -16,7 +16,7 @@ open Reg
16
  section Ops
17
 
18
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
- {L : Layout} {base : Nat} {off : Nat → Nat}
20
 
21
  theorem ult_memSize {a : W} {n : Nat} (hn : n < 2 ^ 32) :
22
  a.ult (BitVec.ofNat 32 n) = decide (a.toNat < n) := by
@@ -65,42 +65,42 @@ theorem addr_trap (hs : Rel0 c p s x) {rt : Reg} (hrt : rt = r1 ∨ rt = r2) {n
65
 
66
  theorem sim_push_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
67
  (hr : r < c.nregs) (hLd : L.dLim = ofN (c.dBase + 4))
68
- (hat : RAt code base (lowerInstr L base off (.push r)))
69
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
70
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := s.regs r :: s.dstack } x' ∧
71
- x'.pc = base + isize (.push r : WordDialect.Instr 32) := by
72
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
73
- obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfD_pass hg hs hLd hfit hpc hato
74
  have hst : step code x0 = .next (x0.mov r0 (s.regs r)) := by
75
  rw [rstep_of_fetch (by rw [hpc0]; exact f0), ld_reg hr0 hr r0 rfl]
76
  have hr1 : Rel0 c p s (x0.mov r0 (s.regs r)) := mov_rel0 hr0 r0 (scratch_ne r0 (by simp)) _
77
- have hpc1 : (x0.mov r0 (s.regs r)).pc = base + 3 + 1 := by simp [M.mov, M.setReg, M.adv, hpc0]
78
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
79
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
80
  have hv : (x0.mov r0 (s.regs r)).regs r0 = s.regs r := by simp [M.mov, M.setReg, M.adv]
81
  rw [hv] at hr2
82
  exact ⟨x2, (hs0.trans (RSteps.single hst)).trans hs2, hr2, by simp [isize]; omega⟩
83
 
84
- theorem sim_push_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
85
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.push r)))
86
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
87
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
88
- exact ovfD_trap hg hs hLd h hpc hato
89
 
90
  theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
91
- {r : Nat} (hr : r < c.nregs) (hat : RAt code base (lowerInstr L base off (.pop r)))
92
  {a : W} {d : List W} (hd : s.dstack = a :: d) :
93
  ∃ x', RSteps code x x' ∧
94
  Rel0 c p { s with dstack := d, regs := State.setReg s.regs r a } x' ∧
95
- x'.pc = base + isize (.pop r : WordDialect.Instr 32) := by
96
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
97
  .store Reg.r5 (4 * (r : Int)) r0]) := hat
98
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
99
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
100
  rw [hufl] at hatr
101
  obtain ⟨f0, f1, f2, _⟩ := hatr
102
  have hk : 1 ≤ s.dstack.length := by simp [hd]
103
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
104
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
105
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
106
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
@@ -114,18 +114,18 @@ theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
114
  have e : s.dstack.drop 1 = d := by simp [hd]
115
  rw [e, hax3] at hr4'
116
  exact ⟨_, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4), hr4',
117
- by simp [M.adv, isize, ufSize]; omega⟩
118
 
119
  theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
120
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .load))
121
  {a v : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = some v) :
122
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := v :: d } x' ∧
123
- x'.pc = base + isize (.load : WordDialect.Instr 32) := by
124
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
125
- .bcc .ult r0 r1 (base + ufSize 1 + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8,
126
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
127
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
128
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
129
  rw [hufl] at hatr
130
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, _⟩ := hatr
131
  have hk : 1 ≤ s.dstack.length := by simp [hd]
@@ -135,11 +135,11 @@ theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
135
  have := hs.irvalid a
136
  rw [hvv] at this
137
  simpa using this.symm
138
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
139
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
140
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
141
  obtain ⟨x3, hs3, hr3, hpc3, hax3, ho3, hm3⟩ := addr_pass (code := code) hr2 (rt := r1) (by simp)
142
- (n := c.M) hMlt (t := base + ufSize 1 + 4) (by simp [ufSize]; omega) hv2 hlt (by
143
  rw [← hMs]
144
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
145
  obtain ⟨x4, hs4, hr4, hpc4, hax4, _, _⟩ := idx_steps hr3 hax3
@@ -153,17 +153,17 @@ theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
153
  simp [hd, M.mov, M.setReg, M.adv]
154
  rw [e] at hr6
155
  exact ⟨x6, ((((hs1.trans hs2).trans hs3).trans hs4).trans (RSteps.single hst5)).trans hs6, hr6,
156
- by simp [M.mov, M.setReg, M.adv, isize, ufSize] at *; omega⟩
157
 
158
  theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
159
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .load))
160
  {a : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = none) :
161
  RExec code x (.trapped .badAddress) := by
162
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
163
- .bcc .ult r0 r1 (base + ufSize 1 + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8,
164
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
165
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
166
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
167
  rw [hufl] at hatr
168
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
169
  have hk : 1 ≤ s.dstack.length := by simp [hd]
@@ -173,25 +173,25 @@ theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize
173
  have := hs.irvalid a
174
  rw [hvv] at this
175
  simpa using this
176
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
177
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
178
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
179
  exact RExec.of_steps (hs1.trans hs2) (addr_trap (code := code) hr2 (rt := r1) (by simp)
180
- (n := c.M) hMlt (t := base + ufSize 1 + 4) (by simp [ufSize]; omega) hv2 hge (by
181
  rw [← hMs]
182
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩))
183
 
184
  theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
185
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .store))
186
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) {m : Memory 32}
187
  (hw : s.mem.write? a v = some m) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, mem := m } x' ∧
189
- x'.pc = base + isize (.store : WordDialect.Instr 32) := by
190
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
191
- .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize 2 + 5),
192
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8, .store r0 0 r1, .addImm Reg.r4 8]) := hat
193
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
194
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
195
  rw [hufl] at hatr
196
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, f8, _⟩ := hatr
197
  have hk : 2 ≤ s.dstack.length := by simp [hd]
@@ -204,14 +204,14 @@ theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
204
  have := hs.irvalid a
205
  rw [hv] at this
206
  simpa using this.symm
207
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
212
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
213
  obtain ⟨x4, hs4, hr4, hpc4, hax4, ho4, hm4⟩ := addr_pass (code := code) hr3 (rt := r2) (by simp)
214
- (n := c.M) hMlt (t := base + ufSize 2 + 5) (by simp [ufSize]; omega) hax3 hlt (by
215
  rw [← hMs]
216
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩)
217
  have hcx4 : x4.regs r1 = v := by rw [ho4 r1 (by decide), hv3]
@@ -229,17 +229,17 @@ theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize =
229
  = { s with dstack := d, mem := m } := by simp [hd]
230
  rw [← this]; exact hr7
231
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans (RSteps.single hst6)).trans hs7,
232
- hr7', by simp [M.adv, isize, ufSize] at *; omega⟩
233
 
234
  theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
235
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .store))
236
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) (hw : s.mem.write? a v = none) :
237
  RExec code x (.trapped .badAddress) := by
238
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
239
- .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize 2 + 5),
240
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8, .store r0 0 r1, .addImm Reg.r4 8]) := hat
241
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
242
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
243
  rw [hufl] at hatr
244
  obtain ⟨f0, f1, f2, f3, f4, _⟩ := hatr
245
  have hk : 2 ≤ s.dstack.length := by simp [hd]
@@ -249,14 +249,14 @@ theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize
249
  have := hs.irvalid a
250
  rw [hvv] at this
251
  simpa using this
252
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
253
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
254
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
255
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
256
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
257
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
258
  exact RExec.of_steps ((hs1.trans hs2).trans hs3) (addr_trap (code := code) hr3 (rt := r2)
259
- (by simp) (n := c.M) hMlt (t := base + ufSize 2 + 5) (by simp [ufSize]; omega) hax3 hge (by
260
  rw [← hMs]
261
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩))
262
 
 
16
  section Ops
17
 
18
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
20
 
21
  theorem ult_memSize {a : W} {n : Nat} (hn : n < 2 ^ 32) :
22
  a.ult (BitVec.ofNat 32 n) = decide (a.toNat < n) := by
 
65
 
66
  theorem sim_push_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
67
  (hr : r < c.nregs) (hLd : L.dLim = ofN (c.dBase + 4))
68
+ (hat : RAt code base (lowerInstr L base off g (.push r)))
69
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
70
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := s.regs r :: s.dstack } x' ∧
71
+ x'.pc = base + isize g (.push r : WordDialect.Instr 32) := by
72
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
73
+ obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfG_pass hg hs hLd hfit hpc hato
74
  have hst : step code x0 = .next (x0.mov r0 (s.regs r)) := by
75
  rw [rstep_of_fetch (by rw [hpc0]; exact f0), ld_reg hr0 hr r0 rfl]
76
  have hr1 : Rel0 c p s (x0.mov r0 (s.regs r)) := mov_rel0 hr0 r0 (scratch_ne r0 (by simp)) _
77
+ have hpc1 : (x0.mov r0 (s.regs r)).pc = base + ovfSize g + 1 := by simp [M.mov, M.setReg, M.adv, hpc0]
78
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
79
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
80
  have hv : (x0.mov r0 (s.regs r)).regs r0 = s.regs r := by simp [M.mov, M.setReg, M.adv]
81
  rw [hv] at hr2
82
  exact ⟨x2, (hs0.trans (RSteps.single hst)).trans hs2, hr2, by simp [isize]; omega⟩
83
 
84
+ theorem sim_push_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) {r : Nat}
85
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.push r)))
86
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
87
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
88
+ exact ovfG_trap hn hg hs hLd h hpc hato
89
 
90
  theorem sim_pop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
91
+ {r : Nat} (hr : r < c.nregs) (hat : RAt code base (lowerInstr L base off g (.pop r)))
92
  {a : W} {d : List W} (hd : s.dstack = a :: d) :
93
  ∃ x', RSteps code x x' ∧
94
  Rel0 c p { s with dstack := d, regs := State.setReg s.regs r a } x' ∧
95
+ x'.pc = base + isize g (.pop r : WordDialect.Instr 32) := by
96
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .addImm Reg.r4 4,
97
  .store Reg.r5 (4 * (r : Int)) r0]) := hat
98
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
99
+ have hufl := uf_length L (need g 1) base
100
  rw [hufl] at hatr
101
  obtain ⟨f0, f1, f2, _⟩ := hatr
102
  have hk : 1 ≤ s.dstack.length := by simp [hd]
103
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
104
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
105
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
106
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := adj_step (code := code) hg hr2 (n := 1) (by simp [hd])
 
114
  have e : s.dstack.drop 1 = d := by simp [hd]
115
  rw [e, hax3] at hr4'
116
  exact ⟨_, ((hs1.trans hs2).trans hs3).trans (RSteps.single hst4), hr4',
117
+ by simp [M.adv, isize]; omega⟩
118
 
119
  theorem sim_load_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
120
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
121
  {a v : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = some v) :
122
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := v :: d } x' ∧
123
+ x'.pc = base + isize g (.load : WordDialect.Instr 32) := by
124
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
125
+ .bcc .ult r0 r1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8,
126
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
127
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
128
+ have hufl := uf_length L (need g 1) base
129
  rw [hufl] at hatr
130
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, _⟩ := hatr
131
  have hk : 1 ≤ s.dstack.length := by simp [hd]
 
135
  have := hs.irvalid a
136
  rw [hvv] at this
137
  simpa using this.symm
138
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
139
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
140
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
141
  obtain ⟨x3, hs3, hr3, hpc3, hax3, ho3, hm3⟩ := addr_pass (code := code) hr2 (rt := r1) (by simp)
142
+ (n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hlt (by
143
  rw [← hMs]
144
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩)
145
  obtain ⟨x4, hs4, hr4, hpc4, hax4, _, _⟩ := idx_steps hr3 hax3
 
153
  simp [hd, M.mov, M.setReg, M.adv]
154
  rw [e] at hr6
155
  exact ⟨x6, ((((hs1.trans hs2).trans hs3).trans hs4).trans (RSteps.single hst5)).trans hs6, hr6,
156
+ by simp [M.mov, M.setReg, M.adv, isize] at *; omega⟩
157
 
158
  theorem sim_load_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
159
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .load))
160
  {a : W} {d : List W} (hd : s.dstack = a :: d) (hv : s.mem.read? a = none) :
161
  RExec code x (.trapped .badAddress) := by
162
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .movImm r1 (BitVec.ofNat 32 L.memSize),
163
+ .bcc .ult r0 r1 (base + ufSize (need g 1) + 4), .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8,
164
  .load r0 r0 0, .store Reg.r4 0 r0]) := hat
165
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
166
+ have hufl := uf_length L (need g 1) base
167
  rw [hufl] at hatr
168
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
169
  have hk : 1 ≤ s.dstack.length := by simp [hd]
 
173
  have := hs.irvalid a
174
  rw [hvv] at this
175
  simpa using this
176
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
177
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
178
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
179
  exact RExec.of_steps (hs1.trans hs2) (addr_trap (code := code) hr2 (rt := r1) (by simp)
180
+ (n := c.M) hMlt (t := base + ufSize (need g 1) + 4) (by omega) hv2 hge (by
181
  rw [← hMs]
182
  refine ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩))
183
 
184
  theorem sim_store_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
185
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
186
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) {m : Memory 32}
187
  (hw : s.mem.write? a v = some m) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, mem := m } x' ∧
189
+ x'.pc = base + isize g (.store : WordDialect.Instr 32) := by
190
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
191
+ .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize (need g 2) + 5),
192
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8, .store r0 0 r1, .addImm Reg.r4 8]) := hat
193
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
194
+ have hufl := uf_length L (need g 2) base
195
  rw [hufl] at hatr
196
  obtain ⟨f0, f1, f2, f3, f4, f5, f6, f7, f8, _⟩ := hatr
197
  have hk : 2 ≤ s.dstack.length := by simp [hd]
 
204
  have := hs.irvalid a
205
  rw [hv] at this
206
  simpa using this.symm
207
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
211
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
212
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
213
  obtain ⟨x4, hs4, hr4, hpc4, hax4, ho4, hm4⟩ := addr_pass (code := code) hr3 (rt := r2) (by simp)
214
+ (n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hlt (by
215
  rw [← hMs]
216
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩)
217
  have hcx4 : x4.regs r1 = v := by rw [ho4 r1 (by decide), hv3]
 
229
  = { s with dstack := d, mem := m } := by simp [hd]
230
  rw [← this]; exact hr7
231
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans (RSteps.single hst6)).trans hs7,
232
+ hr7', by simp [M.adv, isize] at *; omega⟩
233
 
234
  theorem sim_store_trap (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
235
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .store))
236
  {a v : W} {d : List W} (hd : s.dstack = a :: v :: d) (hw : s.mem.write? a v = none) :
237
  RExec code x (.trapped .badAddress) := by
238
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
239
+ .movImm r2 (BitVec.ofNat 32 L.memSize), .bcc .ult r0 r2 (base + ufSize (need g 2) + 5),
240
  .exitTrap .badAddress, .shlImm r0 2, .add r0 Reg.r8, .store r0 0 r1, .addImm Reg.r4 8]) := hat
241
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
242
+ have hufl := uf_length L (need g 2) base
243
  rw [hufl] at hatr
244
  obtain ⟨f0, f1, f2, f3, f4, _⟩ := hatr
245
  have hk : 2 ≤ s.dstack.length := by simp [hd]
 
249
  have := hs.irvalid a
250
  rw [hvv] at this
251
  simpa using this
252
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
253
  obtain ⟨x2, hs2, hr2, hpc2, hv2, ho2, hm2⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
254
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
255
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, hm3⟩ := ld_step (code := code) hr2 (j := 1) (v := v)
256
  (by simp [hd]) (rd := r1) (by simp) (disp := 4) (by simp) (fetch_cast f1 (by omega))
257
  have hax3 : x3.regs r0 = a := by rw [ho3 r0 (by decide), hv2]
258
  exact RExec.of_steps ((hs1.trans hs2).trans hs3) (addr_trap (code := code) hr3 (rt := r2)
259
+ (by simp) (n := c.M) hMlt (t := base + ufSize (need g 2) + 5) (by omega) hax3 hge (by
260
  rw [← hMs]
261
  refine ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), fetch_cast f4 (by omega), trivial⟩))
262
 
backend/cortexm0/CM0/SimOps.lean CHANGED
@@ -16,40 +16,40 @@ open Reg
16
 
17
  /-- Operand-count trap: any lowering that starts with `uf n` exits with `stackUnderflow`. -/
18
  theorem sim_uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
- {L : Layout} {base n : Nat} {rest : List (Instr Nat)} (hg : Geom c) (hs : Rel0 c p s x)
20
- (hL : L.dEnd = ofN c.dEnd) (hn : 0 < n) (hn3 : n ≤ 3) (hk : s.dstack.length < n)
21
- (hpc : x.pc = base) (hat : RAt code base (uf L n base ++ rest)) :
22
  RExec code x (.trapped .stackUnderflow) :=
23
- uf_trap hg hs hL hn hn3 hk hpc (rat_append.mp hat).1
24
 
25
  macro "mid_tac" : tactic =>
26
  `(tactic| (intro m a b ha hb
27
  simp [rseq, exec, M.arith, M.mov, M.setReg, M.adv, ha, hb, MidSpec]))
28
 
29
  theorem sim_bin_instr {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
30
- {L : Layout} {base : Nat} {off : Nat → Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
31
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (mid : List (Instr Nat))
32
  (rr : Reg) (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
33
  (hmid : MidSpec mid rr f) (hstr : ∀ j ∈ mid, j.straightR = true)
34
- (hlow : lowerInstr L base off i = uf L 2 base ++
35
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4]))
36
- (hsize : isize i = 3 + (4 + mid.length))
37
- (hat : RAt code base (lowerInstr L base off i)) {b a : W} {d : List W}
38
  (hd : s.dstack = b :: a :: d) :
39
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
40
- x'.pc = base + isize i := by
41
  rw [hlow] at hat
42
  obtain ⟨x', h1, h2, h3⟩ := sim_bin_ok hg hL hs hpc mid rr hrr f hmid hstr hat hd
43
  exact ⟨x', h1, h2, by rw [h3, hsize]; omega⟩
44
 
45
  theorem sim_uf2_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
46
- {L : Layout} {base : Nat} {off : Nat → Nat} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
47
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (rest : List (Instr Nat))
48
- (hlow : lowerInstr L base off i = uf L 2 base ++ rest)
49
- (hat : RAt code base (lowerInstr L base off i)) (hk : s.dstack.length < 2) :
50
- RExec code x (.trapped .stackUnderflow) := by
51
  rw [hlow] at hat
52
- exact sim_uf_trap hg hs hL (by decide) (by decide) hk hpc hat
53
 
54
  /-! ### Middle computations -/
55
 
@@ -155,87 +155,87 @@ theorem midspec_rotr : MidSpec [.ror r0 r1] r0 Word.rotr := by
155
 
156
  section Ops
157
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
158
- {base : Nat} {off : Nat → Nat}
159
 
160
  theorem sim_add_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
161
- (hat : RAt code base (lowerInstr L base off .add)) {b a : W} {d : List W}
162
  (hd : s.dstack = b :: a :: d) :
163
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a + b) :: d } x' ∧
164
- x'.pc = base + isize (.add : WordDialect.Instr 32) :=
165
  sim_bin_instr hg hL hs hpc .add [.add r0 r1] r0 (by simp) (· + ·) midspec_add
166
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
167
 
168
  theorem sim_sub_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
169
- (hat : RAt code base (lowerInstr L base off .sub)) {b a : W} {d : List W}
170
  (hd : s.dstack = b :: a :: d) :
171
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a - b) :: d } x' ∧
172
- x'.pc = base + isize (.sub : WordDialect.Instr 32) :=
173
  sim_bin_instr hg hL hs hpc .sub [.sub r0 r1] r0 (by simp) (· - ·) midspec_sub
174
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
175
 
176
  theorem sim_mul_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
177
- (hat : RAt code base (lowerInstr L base off .mul)) {b a : W} {d : List W}
178
  (hd : s.dstack = b :: a :: d) :
179
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a * b) :: d } x' ∧
180
- x'.pc = base + isize (.mul : WordDialect.Instr 32) :=
181
  sim_bin_instr hg hL hs hpc .mul [.mul r0 r1] r0 (by simp) (· * ·) midspec_mul
182
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
183
 
184
  theorem sim_and_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
185
- (hat : RAt code base (lowerInstr L base off .and)) {b a : W} {d : List W}
186
  (hd : s.dstack = b :: a :: d) :
187
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a &&& b) :: d } x' ∧
188
- x'.pc = base + isize (.and : WordDialect.Instr 32) :=
189
  sim_bin_instr hg hL hs hpc .and [.and r0 r1] r0 (by simp) (· &&& ·) midspec_and
190
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
191
 
192
  theorem sim_or_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
193
- (hat : RAt code base (lowerInstr L base off .or)) {b a : W} {d : List W}
194
  (hd : s.dstack = b :: a :: d) :
195
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ||| b) :: d } x' ∧
196
- x'.pc = base + isize (.or : WordDialect.Instr 32) :=
197
  sim_bin_instr hg hL hs hpc .or [.or r0 r1] r0 (by simp) (· ||| ·) midspec_or
198
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
199
 
200
  theorem sim_xor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
201
- (hat : RAt code base (lowerInstr L base off .xor)) {b a : W} {d : List W}
202
  (hd : s.dstack = b :: a :: d) :
203
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ^^^ b) :: d } x' ∧
204
- x'.pc = base + isize (.xor : WordDialect.Instr 32) :=
205
  sim_bin_instr hg hL hs hpc .xor [.xor r0 r1] r0 (by simp) (· ^^^ ·) midspec_xor
206
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
207
 
208
  theorem sim_shl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
209
- (hat : RAt code base (lowerInstr L base off .shl)) {b a : W} {d : List W}
210
  (hd : s.dstack = b :: a :: d) :
211
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shl a b :: d } x' ∧
212
- x'.pc = base + isize (.shl : WordDialect.Instr 32) :=
213
  sim_bin_instr hg hL hs hpc .shl _ r0 (by simp) Word.shl midspec_shl
214
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
215
 
216
  theorem sim_shr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
217
- (hat : RAt code base (lowerInstr L base off .shr)) {b a : W} {d : List W}
218
  (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shr a b :: d } x' ∧
220
- x'.pc = base + isize (.shr : WordDialect.Instr 32) :=
221
  sim_bin_instr hg hL hs hpc .shr _ r0 (by simp) Word.shr midspec_shr
222
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
223
 
224
  theorem sim_rotl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
225
- (hat : RAt code base (lowerInstr L base off .rotl)) {b a : W} {d : List W}
226
  (hd : s.dstack = b :: a :: d) :
227
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotl a b :: d } x' ∧
228
- x'.pc = base + isize (.rotl : WordDialect.Instr 32) :=
229
  sim_bin_instr hg hL hs hpc .rotl _ r0 (by simp) Word.rotl midspec_rotl
230
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
231
 
232
  theorem sim_rotr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
233
- (hat : RAt code base (lowerInstr L base off .rotr)) {b a : W} {d : List W}
234
  (hd : s.dstack = b :: a :: d) :
235
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotr a b :: d } x' ∧
236
- x'.pc = base + isize (.rotr : WordDialect.Instr 32) :=
237
  sim_bin_instr hg hL hs hpc .rotr _ r0 (by simp) Word.rotr midspec_rotr
238
- (by simp [Instr.straightR]) rfl (by simp [isize, ufSize]) hat hd
239
 
240
  end Ops
241
 
 
16
 
17
  /-- Operand-count trap: any lowering that starts with `uf n` exits with `stackUnderflow`. -/
18
  theorem sim_uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
19
+ {L : Layout} {base n : Nat} {g : Facts} {rest : List (Instr Nat)} (hg : Geom c) (hs : Rel0 c p s x)
20
+ (hL : L.dEnd = ofN c.dEnd) (hn : 0 < n) (hn3 : n ≤ 3) (hgd : g.lo ≤ s.dstack.length)
21
+ (hk : s.dstack.length < n) (hpc : x.pc = base) (hat : RAt code base (uf L (need g n) base ++ rest)) :
22
  RExec code x (.trapped .stackUnderflow) :=
23
+ uf_trap hg hs hL hn hn3 hgd hk hpc (rat_append.mp hat).1
24
 
25
  macro "mid_tac" : tactic =>
26
  `(tactic| (intro m a b ha hb
27
  simp [rseq, exec, M.arith, M.mov, M.setReg, M.adv, ha, hb, MidSpec]))
28
 
29
  theorem sim_bin_instr {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
30
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
31
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (mid : List (Instr Nat))
32
  (rr : Reg) (hrr : rr = r0 ∨ rr = r1 ∨ rr = r2 ∨ rr = r3) (f : W → W → W)
33
  (hmid : MidSpec mid rr f) (hstr : ∀ j ∈ mid, j.straightR = true)
34
+ (hlow : lowerInstr L base off g i = uf L (need g 2) base ++
35
  ([.load r1 r4 0, .load r0 r4 4] ++ mid ++ [.store r4 4 rr, .addImm r4 4]))
36
+ (hsize : isize g i = ufSize (need g 2) + (4 + mid.length))
37
+ (hat : RAt code base (lowerInstr L base off g i)) {b a : W} {d : List W}
38
  (hd : s.dstack = b :: a :: d) :
39
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := f a b :: d } x' ∧
40
+ x'.pc = base + isize g i := by
41
  rw [hlow] at hat
42
  obtain ⟨x', h1, h2, h3⟩ := sim_bin_ok hg hL hs hpc mid rr hrr f hmid hstr hat hd
43
  exact ⟨x', h1, h2, by rw [h3, hsize]; omega⟩
44
 
45
  theorem sim_uf2_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
46
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts} (hg : Geom c) (hL : L.dEnd = ofN c.dEnd)
47
  (hs : Rel0 c p s x) (hpc : x.pc = base) (i : WordDialect.Instr 32) (rest : List (Instr Nat))
48
+ (hlow : lowerInstr L base off g i = uf L (need g 2) base ++ rest)
49
+ (hat : RAt code base (lowerInstr L base off g i)) (hgd : g.lo ≤ s.dstack.length)
50
+ (hk : s.dstack.length < 2) : RExec code x (.trapped .stackUnderflow) := by
51
  rw [hlow] at hat
52
+ exact sim_uf_trap hg hs hL (by decide) (by decide) hgd hk hpc hat
53
 
54
  /-! ### Middle computations -/
55
 
 
155
 
156
  section Ops
157
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
158
+ {base : Nat} {off : Nat → Nat} {g : Facts}
159
 
160
  theorem sim_add_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
161
+ (hat : RAt code base (lowerInstr L base off g .add)) {b a : W} {d : List W}
162
  (hd : s.dstack = b :: a :: d) :
163
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a + b) :: d } x' ∧
164
+ x'.pc = base + isize g (.add : WordDialect.Instr 32) :=
165
  sim_bin_instr hg hL hs hpc .add [.add r0 r1] r0 (by simp) (· + ·) midspec_add
166
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
167
 
168
  theorem sim_sub_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
169
+ (hat : RAt code base (lowerInstr L base off g .sub)) {b a : W} {d : List W}
170
  (hd : s.dstack = b :: a :: d) :
171
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a - b) :: d } x' ∧
172
+ x'.pc = base + isize g (.sub : WordDialect.Instr 32) :=
173
  sim_bin_instr hg hL hs hpc .sub [.sub r0 r1] r0 (by simp) (· - ·) midspec_sub
174
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
175
 
176
  theorem sim_mul_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
177
+ (hat : RAt code base (lowerInstr L base off g .mul)) {b a : W} {d : List W}
178
  (hd : s.dstack = b :: a :: d) :
179
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a * b) :: d } x' ∧
180
+ x'.pc = base + isize g (.mul : WordDialect.Instr 32) :=
181
  sim_bin_instr hg hL hs hpc .mul [.mul r0 r1] r0 (by simp) (· * ·) midspec_mul
182
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
183
 
184
  theorem sim_and_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
185
+ (hat : RAt code base (lowerInstr L base off g .and)) {b a : W} {d : List W}
186
  (hd : s.dstack = b :: a :: d) :
187
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a &&& b) :: d } x' ∧
188
+ x'.pc = base + isize g (.and : WordDialect.Instr 32) :=
189
  sim_bin_instr hg hL hs hpc .and [.and r0 r1] r0 (by simp) (· &&& ·) midspec_and
190
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
191
 
192
  theorem sim_or_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
193
+ (hat : RAt code base (lowerInstr L base off g .or)) {b a : W} {d : List W}
194
  (hd : s.dstack = b :: a :: d) :
195
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ||| b) :: d } x' ∧
196
+ x'.pc = base + isize g (.or : WordDialect.Instr 32) :=
197
  sim_bin_instr hg hL hs hpc .or [.or r0 r1] r0 (by simp) (· ||| ·) midspec_or
198
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
199
 
200
  theorem sim_xor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
201
+ (hat : RAt code base (lowerInstr L base off g .xor)) {b a : W} {d : List W}
202
  (hd : s.dstack = b :: a :: d) :
203
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (a ^^^ b) :: d } x' ∧
204
+ x'.pc = base + isize g (.xor : WordDialect.Instr 32) :=
205
  sim_bin_instr hg hL hs hpc .xor [.xor r0 r1] r0 (by simp) (· ^^^ ·) midspec_xor
206
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
207
 
208
  theorem sim_shl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
209
+ (hat : RAt code base (lowerInstr L base off g .shl)) {b a : W} {d : List W}
210
  (hd : s.dstack = b :: a :: d) :
211
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shl a b :: d } x' ∧
212
+ x'.pc = base + isize g (.shl : WordDialect.Instr 32) :=
213
  sim_bin_instr hg hL hs hpc .shl _ r0 (by simp) Word.shl midspec_shl
214
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
215
 
216
  theorem sim_shr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
217
+ (hat : RAt code base (lowerInstr L base off g .shr)) {b a : W} {d : List W}
218
  (hd : s.dstack = b :: a :: d) :
219
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.shr a b :: d } x' ∧
220
+ x'.pc = base + isize g (.shr : WordDialect.Instr 32) :=
221
  sim_bin_instr hg hL hs hpc .shr _ r0 (by simp) Word.shr midspec_shr
222
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
223
 
224
  theorem sim_rotl_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
225
+ (hat : RAt code base (lowerInstr L base off g .rotl)) {b a : W} {d : List W}
226
  (hd : s.dstack = b :: a :: d) :
227
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotl a b :: d } x' ∧
228
+ x'.pc = base + isize g (.rotl : WordDialect.Instr 32) :=
229
  sim_bin_instr hg hL hs hpc .rotl _ r0 (by simp) Word.rotl midspec_rotl
230
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
231
 
232
  theorem sim_rotr_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
233
+ (hat : RAt code base (lowerInstr L base off g .rotr)) {b a : W} {d : List W}
234
  (hd : s.dstack = b :: a :: d) :
235
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := Word.rotr a b :: d } x' ∧
236
+ x'.pc = base + isize g (.rotr : WordDialect.Instr 32) :=
237
  sim_bin_instr hg hL hs hpc .rotr _ r0 (by simp) Word.rotr midspec_rotr
238
+ (by simp [Instr.straightR]) rfl (by simp [isize]) hat hd
239
 
240
  end Ops
241
 
backend/cortexm0/CM0/SimStack.lean CHANGED
@@ -64,51 +64,53 @@ theorem not_step (hs : Rel0 c p s x) (hf : code[x.pc]? = some (.not r0)) :
64
 
65
  end Steps
66
 
67
- /-- Placement of `ovfD L base ++ [i0, i1, i2]`. -/
68
- theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {base : Nat} {i0 i1 i2 : Instr Nat}
69
- (hat : RAt code base (ovfD L base ++ [i0, i1, i2])) :
70
- RAt code base (ovfD L base) ∧ code[base + 3]? = some i0 ∧ code[base + 3 + 1]? = some i1 ∧
71
- code[base + 3 + 1 + 1]? = some i2 := by
72
  obtain ⟨hato, hatr⟩ := rat_append.mp hat
73
- have hl : (ovfD L base).length = 3 := rfl
74
- rw [hl] at hatr
75
  obtain ⟨f0, f1, f2, _⟩ := hatr
76
  exact ⟨hato, f0, f1, f2⟩
77
 
78
- /-- Placement of `uf L n base ++ ovfD L (base + ufSize n) ++ [i0, i1, i2]`. -/
79
- theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {base n : Nat} (hn : 0 < n)
80
  {i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
81
- (hat : RAt code base (uf L n base ++ ovfD L (base + ufSize n) ++ rest)) :
82
- RAt code base (uf L n base) ∧ RAt code (base + 3) (ovfD L (base + 3)) ∧
83
- code[base + 6]? = some i0 ∧ code[base + 6 + 1]? = some i1 ∧ code[base + 6 + 1 + 1]? = some i2 := by
 
 
84
  subst hrest
85
- rw [ufSize_pos hn] at hat
86
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
87
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
88
- have hufl : (uf L n base).length = 3 := by rw [uf_eq L hn]; rfl
89
  rw [hufl] at hato
90
- have hl : (uf L n base ++ ovfD L (base + 3)).length = 6 := by simp [hufl, ovfD]
 
91
  rw [hl] at hatr
92
  obtain ⟨f0, f1, f2, _⟩ := hatr
93
- exact ⟨hatuf, hato, f0, f1, f2⟩
 
94
 
95
  section Ops
96
 
97
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
98
- {L : Layout} {base : Nat} {off : Nat → Nat}
99
 
100
  theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
101
- (hat : RAt code base (lowerInstr L base off .not)) {a : W} {d : List W}
102
  (hd : s.dstack = a :: d) :
103
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (~~~a) :: d } x' ∧
104
- x'.pc = base + isize (.not : WordDialect.Instr 32) := by
105
- have hat' : RAt code base (uf L 1 base ++ [.load r0 Reg.r4 0, .not r0, .store Reg.r4 0 r0]) := hat
106
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
107
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
108
  rw [hufl] at hatr
109
  obtain ⟨f0, f1, f2, _⟩ := hatr
110
  have hk : 1 ≤ s.dstack.length := by simp [hd]
111
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
112
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
113
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
114
  obtain ⟨x3, hs3, hr3, hpc3, hv3⟩ := not_step (code := code) hr2 (fetch_cast f1 (by omega))
@@ -116,57 +118,57 @@ theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
116
  (rs := r0) (disp := 0) (by simp) (fetch_cast f2 (by omega))
117
  have e : s.dstack.set 0 (x3.regs r0) = (~~~a) :: d := by simp [hd, hv3, hv2]
118
  rw [e] at hr4
119
- exact ⟨x4, ((hs1.trans hs2).trans hs3).trans hs4, hr4, by simp [isize, ufSize]; omega⟩
120
 
121
  theorem sim_dup_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
122
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .dup)) {a : W}
123
  {d : List W} (hd : s.dstack = a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
124
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: a :: d } x' ∧
125
- x'.pc = base + isize (.dup : WordDialect.Instr 32) := by
126
- obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := 1) (by decide) rfl hat
127
  have hk : 1 ≤ s.dstack.length := by simp [hd]
128
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
129
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
130
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
131
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
132
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
133
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
134
  rw [hv2, hd] at hr3
135
- exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize, ufSize]; omega⟩
136
 
137
- theorem sim_dup_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
138
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .dup)) {a : W}
139
  {d : List W} (hd : s.dstack = a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
140
  RExec code x .overflow := by
141
- obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := 1) (by decide) rfl hat
142
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) (by simp [hd]) hpc hatuf
143
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
144
 
145
  theorem sim_drop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
146
- (hat : RAt code base (lowerInstr L base off .drop)) {a : W} {d : List W}
147
  (hd : s.dstack = a :: d) :
148
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
149
- x'.pc = base + isize (.drop : WordDialect.Instr 32) := by
150
- have hat' : RAt code base (uf L 1 base ++ [.addImm Reg.r4 4]) := hat
151
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
152
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
153
  rw [hufl] at hatr
154
  obtain ⟨f0, _⟩ := hatr
155
  have hk : 1 ≤ s.dstack.length := by simp [hd]
156
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
157
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := adj_step (code := code) hg hr1 (n := 1) (by simp [hd])
158
  (δ := 4) (by simp) (fetch_cast f0 (by omega))
159
  have e : (s.dstack).drop 1 = d := by simp [hd]
160
  rw [e] at hr2
161
- exact ⟨x2, hs1.trans hs2, hr2, by simp [isize, ufSize]; omega⟩
162
 
163
  theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
164
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.word w)))
165
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
166
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := w :: s.dstack } x' ∧
167
- x'.pc = base + isize (.word w : WordDialect.Instr 32) := by
168
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
169
- obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfD_pass hg hs hLd hfit hpc hato
170
  obtain ⟨x1, hs1, hr1, hpc1, hv1, _⟩ := movimm_step (code := code) hr0 (rd := r0) (by simp)
171
  (v := w) (by rw [hpc0]; exact f0)
172
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
@@ -174,37 +176,37 @@ theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W
174
  rw [hv1] at hr2
175
  exact ⟨x2, (hs0.trans hs1).trans hs2, hr2, by simp [isize]; omega⟩
176
 
177
- theorem sim_word_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
178
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.word w)))
179
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
180
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
181
- exact ovfD_trap hg hs hLd h hpc hato
182
 
183
  theorem sim_ptr_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
184
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.ptr q)))
185
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
186
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := q.toWord :: s.dstack } x' ∧
187
- x'.pc = base + isize (.ptr q : WordDialect.Instr 32) :=
188
- sim_word_ok (L := L) (off := off) hg hs hpc q.toWord hLd hat hfit
189
 
190
- theorem sim_ptr_ovf (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
191
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off (.ptr q)))
192
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow :=
193
- sim_word_ovf (L := L) (off := off) hg hs hpc q.toWord hLd hat h
194
 
195
  theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
196
- (hat : RAt code base (lowerInstr L base off .swap)) {b a : W} {d : List W}
197
  (hd : s.dstack = b :: a :: d) :
198
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: d } x' ∧
199
- x'.pc = base + isize (.swap : WordDialect.Instr 32) := by
200
- have hat' : RAt code base (uf L 2 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
201
  .store Reg.r4 0 r1, .store Reg.r4 4 r0]) := hat
202
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
203
- have hufl : (uf L 2 base).length = 3 := by simp [uf]
204
  rw [hufl] at hatr
205
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
206
  have hk : 2 ≤ s.dstack.length := by simp [hd]
207
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
208
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
209
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
210
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
@@ -220,45 +222,45 @@ theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
220
  have e : (s.dstack.set 0 (x3.regs r1)).set 1 (x4.regs r0) = a :: b :: d := by
221
  simp [hd, hv3, hreg4, hax3]
222
  rw [e] at hr5'
223
- exact ⟨x5, (((hs1.trans hs2).trans hs3).trans hs4).trans hs5, hr5', by simp [isize, ufSize]; omega⟩
224
 
225
  theorem sim_over_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
226
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .over)) {b a : W}
227
  {d : List W} (hd : s.dstack = b :: a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
228
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: a :: d } x' ∧
229
- x'.pc = base + isize (.over : WordDialect.Instr 32) := by
230
- obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := 2) (by decide) rfl hat
231
  have hk : 2 ≤ s.dstack.length := by simp [hd]
232
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
233
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
234
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 1) (v := a)
235
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f0 (by omega))
236
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
237
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
238
  rw [hv2, hd] at hr3
239
- exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize, ufSize]; omega⟩
240
 
241
- theorem sim_over_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
242
- (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off .over)) {b a : W}
243
  {d : List W} (hd : s.dstack = b :: a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
244
  RExec code x .overflow := by
245
- obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := 2) (by decide) rfl hat
246
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) (by simp [hd]) hpc hatuf
247
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
248
 
249
  theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
250
- (hat : RAt code base (lowerInstr L base off .rot)) {cc b a : W} {d : List W}
251
  (hd : s.dstack = cc :: b :: a :: d) :
252
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: cc :: b :: d } x' ∧
253
- x'.pc = base + isize (.rot : WordDialect.Instr 32) := by
254
- have hat' : RAt code base (uf L 3 base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
255
  .load r2 Reg.r4 8, .store Reg.r4 0 r2, .store Reg.r4 4 r0, .store Reg.r4 8 r1]) := hat
256
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
257
- have hufl : (uf L 3 base).length = 3 := by simp [uf]
258
  rw [hufl] at hatr
259
  obtain ⟨f0, f1, f2, f3, f4, f5, _⟩ := hatr
260
  have hk : 3 ≤ s.dstack.length := by simp [hd]
261
- obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
262
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
263
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
264
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := b)
@@ -284,7 +286,7 @@ theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x)
284
  simp [hd, hv4, hreg5, hreg6, hax4, hcx4]
285
  rw [e] at hr7'
286
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans hs6).trans hs7, hr7',
287
- by simp [isize, ufSize]; omega⟩
288
 
289
  end Ops
290
 
 
64
 
65
  end Steps
66
 
67
+ /-- Placement of `ovf L g base ++ [i0, i1, i2]`. -/
68
+ theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {g : Facts} {base : Nat}
69
+ {i0 i1 i2 : Instr Nat} (hat : RAt code base (ovf L g base ++ [i0, i1, i2])) :
70
+ RAt code base (ovf L g base) ∧ code[base + ovfSize g]? = some i0 ∧
71
+ code[base + ovfSize g + 1]? = some i1 ∧ code[base + ovfSize g + 1 + 1]? = some i2 := by
72
  obtain ⟨hato, hatr⟩ := rat_append.mp hat
73
+ rw [ovf_length] at hatr
 
74
  obtain ⟨f0, f1, f2, _⟩ := hatr
75
  exact ⟨hato, f0, f1, f2⟩
76
 
77
+ /-- Placement of `uf L n base ++ ovf L g (base + ufSize n) ++ [i0, i1, i2]`. -/
78
+ theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {g : Facts} {base n : Nat}
79
  {i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
80
+ (hat : RAt code base (uf L n base ++ ovf L g (base + ufSize n) ++ rest)) :
81
+ RAt code base (uf L n base) ∧ RAt code (base + ufSize n) (ovf L g (base + ufSize n)) ∧
82
+ code[base + ufSize n + ovfSize g]? = some i0 ∧
83
+ code[base + ufSize n + ovfSize g + 1]? = some i1 ∧
84
+ code[base + ufSize n + ovfSize g + 1 + 1]? = some i2 := by
85
  subst hrest
 
86
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
87
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
88
+ have hufl := uf_length L n base
89
  rw [hufl] at hato
90
+ have hl : (uf L n base ++ ovf L g (base + ufSize n)).length = ufSize n + ovfSize g := by
91
+ simp [hufl, ovf_length]
92
  rw [hl] at hatr
93
  obtain ⟨f0, f1, f2, _⟩ := hatr
94
+ exact ⟨hatuf, hato, by simpa [Nat.add_assoc] using f0, by simpa [Nat.add_assoc] using f1,
95
+ by simpa [Nat.add_assoc] using f2⟩
96
 
97
  section Ops
98
 
99
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
100
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
101
 
102
  theorem sim_not_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
103
+ (hat : RAt code base (lowerInstr L base off g .not)) {a : W} {d : List W}
104
  (hd : s.dstack = a :: d) :
105
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := (~~~a) :: d } x' ∧
106
+ x'.pc = base + isize g (.not : WordDialect.Instr 32) := by
107
+ have hat' : RAt code base (uf L (need g 1) base ++ [.load r0 Reg.r4 0, .not r0, .store Reg.r4 0 r0]) := hat
108
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
109
+ have hufl := uf_length L (need g 1) base
110
  rw [hufl] at hatr
111
  obtain ⟨f0, f1, f2, _⟩ := hatr
112
  have hk : 1 ≤ s.dstack.length := by simp [hd]
113
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
114
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := a)
115
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
116
  obtain ⟨x3, hs3, hr3, hpc3, hv3⟩ := not_step (code := code) hr2 (fetch_cast f1 (by omega))
 
118
  (rs := r0) (disp := 0) (by simp) (fetch_cast f2 (by omega))
119
  have e : s.dstack.set 0 (x3.regs r0) = (~~~a) :: d := by simp [hd, hv3, hv2]
120
  rw [e] at hr4
121
+ exact ⟨x4, ((hs1.trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
122
 
123
  theorem sim_dup_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
124
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .dup)) {a : W}
125
  {d : List W} (hd : s.dstack = a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
126
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: a :: d } x' ∧
127
+ x'.pc = base + isize g (.dup : WordDialect.Instr 32) := by
128
+ obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := need g 1) rfl hat
129
  have hk : 1 ≤ s.dstack.length := by simp [hd]
130
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
131
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
132
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
133
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
134
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
135
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
136
  rw [hv2, hd] at hr3
137
+ exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
138
 
139
+ theorem sim_dup_ovf (hn : g.noOvf = false) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
140
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .dup)) {a : W}
141
  {d : List W} (hd : s.dstack = a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
142
  RExec code x .overflow := by
143
+ obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := need g 1) rfl hat
144
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by simp [hd]) hpc hatuf
145
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
146
 
147
  theorem sim_drop_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
148
+ (hat : RAt code base (lowerInstr L base off g .drop)) {a : W} {d : List W}
149
  (hd : s.dstack = a :: d) :
150
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d } x' ∧
151
+ x'.pc = base + isize g (.drop : WordDialect.Instr 32) := by
152
+ have hat' : RAt code base (uf L (need g 1) base ++ [.addImm Reg.r4 4]) := hat
153
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
154
+ have hufl := uf_length L (need g 1) base
155
  rw [hufl] at hatr
156
  obtain ⟨f0, _⟩ := hatr
157
  have hk : 1 ≤ s.dstack.length := by simp [hd]
158
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
159
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := adj_step (code := code) hg hr1 (n := 1) (by simp [hd])
160
  (δ := 4) (by simp) (fetch_cast f0 (by omega))
161
  have e : (s.dstack).drop 1 = d := by simp [hd]
162
  rw [e] at hr2
163
+ exact ⟨x2, hs1.trans hs2, hr2, by simp [isize]; omega⟩
164
 
165
  theorem sim_word_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
166
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.word w)))
167
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
168
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := w :: s.dstack } x' ∧
169
+ x'.pc = base + isize g (.word w : WordDialect.Instr 32) := by
170
  obtain ⟨hato, f0, f1, f2⟩ := xat_ovf3 (L := L) (by exact hat)
171
+ obtain ⟨x0, hs0, hr0, hpc0, _, _⟩ := ovfG_pass hg hs hLd hfit hpc hato
172
  obtain ⟨x1, hs1, hr1, hpc1, hv1, _⟩ := movimm_step (code := code) hr0 (rd := r0) (by simp)
173
  (v := w) (by rw [hpc0]; exact f0)
174
  obtain ⟨x2, hs2, hr2, hpc2, _⟩ := push_pair hg hr1 r0 (by decide) hfit
 
176
  rw [hv1] at hr2
177
  exact ⟨x2, (hs0.trans hs1).trans hs2, hr2, by simp [isize]; omega⟩
178
 
179
+ theorem sim_word_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (w : W)
180
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.word w)))
181
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow := by
182
  obtain ⟨hato, _⟩ := xat_ovf3 (L := L) (by exact hat)
183
+ exact ovfG_trap hn hg hs hLd h hpc hato
184
 
185
  theorem sim_ptr_ok (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
186
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.ptr q)))
187
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
188
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := q.toWord :: s.dstack } x' ∧
189
+ x'.pc = base + isize g (.ptr q : WordDialect.Instr 32) :=
190
+ sim_word_ok (L := L) (off := off) (g := g) hg hs hpc q.toWord hLd hat hfit
191
 
192
+ theorem sim_ptr_ovf (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x) (hpc : x.pc = base) (q : WordDialect.Ptr 32)
193
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g (.ptr q)))
194
  (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) : RExec code x .overflow :=
195
+ sim_word_ovf (L := L) (off := off) (g := g) hn hg hs hpc q.toWord hLd hat h
196
 
197
  theorem sim_swap_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
198
+ (hat : RAt code base (lowerInstr L base off g .swap)) {b a : W} {d : List W}
199
  (hd : s.dstack = b :: a :: d) :
200
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: d } x' ∧
201
+ x'.pc = base + isize g (.swap : WordDialect.Instr 32) := by
202
+ have hat' : RAt code base (uf L (need g 2) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
203
  .store Reg.r4 0 r1, .store Reg.r4 4 r0]) := hat
204
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
205
+ have hufl := uf_length L (need g 2) base
206
  rw [hufl] at hatr
207
  obtain ⟨f0, f1, f2, f3, _⟩ := hatr
208
  have hk : 2 ≤ s.dstack.length := by simp [hd]
209
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
210
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := b)
211
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
212
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := a)
 
222
  have e : (s.dstack.set 0 (x3.regs r1)).set 1 (x4.regs r0) = a :: b :: d := by
223
  simp [hd, hv3, hreg4, hax3]
224
  rw [e] at hr5'
225
+ exact ⟨x5, (((hs1.trans hs2).trans hs3).trans hs4).trans hs5, hr5', by simp [isize]; omega⟩
226
 
227
  theorem sim_over_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
228
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .over)) {b a : W}
229
  {d : List W} (hd : s.dstack = b :: a :: d) (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
230
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: b :: a :: d } x' ∧
231
+ x'.pc = base + isize g (.over : WordDialect.Instr 32) := by
232
+ obtain ⟨hatuf, hato, f0, f1, f2⟩ := xat_uf_ovf (L := L) (n := need g 2) rfl hat
233
  have hk : 2 ≤ s.dstack.length := by simp [hd]
234
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
235
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
236
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 1) (v := a)
237
  (by simp [hd]) (rd := r0) (by simp) (disp := 4) (by simp) (fetch_cast f0 (by omega))
238
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 r0 (by decide) hfit
239
  ⟨fetch_cast f1 (by omega), fetch_cast f2 (by omega), trivial⟩
240
  rw [hv2, hd] at hr3
241
+ exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
242
 
243
+ theorem sim_over_ovf (hn : g.noOvf = false) (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
244
+ (hLd : L.dLim = ofN (c.dBase + 4)) (hat : RAt code base (lowerInstr L base off g .over)) {b a : W}
245
  {d : List W} (hd : s.dstack = b :: a :: d) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
246
  RExec code x .overflow := by
247
+ obtain ⟨hatuf, hato, _⟩ := xat_uf_ovf (L := L) (n := need g 2) rfl hat
248
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by simp [hd]) hpc hatuf
249
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
250
 
251
  theorem sim_rot_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hs : Rel0 c p s x) (hpc : x.pc = base)
252
+ (hat : RAt code base (lowerInstr L base off g .rot)) {cc b a : W} {d : List W}
253
  (hd : s.dstack = cc :: b :: a :: d) :
254
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: cc :: b :: d } x' ∧
255
+ x'.pc = base + isize g (.rot : WordDialect.Instr 32) := by
256
+ have hat' : RAt code base (uf L (need g 3) base ++ [.load r0 Reg.r4 0, .load r1 Reg.r4 4,
257
  .load r2 Reg.r4 8, .store Reg.r4 0 r2, .store Reg.r4 4 r0, .store Reg.r4 8 r1]) := hat
258
  obtain ⟨hatuf, hatr⟩ := rat_append.mp hat'
259
+ have hufl := uf_length L (need g 3) base
260
  rw [hufl] at hatr
261
  obtain ⟨f0, f1, f2, f3, f4, f5, _⟩ := hatr
262
  have hk : 3 ≤ s.dstack.length := by simp [hd]
263
+ obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
264
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1 (j := 0) (v := cc)
265
  (by simp [hd]) (rd := r0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
266
  obtain ⟨x3, hs3, hr3, hpc3, hv3, ho3, _⟩ := ld_step (code := code) hr2 (j := 1) (v := b)
 
286
  simp [hd, hv4, hreg5, hreg6, hax4, hcx4]
287
  rw [e] at hr7'
288
  exact ⟨x7, (((((hs1.trans hs2).trans hs3).trans hs4).trans hs5).trans hs6).trans hs7, hr7',
289
+ by simp [isize]; omega⟩
290
 
291
  end Ops
292
 
backend/cortexm0/CM0/SimStep.lean CHANGED
@@ -53,10 +53,13 @@ theorem shape3 {l : List W} (h : 3 ≤ l.length) : ∃ cc y v d, l = cc :: y ::
53
  | nil => simp at h
54
  | cons v d => exact ⟨cc, y, v, d, rfl⟩
55
 
56
- theorem lowerInstr_uf (L : Layout) (base : Nat) (off : Nat → Nat) (i : WordDialect.Instr 32)
57
  (h : 0 < i.pops) :
58
- ∃ rest, lowerInstr L base off i = uf L i.pops base ++ rest ∧ i.pops ≤ 3 := by
59
- cases i <;> first | exact ⟨_, rfl, by simp [Instr.pops]⟩ | exact absurd h (by simp [Instr.pops])
 
 
 
60
 
61
  theorem Rel0.setPc {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (h : Rel0 c p s x) (n : Nat) :
62
  Rel0 c p { s with pc := n } x :=
@@ -78,14 +81,15 @@ theorem sim_trapped {code : List (Instr Nat)} {t : Trap} (h : RExec code x (.tra
78
  Sim c p code x (.trapped t) := h
79
 
80
  theorem rel_fall {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i) {s' : State 32}
81
- {x' : M} (h0 : Rel0 c p s' x') (hpc : x'.pc = offs p s.pc + isize i) :
82
  Rel c p { s' with pc := s.pc + 1 } x' :=
83
- ⟨h0.setPc _, by rw [hpc, offs_succ hi]⟩
84
 
85
  theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
86
  (hLd : L.dLim = ofN (c.dBase + 4)) (hLr : L.rGap = ofN (4 * c.rcap - 8))
87
  (hLa : L.aEnd = ofN c.aEnd) (hLal : L.aLim = ofN (c.aBase + 4))
88
- (hsz : ∀ k, offs p k < 2 ^ 32) (hs : Rel c p s x)
 
89
  {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i)
90
  (hreg : ∀ r, (i = .push r ∨ i = .pop r) → r < c.nregs) :
91
  Sim c p (lowerProg L p) x (WordDialect.exec i s) ∨
@@ -93,27 +97,39 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
93
  have nfD : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → ¬ Fits c s := fun h hf => h hf.1
94
  have nfR : ¬ s.rstack.length + 2 ≤ c.rcap → ¬ Fits c s := fun h hf => h hf.2.1
95
  have nfA : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd → ¬ Fits c s := fun h hf => h hf.2.2
96
- have hpc : x.pc = offs p s.pc := hs.2
97
  have hs0 : Rel0 c p s x := hs.1
98
  have hat := lowerProg_at L p s.pc i hi
 
 
 
 
 
 
 
 
 
 
 
99
  by_cases hk : s.dstack.length < i.pops
100
  · rw [exec_underflow i s hk]
101
- obtain ⟨rest, hlow, h3⟩ := lowerInstr_uf L (offs p s.pc) (offs p) i (by omega)
 
102
  rw [hlow] at hat
103
- exact .inl <| sim_trapped (sim_uf_trap hg hs0 hL (by omega) h3 hk hpc hat)
104
  · have hk' : i.pops ≤ s.dstack.length := by omega
105
  cases i with
106
  | word w =>
107
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
108
  rotate_left
109
- · exact .inr ⟨nfD hf, sim_word_ovf hg hs0 hpc w hLd hat hf⟩
110
  obtain ⟨x', hst, h0, hpc'⟩ := sim_word_ok hg hs0 hpc w hLd hat hf
111
  rw [exec_word]
112
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
113
  | ptr q =>
114
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
115
  rotate_left
116
- · exact .inr ⟨nfD hf, sim_ptr_ovf hg hs0 hpc q hLd hat hf⟩
117
  obtain ⟨x', hst, h0, hpc'⟩ := sim_ptr_ok hg hs0 hpc q hLd hat hf
118
  rw [exec_ptr]
119
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -238,8 +254,9 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
238
  simp only [hc', Bool.false_eq_true, if_false] at hpc'
239
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
240
  | call t =>
241
- have hret : offs p s.pc + isize (.call t : WordDialect.Instr 32) = offs p (s.pc + 1) := by
242
- rw [offs_succ hi]
 
243
  by_cases hf : s.rstack.length + 2 ≤ c.rcap
244
  rotate_left
245
  · exact .inr ⟨nfR hf, sim_call_ovf hg hs0 hpc hLr hat hf⟩
@@ -259,7 +276,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
259
  | push r =>
260
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
261
  rotate_left
262
- · exact .inr ⟨nfD hf, sim_push_ovf hg hs0 hpc hLd hat hf⟩
263
  obtain ⟨x', hst, h0, hpc'⟩ := sim_push_ok hg hs0 hpc (hreg r (Or.inl rfl)) hLd hat hf
264
  rw [exec_push]
265
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -272,7 +289,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
272
  obtain ⟨a, d, hd⟩ := shape1 (by simpa [Instr.pops] using hk')
273
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
274
  rotate_left
275
- · exact .inr ⟨nfD hf, sim_dup_ovf hg hL hs0 hpc hLd hat hd hf⟩
276
  obtain ⟨x', hst, h0, hpc'⟩ := sim_dup_ok hg hL hs0 hpc hLd hat hd hf
277
  rw [exec_dup hd]
278
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -290,7 +307,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
290
  obtain ⟨b, a, d, hd⟩ := shape2 (by simpa [Instr.pops] using hk')
291
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
292
  rotate_left
293
- · exact .inr ⟨nfD hf, sim_over_ovf hg hL hs0 hpc hLd hat hd hf⟩
294
  obtain ⟨x', hst, h0, hpc'⟩ := sim_over_ok hg hL hs0 hpc hLd hat hd hf
295
  rw [exec_over hd]
296
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
@@ -320,7 +337,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
320
  | cons a as =>
321
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
322
  rotate_left
323
- · exact .inr ⟨nfD hf, sim_fromr_ovf hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
324
  obtain ⟨x', hst, h0, hpc'⟩ := sim_fromr_ok hg hLa hLd hs0 hpc hat ha hf
325
  have e : WordDialect.exec WordDialect.Instr.fromr s =
326
  .next { s with pc := s.pc + 1, dstack := a :: s.dstack, astack := as } := by
@@ -337,7 +354,7 @@ theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M
337
  | cons a as =>
338
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
339
  rotate_left
340
- · exact .inr ⟨nfD hf, sim_rfetch_ovf hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
341
  obtain ⟨x', hst, h0, hpc'⟩ := sim_rfetch_ok hg hLa hLd hs0 hpc hat ha hf
342
  have e : WordDialect.exec WordDialect.Instr.rfetch s = s.fall (a :: s.dstack) := by
343
  simp [WordDialect.exec, ha]
 
53
  | nil => simp at h
54
  | cons v d => exact ⟨cc, y, v, d, rfl⟩
55
 
56
+ theorem lowerInstr_uf (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts) (i : WordDialect.Instr 32)
57
  (h : 0 < i.pops) :
58
+ ∃ rest, lowerInstr L base off g i = uf L (need g i.pops) base ++ rest ∧ i.pops ≤ 3 := by
59
+ cases i <;> first
60
+ | exact ⟨_, rfl, by simp [Instr.pops]⟩
61
+ | exact ⟨_, List.append_assoc _ _ _, by simp [Instr.pops]⟩
62
+ | exact absurd h (by simp [Instr.pops])
63
 
64
  theorem Rel0.setPc {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (h : Rel0 c p s x) (n : Nat) :
65
  Rel0 c p { s with pc := n } x :=
 
81
  Sim c p code x (.trapped t) := h
82
 
83
  theorem rel_fall {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i) {s' : State 32}
84
+ {x' : M} (h0 : Rel0 c p s' x') (hpc : x'.pc = offs c.facts p s.pc + isize (c.facts s.pc) i) :
85
  Rel c p { s' with pc := s.pc + 1 } x' :=
86
+ ⟨h0.setPc _, by rw [hpc, offs_succ c.facts hi]⟩
87
 
88
  theorem sim_exec (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M)
89
  (hLd : L.dLim = ofN (c.dBase + 4)) (hLr : L.rGap = ofN (4 * c.rcap - 8))
90
  (hLa : L.aEnd = ofN c.aEnd) (hLal : L.aLim = ofN (c.aBase + 4))
91
+ (hLf : L.facts = c.facts) (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hs : Rel c p s x)
92
+ (hgd : c.cert s.pc ≤ s.dstack.length) (hub : s.dstack.length ≤ c.ub s.pc)
93
  {i : WordDialect.Instr 32} (hi : p[s.pc]? = some i)
94
  (hreg : ∀ r, (i = .push r ∨ i = .pop r) → r < c.nregs) :
95
  Sim c p (lowerProg L p) x (WordDialect.exec i s) ∨
 
97
  have nfD : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → ¬ Fits c s := fun h hf => h hf.1
98
  have nfR : ¬ s.rstack.length + 2 ≤ c.rcap → ¬ Fits c s := fun h hf => h hf.2.1
99
  have nfA : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd → ¬ Fits c s := fun h hf => h hf.2.2
100
+ have hpc : x.pc = offs c.facts p s.pc := hs.2
101
  have hs0 : Rel0 c p s x := hs.1
102
  have hat := lowerProg_at L p s.pc i hi
103
+ rw [hLf] at hat
104
+ -- Where the stack may be full, the overflow guard is there: the bound left it out only where
105
+ -- one more word fits.
106
+ have hnov : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd → (c.facts s.pc).noOvf = false := by
107
+ intro hf
108
+ cases h : (c.facts s.pc).noOvf
109
+ · rfl
110
+ · exfalso; apply hf
111
+ simp only [Cfg.facts, decide_eq_true_eq] at h
112
+ unfold Cfg.dCap at h
113
+ omega
114
  by_cases hk : s.dstack.length < i.pops
115
  · rw [exec_underflow i s hk]
116
+ obtain ⟨rest, hlow, h3⟩ := lowerInstr_uf L (offs c.facts p s.pc) (offs c.facts p) (c.facts s.pc) i
117
+ (by omega)
118
  rw [hlow] at hat
119
+ exact .inl <| sim_trapped (sim_uf_trap hg hs0 hL (by omega) h3 hgd hk hpc hat)
120
  · have hk' : i.pops ≤ s.dstack.length := by omega
121
  cases i with
122
  | word w =>
123
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
124
  rotate_left
125
+ · exact .inr ⟨nfD hf, sim_word_ovf (hnov hf) hg hs0 hpc w hLd hat hf⟩
126
  obtain ⟨x', hst, h0, hpc'⟩ := sim_word_ok hg hs0 hpc w hLd hat hf
127
  rw [exec_word]
128
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
129
  | ptr q =>
130
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
131
  rotate_left
132
+ · exact .inr ⟨nfD hf, sim_ptr_ovf (hnov hf) hg hs0 hpc q hLd hat hf⟩
133
  obtain ⟨x', hst, h0, hpc'⟩ := sim_ptr_ok hg hs0 hpc q hLd hat hf
134
  rw [exec_ptr]
135
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
254
  simp only [hc', Bool.false_eq_true, if_false] at hpc'
255
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
256
  | call t =>
257
+ have hret : offs c.facts p s.pc + isize (c.facts s.pc) (.call t : WordDialect.Instr 32) =
258
+ offs c.facts p (s.pc + 1) := by
259
+ rw [offs_succ c.facts hi]
260
  by_cases hf : s.rstack.length + 2 ≤ c.rcap
261
  rotate_left
262
  · exact .inr ⟨nfR hf, sim_call_ovf hg hs0 hpc hLr hat hf⟩
 
276
  | push r =>
277
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
278
  rotate_left
279
+ · exact .inr ⟨nfD hf, sim_push_ovf (hnov hf) hg hs0 hpc hLd hat hf⟩
280
  obtain ⟨x', hst, h0, hpc'⟩ := sim_push_ok hg hs0 hpc (hreg r (Or.inl rfl)) hLd hat hf
281
  rw [exec_push]
282
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
289
  obtain ⟨a, d, hd⟩ := shape1 (by simpa [Instr.pops] using hk')
290
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
291
  rotate_left
292
+ · exact .inr ⟨nfD hf, sim_dup_ovf (hnov hf) hg hL hs0 hpc hLd hat hd hf⟩
293
  obtain ⟨x', hst, h0, hpc'⟩ := sim_dup_ok hg hL hs0 hpc hLd hat hd hf
294
  rw [exec_dup hd]
295
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
307
  obtain ⟨b, a, d, hd⟩ := shape2 (by simpa [Instr.pops] using hk')
308
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
309
  rotate_left
310
+ · exact .inr ⟨nfD hf, sim_over_ovf (hnov hf) hg hL hs0 hpc hLd hat hd hf⟩
311
  obtain ⟨x', hst, h0, hpc'⟩ := sim_over_ok hg hL hs0 hpc hLd hat hd hf
312
  rw [exec_over hd]
313
  exact .inl <| sim_next ⟨x', hst, rel_fall hi h0 hpc'⟩
 
337
  | cons a as =>
338
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
339
  rotate_left
340
+ · exact .inr ⟨nfD hf, sim_fromr_ovf (hnov hf) hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
341
  obtain ⟨x', hst, h0, hpc'⟩ := sim_fromr_ok hg hLa hLd hs0 hpc hat ha hf
342
  have e : WordDialect.exec WordDialect.Instr.fromr s =
343
  .next { s with pc := s.pc + 1, dstack := a :: s.dstack, astack := as } := by
 
354
  | cons a as =>
355
  by_cases hf : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd
356
  rotate_left
357
+ · exact .inr ⟨nfD hf, sim_rfetch_ovf (hnov hf) hg hLa hLd hs0 hpc hat (by simp [ha]) hf⟩
358
  obtain ⟨x', hst, h0, hpc'⟩ := sim_rfetch_ok hg hLa hLd hs0 hpc hat ha hf
359
  have e : WordDialect.exec WordDialect.Instr.rfetch s = s.fall (a :: s.dstack) := by
360
  simp [WordDialect.exec, ha]
backend/cortexm0/CM0Main.lean CHANGED
@@ -14,7 +14,8 @@ divide instruction. For each program it
14
  3. runs the image on the emulated BBC micro:bit, an nRF51822 (Cortex-M0, 256 KiB of flash,
15
  16 KiB of SRAM; `qemu-system-arm -M microbit`). It takes the initial stack pointer and reset
16
  vector from the vector table, copies `.data` from flash to SRAM, prints through the nRF51
17
- UART and stops through semihosting,
 
18
  4. runs the same IR program under the Lean semantics at width 32 (`WordDialect.run`), and
19
  5. compares the exit status and the dumped data stack, IR memory and virtual registers.
20
 
@@ -23,8 +24,16 @@ shared samples and generated programs narrowed to 32-bit words, 32-bit edge case
23
  `INT_MIN / -1`, which the division loop must wrap), the auxiliary-stack and overflow programs,
24
  and Forth source files compiled at width 32.
25
 
26
- Usage: `cm0c check [fuzzCount]`, `cm0c emit <sample>`, `cm0c forth <file.fs> [memWords]`,
27
- `cm0c emit-forth <file.fs> [memWords]`.
 
 
 
 
 
 
 
 
28
  -/
29
 
30
  open WordDialect
@@ -43,18 +52,53 @@ def rBase : Nat := 0x20002400
43
  def rcap : Nat := 1024
44
  def rEnd : Nat := rBase + 4 * rcap
45
 
46
- def runtimeFor (s : Sample32) : CM0.Emit.Runtime :=
47
- { dEnd := dEnd, capacity := capacity, rEnd := rEnd, rcap := rcap, memImage := s.mem,
48
- nregs := s.nregs, aEnd := aEnd, acap := acap }
49
-
50
- def asmFor (s : Sample32) : String :=
51
- CM0.Emit.program (runtimeFor s) (CM0.lowerProg (runtimeFor s).layout s.prog)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  /-- The vector table and code in flash from address 0 (where a Cortex-M reads its initial stack
54
  pointer and reset vector); `.data` in the first 1 KiB of SRAM, loaded into flash after the code
55
  (`__data_load`); the stacks are uninitialised sections at fixed addresses. -/
56
- def linkerScript : String :=
57
- "ENTRY(_start)\nMEMORY {\n FLASH (rx) : ORIGIN = 0x0, LENGTH = 256K\n" ++
58
  " DATA (rw) : ORIGIN = 0x20000000, LENGTH = 1K\n STACKS (rw) : ORIGIN = 0x20000400, LENGTH = 12K\n}\nSECTIONS {\n" ++
59
  " .vectors : { *(.vectors) } > FLASH\n .text : { *(.text*) } > FLASH\n" ++
60
  " .data : { *(.data*) } > DATA AT > FLASH\n __data_load = LOADADDR(.data);\n" ++
@@ -64,12 +108,12 @@ def linkerScript : String :=
64
 
65
  def workDir : String := "/tmp/cm0c"
66
 
67
- /-- Assemble, link and run one assembly file; the UART output and the exit status. -/
68
- def runAsm (name asm : String) : IO (Except String (String × UInt32)) := do
69
  IO.FS.createDirAll workDir
70
  let base := s!"{workDir}/{name}"
71
  IO.FS.writeFile (base ++ ".s") asm
72
- IO.FS.writeFile (workDir ++ "/link.ld") linkerScript
73
  let asArgs := #["--target=thumbv6m-none-eabi", "-mcpu=cortex-m0", "-c", "-o", base ++ ".o",
74
  base ++ ".s"]
75
  let a ← IO.Process.output { cmd := "clang", args := asArgs }
@@ -77,40 +121,59 @@ def runAsm (name asm : String) : IO (Except String (String × UInt32)) := do
77
  let l ← IO.Process.output
78
  { cmd := "ld.lld", args := #["-T", workDir ++ "/link.ld", "-o", base, base ++ ".o"] }
79
  if l.exitCode != 0 then return .error s!"ld.lld failed: {l.stderr}"
80
- let child ← IO.Process.spawn
81
- { cmd := "qemu-system-arm",
82
- args := #["-machine", "microbit", "-kernel", base, "-display", "none", "-serial", "stdio",
83
- "-monitor", "none", "-semihosting-config", "enable=on,target=native"],
84
- stdout := .piped, stderr := .null, stdin := .null }
85
- let out ← readAll child.stdout ByteArray.empty
86
- let code ← child.wait
87
- match String.fromUTF8? out with
88
- | some t => return .ok (t, code)
89
- | none => return .error "UART output is not text"
90
-
91
- def runNative : Runner32 := fun s => do
92
- match ← runAsm s.name (asmFor s) with
93
  | .error e => return .error e
94
- | .ok (out, code) => return (if code != 0 then .ok (.trap code.toNat) else parseHexDump s out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  /-! ## Driver -/
97
 
 
 
 
 
 
 
 
 
 
98
  def parseMem (rest : List String) : Option Nat :=
99
  match rest with
100
  | [] => some 16
101
  | [m] => m.toNat?
102
  | _ => none
103
 
104
- def main (args : List String) : IO UInt32 := do
 
 
 
105
  match args with
106
  | ["emit", name] =>
107
  match allSamples32.find? (·.name == name) with
108
- | some s => IO.println (asmFor s); return 0
109
  | none => IO.eprintln "unknown sample"; return 1
110
  | "forth" :: path :: rest =>
111
  match parseMem rest with
112
  | none => IO.eprintln "usage: cm0c forth <file.fs> [memWords]"; return 2
113
- | some m => return (if ← check32 runNative (← forthFileSample32 path m) then 0 else 1)
114
  | "emit-forth" :: path :: rest =>
115
  match parseMem rest with
116
  | none => IO.eprintln "usage: cm0c emit-forth <file.fs> [memWords]"; return 2
@@ -118,9 +181,34 @@ def main (args : List String) : IO UInt32 := do
118
  let s ← forthFileSample32 path m
119
  match s.buildError with
120
  | some e => IO.eprintln e; return 1
121
- | none => IO.println (asmFor s); return 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  | "check" :: rest =>
123
  let count := match rest with | [n] => n.toNat! | _ => 200
124
- let ok ← checkAll32 runNative count
125
- return (if ok then 0 else 1)
126
- | _ => IO.eprintln "usage: cm0c check [fuzzCount] | cm0c emit <sample> | cm0c forth <file.fs> [memWords] | cm0c emit-forth <file.fs> [memWords]"; return 2
 
 
14
  3. runs the image on the emulated BBC micro:bit, an nRF51822 (Cortex-M0, 256 KiB of flash,
15
  16 KiB of SRAM; `qemu-system-arm -M microbit`). It takes the initial stack pointer and reset
16
  vector from the vector table, copies `.data` from flash to SRAM, prints through the nRF51
17
+ UART and ends the run there (an `EXIT` line and the status, then `wfi`; the harness reads up
18
+ to that line and stops the emulator),
19
  4. runs the same IR program under the Lean semantics at width 32 (`WordDialect.run`), and
20
  5. compares the exit status and the dumped data stack, IR memory and virtual registers.
21
 
 
24
  `INT_MIN / -1`, which the division loop must wrap), the auxiliary-stack and overflow programs,
25
  and Forth source files compiled at width 32.
26
 
27
+ For a real board, `cm0c image` writes the ELF, an Intel HEX file (copy it onto the micro:bit's
28
+ `MICROBIT` drive) and the UART transcript a correct run prints, for the micro:bit V1 or, with
29
+ `--board microbit-v2`, the V2; `cm0c verify` checks a serial log captured from the board
30
+ (`docs/HARDWARE.md`).
31
+
32
+ Usage: `cm0c check [fuzzCount]`, `cm0c image <file.fs> [memWords] [--board …]`,
33
+ `cm0c verify <file.fs> <serial.log> [memWords]`, `cm0c emit <sample>`, `cm0c forth <file.fs> [memWords]`,
34
+ `cm0c emit-forth <file.fs> [memWords]`; `--no-opt` with any of them lowers without the
35
+ stack-depth certificate and bound, keeping every guard; `cm0c stats <file.fs>` prints how many
36
+ guards the two leave out.
37
  -/
38
 
39
  open WordDialect
 
52
  def rcap : Nat := 1024
53
  def rEnd : Nat := rBase + 4 * rcap
54
 
55
+ /-- A board: its chip family, flash size, and (on nRF chips) its UART pins. -/
56
+ structure Board where
57
+ name : String
58
+ txPin : Nat := 0
59
+ rxPsel : Nat := 0
60
+ soc : CM0.Emit.Soc := .nrf
61
+ flashKiB : Nat := 256
62
+
63
+ /-- The BBC micro:bit V1 (nRF51822, a Cortex-M0): TX P0.24, RX P0.25. The emulator models it. -/
64
+ def microbitV1 : Board := { name := "microbit-v1", txPin := 24, rxPsel := 25 }
65
+
66
+ /-- The BBC micro:bit V2 (nRF52833, a Cortex-M4F, which runs ARMv6-M code): TX P0.06, RX P1.08
67
+ (`PSEL` 40 = port 1, pin 8). Not modelled by the emulator; for real boards. -/
68
+ def microbitV2 : Board := { name := "microbit-v2", txPin := 6, rxPsel := 40 }
69
+
70
+ /-- Microchip's SAM D21 Curiosity Nano (DM320119; `ATSAMD21G17D`, a Cortex-M0+ with 128 KiB of
71
+ flash and 16 KiB of SRAM, the same SRAM layout as the micro:bit). The transcript goes to the
72
+ on-board debugger's virtual COM port (SERCOM5 on PA22/PB22); the yellow LED lights when the run
73
+ halts with status 0; pressing SW0 runs the program again. Not modelled by the emulator. -/
74
+ def samd21Cnano : Board := { name := "samd21-cnano", soc := .samd21, flashKiB := 128 }
75
+
76
+ /-- The runtime for one program. With `opt` the lowering uses the stack-depth certificate
77
+ `safeCert` (`WordDialect.Depth`): the analysis result if `certOk` accepts it, else the empty
78
+ certificate. Either way `certOk` holds (`certTable_ok`), which is all the correctness theorem
79
+ needs, so the analysis itself is not trusted. The table is computed once per runtime. Likewise
80
+ the upper bounds `upperTable` (the least of the checked context-insensitive bound and the checked
81
+ per-word frame bound; `upperTable_sound`) decide which overflow guards are left out. -/
82
+ def runtimeFor (s : Sample32) (b : Board := microbitV1) (opt : Bool := true) : CM0.Emit.Runtime :=
83
+ let tbl := if opt then certTable s.prog else #[]
84
+ let r : CM0.Emit.Runtime :=
85
+ { dEnd := dEnd, capacity := capacity, rEnd := rEnd, rcap := rcap, memImage := s.mem,
86
+ nregs := s.nregs, aEnd := aEnd, acap := acap, txPin := b.txPin, rxPsel := b.rxPsel,
87
+ soc := b.soc, cert := fun k => tbl.getD k 0 }
88
+ if opt then
89
+ let up := upperTable s.prog r.dCap
90
+ { r with ub := fun k => upperAt up r.dCap k }
91
+ else r
92
+
93
+ def asmFor (s : Sample32) (b : Board := microbitV1) (opt : Bool := true) : String :=
94
+ let r := runtimeFor s b opt
95
+ CM0.Emit.program r (CM0.lowerProg r.layout s.prog)
96
 
97
  /-- The vector table and code in flash from address 0 (where a Cortex-M reads its initial stack
98
  pointer and reset vector); `.data` in the first 1 KiB of SRAM, loaded into flash after the code
99
  (`__data_load`); the stacks are uninitialised sections at fixed addresses. -/
100
+ def linkerScript (b : Board := microbitV1) : String :=
101
+ s!"ENTRY(_start)\nMEMORY \{\n FLASH (rx) : ORIGIN = 0x0, LENGTH = {b.flashKiB}K\n" ++
102
  " DATA (rw) : ORIGIN = 0x20000000, LENGTH = 1K\n STACKS (rw) : ORIGIN = 0x20000400, LENGTH = 12K\n}\nSECTIONS {\n" ++
103
  " .vectors : { *(.vectors) } > FLASH\n .text : { *(.text*) } > FLASH\n" ++
104
  " .data : { *(.data*) } > DATA AT > FLASH\n __data_load = LOADADDR(.data);\n" ++
 
108
 
109
  def workDir : String := "/tmp/cm0c"
110
 
111
+ /-- Assemble and link one assembly file; the ELF's path. -/
112
+ def buildElf (name asm : String) (b : Board := microbitV1) : IO (Except String String) := do
113
  IO.FS.createDirAll workDir
114
  let base := s!"{workDir}/{name}"
115
  IO.FS.writeFile (base ++ ".s") asm
116
+ IO.FS.writeFile (workDir ++ "/link.ld") (linkerScript b)
117
  let asArgs := #["--target=thumbv6m-none-eabi", "-mcpu=cortex-m0", "-c", "-o", base ++ ".o",
118
  base ++ ".s"]
119
  let a ← IO.Process.output { cmd := "clang", args := asArgs }
 
121
  let l ← IO.Process.output
122
  { cmd := "ld.lld", args := #["-T", workDir ++ "/link.ld", "-o", base, base ++ ".o"] }
123
  if l.exitCode != 0 then return .error s!"ld.lld failed: {l.stderr}"
124
+ return .ok base
125
+
126
+ /-- Build, run on the emulated micro:bit, and read its UART up to the end of the run (the `EXIT`
127
+ line and the status). The emulator is then stopped: the board itself sleeps for good. -/
128
+ def runAsm (name asm : String) : IO (Except String String) := do
129
+ match ← buildElf name asm with
 
 
 
 
 
 
 
130
  | .error e => return .error e
131
+ | .ok elf =>
132
+ let child ← IO.Process.spawn
133
+ { cmd := "qemu-system-arm",
134
+ args := #["-machine", "microbit", "-kernel", elf, "-display", "none", "-serial", "stdio",
135
+ "-monitor", "none"],
136
+ stdout := .piped, stderr := .null, stdin := .null }
137
+ let out ← readUntilExit child.stdout
138
+ child.kill
139
+ let _ ← child.wait
140
+ return .ok out
141
+
142
+ def runNative (opt : Bool := true) : Runner32 := fun s => do
143
+ match ← runAsm s.name (asmFor s microbitV1 opt) with
144
+ | .error e => return .error e
145
+ | .ok out => return parseTranscript s out
146
 
147
  /-! ## Driver -/
148
 
149
+ /-- `--board microbit-v1|microbit-v2|samd21-cnano` anywhere in the arguments, and the rest. -/
150
+ def takeBoard : List String → Option Board × List String
151
+ | "--board" :: "microbit-v1" :: rest => (some microbitV1, rest)
152
+ | "--board" :: "microbit-v2" :: rest => (some microbitV2, rest)
153
+ | "--board" :: "samd21-cnano" :: rest => (some samd21Cnano, rest)
154
+ | "--board" :: _ :: rest => (none, "--board?" :: rest)
155
+ | a :: rest => let (b, r) := takeBoard rest; (b, a :: r)
156
+ | [] => (none, [])
157
+
158
  def parseMem (rest : List String) : Option Nat :=
159
  match rest with
160
  | [] => some 16
161
  | [m] => m.toNat?
162
  | _ => none
163
 
164
+ def main (args0 : List String) : IO UInt32 := do
165
+ -- `--no-opt` keeps every guard (the lowering without depth certificates).
166
+ let opt := !args0.contains "--no-opt"
167
+ let args := args0.filter (· != "--no-opt")
168
  match args with
169
  | ["emit", name] =>
170
  match allSamples32.find? (·.name == name) with
171
+ | some s => IO.println (asmFor s microbitV1 opt); return 0
172
  | none => IO.eprintln "unknown sample"; return 1
173
  | "forth" :: path :: rest =>
174
  match parseMem rest with
175
  | none => IO.eprintln "usage: cm0c forth <file.fs> [memWords]"; return 2
176
+ | some m => return (if ← check32 (runNative opt) (← forthFileSample32 path m) then 0 else 1)
177
  | "emit-forth" :: path :: rest =>
178
  match parseMem rest with
179
  | none => IO.eprintln "usage: cm0c emit-forth <file.fs> [memWords]"; return 2
 
181
  let s ← forthFileSample32 path m
182
  match s.buildError with
183
  | some e => IO.eprintln e; return 1
184
+ | none => IO.println (asmFor s microbitV1 opt); return 0
185
+ | "image" :: path :: rest =>
186
+ let (b, rest) := takeBoard rest
187
+ match parseMem rest with
188
+ | none => IO.eprintln "usage: cm0c image <file.fs> [memWords] [--board microbit-v1|microbit-v2|samd21-cnano]"; return 2
189
+ | some m =>
190
+ let board := b.getD microbitV1
191
+ let s ← forthFileSample32 path m
192
+ if let some e := s.buildError then IO.eprintln e; return 1
193
+ match ← buildElf s!"{s.name}-{board.name}" (asmFor s board opt) board with
194
+ | .error e => IO.eprintln e; return 1
195
+ | .ok elf => writeImage s elf s!"{s.name}-{board.name}"
196
+ | "verify" :: path :: log :: rest =>
197
+ match parseMem rest with
198
+ | none => IO.eprintln "usage: cm0c verify <file.fs> <serial.log> [memWords]"; return 2
199
+ | some m => verifyLog (← forthFileSample32 path m) log
200
+ | "stats" :: path :: rest =>
201
+ match parseMem rest with
202
+ | none => IO.eprintln "usage: cm0c stats <file.fs> [memWords]"; return 2
203
+ | some m =>
204
+ let s ← forthFileSample32 path m
205
+ if let some e := s.buildError then IO.eprintln e; return 1
206
+ let r := runtimeFor s
207
+ IO.println (guardStats s r.cert r.ub r.dCap)
208
+ return 0
209
  | "check" :: rest =>
210
  let count := match rest with | [n] => n.toNat! | _ => 200
211
+ let ok ← checkAll32 (runNative opt) count
212
+ let okc ← checkCapacity32 (runNative opt) capacity
213
+ return (if ok && okc then 0 else 1)
214
+ | _ => IO.eprintln "usage: cm0c check [fuzzCount] | cm0c emit <sample> | cm0c forth <file.fs> [memWords] | cm0c emit-forth <file.fs> [memWords] | cm0c image <file.fs> [memWords] [--board microbit-v1|microbit-v2|samd21-cnano] | cm0c verify <file.fs> <serial.log> [memWords] | cm0c stats <file.fs> [memWords] (any command: --no-opt keeps every guard)"; return 2
backend/rv32/RV32/Correct.lean CHANGED
@@ -25,6 +25,11 @@ Hypotheses of both (all explicit):
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
 
 
 
 
 
28
  * `hsz` code indices fit in 32 bits;
29
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
30
  -/
@@ -44,15 +49,30 @@ def Final (c : Cfg) (p : Prog 32) (code : List (Instr Nat)) (x : M) : Outcome 32
44
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
45
  | .trapped t => RExec code x (.trapped t)
46
 
47
- theorem offs_ge {p : Prog 32} {k : Nat} (h : p.length ≤ k) : offs p k = offs p p.length := by
48
- simp [offs, List.take_of_length_le h, List.take_length]
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
51
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
52
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
53
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
54
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
55
- {s : State 32} {x : M} (hs : Rel c p s x) :
 
 
56
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
57
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
58
  cases hi : p[s.pc]? with
@@ -65,43 +85,48 @@ theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
65
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
66
  · omega
67
  obtain ⟨f0, _⟩ := lowerProg_stub L p
68
- have hpc : x.pc = offs p p.length := by rw [hs.2, offs_ge hge]
 
69
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
70
  | some i =>
71
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
72
  rw [hst]
73
- exact sim_exec hg hL hMs hLd hLr hLa hLal hsz hs hi (fun r hr => hreg s.pc i hi r hr)
74
 
75
  /-- Whole-program preservation, with no capacity hypothesis: the RISC-V code reaches the IR
76
  outcome, or exits with `overflow` because a stack was full. -/
77
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
78
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
79
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
80
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
81
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
82
- ∀ {x : M}, Rel c p s x →
83
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
84
  induction h with
85
  | @halt s s' hst =>
86
- intro x hs
87
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
88
  rw [hst] at this
89
  rcases this with this | ⟨_, h6⟩
90
  · exact .inl this
91
  · exact .inr h6
92
  | @trap s t hst =>
93
- intro x hs
94
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
95
  rw [hst] at this
96
  rcases this with this | ⟨_, h6⟩
97
  · exact .inl this
98
  · exact .inr h6
99
  | @next s s' o hst _ ih =>
100
- intro x hs
101
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
102
  rw [hst] at this
103
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
104
- · rcases ih hrel with hih | h6
105
  · left
106
  cases o with
107
  | next _ => exact hih.elim
@@ -117,31 +142,35 @@ every reachable state), no overflow guard fires and the outcome is exactly the I
117
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
118
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
119
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
120
- (hLal : L.aLim = ofN (c.aBase + 4)) (hsz : ∀ k, offs p k < 2 ^ 32) (hreg : RegsOk c p)
 
 
 
 
121
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
122
- ∀ {x : M}, Rel c p s x → (∀ s', Steps p s s' → Fits c s') →
123
  Final c p (lowerProg L p) x o := by
124
  induction h with
125
  | @halt s s' hst =>
126
- intro x hs hb
127
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
128
  rw [hst] at this
129
  rcases this with this | ⟨hnf, _⟩
130
  · exact this
131
  · exact absurd (hb s .refl) hnf
132
  | @trap s t hst =>
133
- intro x hs hb
134
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
135
  rw [hst] at this
136
  rcases this with this | ⟨hnf, _⟩
137
  · exact this
138
  · exact absurd (hb s .refl) hnf
139
  | @next s s' o hst _ ih =>
140
- intro x hs hb
141
- have := step_sim hg hL hMs hLd hLr hLa hLal hsz hreg hs
142
  rw [hst] at this
143
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
144
- · have hih := ih hrel (fun s'' hss => hb s'' (Steps.cons hst hss))
145
  cases o with
146
  | next _ => exact hih.elim
147
  | halted s2 =>
@@ -159,7 +188,7 @@ theorem init_rel {c : Cfg} {p : Prog 32} {s0 : State 32} {x0 : M} (hg : Geom c)
159
  (h13 : x0.regs Reg.s3 = ofN c.mb) (h12 : x0.regs Reg.s4 = ofN c.sp0)
160
  (hsp : x0.regs Reg.s5 = ofN c.sp0) (hbp : x0.regs Reg.s6 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
161
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
162
- (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs p s0.pc) : Rel c p s0 x0 :=
163
  ⟨{ s1 := by simpa [hd] using h15
164
  s2 := h14
165
  s3 := h13
 
25
  at least two;
26
  * `L` matches `c` data-stack end and limit, return-stack gap, auxiliary-stack end and limit,
27
  and IR memory size;
28
+ * `hLf`, `hok`, `I` the code was lowered with the configuration's facts: its lower-bound
29
+ certificate passes `certOk`, and its upper bound `c.ub` is implied by an
30
+ invariant `I` kept by every step within the data stack's capacity (`hIs`,
31
+ `hIb`; `WordDialect.UbSound`); the runs carry `DepthInv` and `I`, so every
32
+ underflow or overflow guard the lowering left out would have passed;
33
  * `hsz` code indices fit in 32 bits;
34
  * `RegsOk` every `push r`/`pop r` names a register inside the register file.
35
  -/
 
49
  | .halted s' => ∃ x', RExec code x (.halted x') ∧ Rel0 c p s' x'
50
  | .trapped t => RExec code x (.trapped t)
51
 
52
+ theorem offs_ge (cf : Nat → Facts) {p : Prog 32} {k : Nat} (h : p.length ≤ k) :
53
+ offs cf p k = offs cf p p.length := by
54
+ induction p generalizing cf k with
55
+ | nil => cases k <;> simp [offs]
56
+ | cons i is ih =>
57
+ cases k with
58
+ | zero => simp at h
59
+ | succ k => simp only [List.length_cons, offs]; rw [ih _ (by simp at h; omega)]
60
+
61
+ /-- A related state is within the data stack's capacity. -/
62
+ theorem cap_of_rel {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hs : Rel c p s x) :
63
+ s.dstack.length ≤ c.dCap := by
64
+ have := hs.1.capD
65
+ unfold Cfg.dCap
66
+ omega
67
 
68
  /-- One IR step from a related state: the bad-pc stub, or the dispatched instruction. -/
69
  theorem step_sim {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
70
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
71
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
72
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
73
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
74
+ {s : State 32} {x : M} (hs : Rel c p s x) (hdi : DepthInv c.cert s)
75
+ (hub : s.dstack.length ≤ c.ub s.pc) :
76
  Sim c p (lowerProg L p) x (WordDialect.step p s) ∨
77
  (¬ Fits c s ∧ RExec (lowerProg L p) x .overflow) := by
78
  cases hi : p[s.pc]? with
 
85
  · rw [List.getElem?_eq_getElem hh] at hi; simp at hi
86
  · omega
87
  obtain ⟨f0, _⟩ := lowerProg_stub L p
88
+ rw [hLf] at f0
89
+ have hpc : x.pc = offs c.facts p p.length := by rw [hs.2, offs_ge _ hge]
90
  exact RExec.trap (by rw [rstep_of_fetch (by rw [hpc]; exact f0)]; rfl)
91
  | some i =>
92
  have hst : WordDialect.step p s = WordDialect.exec i s := by simp [WordDialect.step, hi]
93
  rw [hst]
94
+ exact sim_exec hg hL hMs hLd hLr hLa hLal hLf hsz hs hdi.depth hub hi (fun r hr => hreg s.pc i hi r hr)
95
 
96
  /-- Whole-program preservation, with no capacity hypothesis: the RISC-V code reaches the IR
97
  outcome, or exits with `overflow` because a stack was full. -/
98
  theorem lowerProg_correct_or_overflow {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
99
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
100
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
101
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
102
+ {I : State 32 → Prop}
103
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
104
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
105
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
106
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
107
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s →
108
  Final c p (lowerProg L p) x o ∨ RExec (lowerProg L p) x .overflow := by
109
  induction h with
110
  | @halt s s' hst =>
111
+ intro x hs hdi hbi
112
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
113
  rw [hst] at this
114
  rcases this with this | ⟨_, h6⟩
115
  · exact .inl this
116
  · exact .inr h6
117
  | @trap s t hst =>
118
+ intro x hs hdi hbi
119
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
120
  rw [hst] at this
121
  rcases this with this | ⟨_, h6⟩
122
  · exact .inl this
123
  · exact .inr h6
124
  | @next s s' o hst _ ih =>
125
+ intro x hs hdi hbi
126
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
127
  rw [hst] at this
128
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨_, h6⟩
129
+ · rcases ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) with hih | h6
130
  · left
131
  cases o with
132
  | next _ => exact hih.elim
 
142
  theorem lowerProg_correct {c : Cfg} {p : Prog 32} {L : Layout} (hg : Geom c)
143
  (hL : L.dEnd = ofN c.dEnd) (hMs : L.memSize = c.M) (hLd : L.dLim = ofN (c.dBase + 4))
144
  (hLr : L.rGap = ofN (4 * c.rcap - 8)) (hLa : L.aEnd = ofN c.aEnd)
145
+ (hLal : L.aLim = ofN (c.aBase + 4)) (hLf : L.facts = c.facts) (hok : certOk p c.cert = true)
146
+ {I : State 32 → Prop}
147
+ (hIs : ∀ s s', I s → s.dstack.length ≤ c.dCap → WordDialect.step p s = .next s' → I s')
148
+ (hIb : ∀ s, I s → s.dstack.length ≤ c.ub s.pc)
149
+ (hsz : ∀ k, offs c.facts p k < 2 ^ 32) (hreg : RegsOk c p)
150
  {s : State 32} {o : Outcome 32} (h : Exec p s o) :
151
+ ∀ {x : M}, Rel c p s x → DepthInv c.cert s → I s → (∀ s', Steps p s s' → Fits c s') →
152
  Final c p (lowerProg L p) x o := by
153
  induction h with
154
  | @halt s s' hst =>
155
+ intro x hs hdi hbi hb
156
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
157
  rw [hst] at this
158
  rcases this with this | ⟨hnf, _⟩
159
  · exact this
160
  · exact absurd (hb s .refl) hnf
161
  | @trap s t hst =>
162
+ intro x hs hdi hbi hb
163
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
164
  rw [hst] at this
165
  rcases this with this | ⟨hnf, _⟩
166
  · exact this
167
  · exact absurd (hb s .refl) hnf
168
  | @next s s' o hst _ ih =>
169
+ intro x hs hdi hbi hb
170
+ have := step_sim hg hL hMs hLd hLr hLa hLal hLf hok hsz hreg hs hdi (hIb s hbi)
171
  rw [hst] at this
172
  rcases this with ⟨x1, hsteps, hrel⟩ | ⟨hnf, _⟩
173
+ · have hih := ih hrel (DepthInv.step hok hdi hst) (hIs s _ hbi (cap_of_rel hs) hst) (fun s'' hss => hb s'' (Steps.cons hst hss))
174
  cases o with
175
  | next _ => exact hih.elim
176
  | halted s2 =>
 
188
  (h13 : x0.regs Reg.s3 = ofN c.mb) (h12 : x0.regs Reg.s4 = ofN c.sp0)
189
  (hsp : x0.regs Reg.s5 = ofN c.sp0) (hbp : x0.regs Reg.s6 = ofN c.aEnd) (hregs : RegRel c x0.mem s0.regs)
190
  (hmem : MemRel c x0.mem s0.mem) (hiv : ∀ a : Word 32, s0.mem.valid a = decide (a.toNat < c.M))
191
+ (hxv : RegionsValid c x0.mem.valid) (hpc : x0.pc = offs c.facts p s0.pc) : Rel c p s0 x0 :=
192
  ⟨{ s1 := by simpa [hd] using h15
193
  s2 := h14
194
  s3 := h13
backend/rv32/RV32/Emit.lean CHANGED
@@ -146,6 +146,13 @@ structure Runtime where
146
  acap : Nat
147
  uartBase : Nat := 0x10000000
148
  exitBase : Nat := 0x100000
 
 
 
 
 
 
 
149
 
150
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
151
 
@@ -153,11 +160,15 @@ def Runtime.rBase (r : Runtime) : Nat := r.rEnd - 4 * r.rcap
153
 
154
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
155
 
 
 
 
156
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
157
  def Runtime.layout (r : Runtime) : Layout :=
158
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
159
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
160
- aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4) }
 
161
 
162
  /-- The runtime prologue. Its model is `RV32.Emit.prologueCode` (`RV32/Init.lean`), where each
163
  `lla` is the `movImm` of the address the linker resolves the symbol to; keep the two in step. -/
 
146
  acap : Nat
147
  uartBase : Nat := 0x10000000
148
  exitBase : Nat := 0x100000
149
+ /-- The stack-depth certificate the code is lowered with (`WordDialect.Depth`); the driver
150
+ passes `certTable` of the program. The default claims nothing and keeps every guard. -/
151
+ cert : Nat → Nat := fun _ => 0
152
+ /-- The upper bound on the data-stack depth the code is lowered with; the driver passes
153
+ `upperTable` of the program against `dCap` (`WordDialect.Depth`). An overflow guard is left out
154
+ where `ub k + 1 ≤ dCap`; the default (`2^32` everywhere) shows no room, so every guard stays. -/
155
+ ub : Nat → Nat := fun _ => 2 ^ 32
156
 
157
  def Runtime.dBase (r : Runtime) : Nat := r.dEnd - 4 * r.capacity
158
 
 
160
 
161
  def Runtime.aBase (r : Runtime) : Nat := r.aEnd - 4 * r.acap
162
 
163
+ /-- The data stack's capacity in words. -/
164
+ def Runtime.dCap (r : Runtime) : Nat := (r.dEnd - r.dBase) / 4
165
+
166
  /-- The lowering's view of the runtime: the constants the guards and bounds checks use. -/
167
  def Runtime.layout (r : Runtime) : Layout :=
168
  { dEnd := BitVec.ofNat 32 r.dEnd, memSize := r.memImage.length,
169
  dLim := BitVec.ofNat 32 (r.dBase + 4), rGap := BitVec.ofNat 32 (4 * r.rcap - 8),
170
+ aEnd := BitVec.ofNat 32 r.aEnd, aLim := BitVec.ofNat 32 (r.aBase + 4), cert := r.cert,
171
+ ub := r.ub, dCap := r.dCap }
172
 
173
  /-- The runtime prologue. Its model is `RV32.Emit.prologueCode` (`RV32/Init.lean`), where each
174
  `lla` is the `movImm` of the address the linker resolves the symbol to; keep the two in step. -/
backend/rv32/RV32/Guard.lean CHANGED
@@ -40,7 +40,7 @@ theorem uf_cond {c : Cfg} {p : Prog 32} {s : State 32} {x : M} (hg : Geom c) (hs
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
- theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
@@ -62,19 +62,38 @@ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Ins
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
- /-- Too few operands: the guard exits with `stackUnderflow`. -/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
67
- {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
68
- (hn : 0 < n) (hn3 : n ≤ 3) (hk : s.dstack.length < n) (hpc : x.pc = base)
69
- (hat : RAt code base (uf L n base)) : RExec code x (.trapped .stackUnderflow) := by
70
- rw [uf_eq L hn] at hat
 
 
71
  obtain ⟨h1, h2, h3, _⟩ := hat
72
- let xa := x.mov t0 (L.dEnd - BitVec.ofNat 32 (4 * n))
73
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
74
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
75
  have hholds : Cond.eval .ule (xa.regs s1) (xa.regs t0) = false := by
76
- have := uf_cond hg hs hL hn hn3
77
- have h : ¬ n ≤ s.dstack.length := by omega
78
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
79
  exact RExec.of_steps (RSteps.single hst1)
80
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
@@ -131,6 +150,29 @@ theorem ovfD_trap (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase
131
  rw [hra s1 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
132
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
135
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
136
  Cond.eval .uge (x.regs Reg.s5) (x.regs Reg.s4 - L.rGap) =
 
40
  · simp [h]; omega
41
 
42
  /-- Enough operands: the guard falls through to `base + 3`, changing only scratch state. -/
43
+ theorem uf_pass_pos {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
44
  {L : Layout} {base n : Nat} (hg : Geom c) (hs : Rel0 c p s x) (hL : L.dEnd = ofN c.dEnd)
45
  (hn : 0 < n) (hn3 : n ≤ 3) (hk : n ≤ s.dstack.length) (hpc : x.pc = base)
46
  (hat : RAt code base (uf L n base)) :
 
62
  simp [xa, M.adv, M.mov, M.setReg]
63
  · intro r hr; simp [xa, M.adv, M.mov, M.setReg, hr]
64
 
65
+ /-- The guard of an instruction popping `k` words, when the data stack is known to hold at least
66
+ `g` words: with enough operands it falls through, to `base + ufSize (need g k)` (at once when the
67
+ certificate made the guard empty). -/
68
+ theorem uf_pass {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
69
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
70
+ (hL : L.dEnd = ofN c.dEnd) (hk3 : k ≤ 3) (hk : k ≤ s.dstack.length) (hpc : x.pc = base)
71
+ (hat : RAt code base (uf L (need g k) base)) :
72
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ufSize (need g k) ∧ x1.mem = x.mem ∧
73
+ (∀ r, r ≠ t0 → x1.regs r = x.regs r) := by
74
+ by_cases h0 : need g k = 0
75
+ · rw [h0]; exact ⟨x, .refl, hs, by simp [ufSize, hpc], rfl, fun _ _ => rfl⟩
76
+ · have hn : 0 < need g k := Nat.pos_of_ne_zero h0
77
+ have hle := need_le g k
78
+ obtain ⟨x1, a, b, hpc1, d, e⟩ := uf_pass_pos hg hs hL hn (by omega) (by omega) hpc hat
79
+ exact ⟨x1, a, b, by rw [hpc1, ufSize_pos hn], d, e⟩
80
+
81
+ /-- Too few operands: the guard exits with `stackUnderflow`. It is there, because the depth
82
+ certificate's bound `g.lo` is a true lower bound (`hgd`) and the stack holds fewer than `k` words. -/
83
  theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
84
+ {L : Layout} {base k : Nat} {g : Facts} (hg : Geom c) (hs : Rel0 c p s x)
85
+ (hL : L.dEnd = ofN c.dEnd) (hk0 : 0 < k) (hk3 : k ≤ 3) (hgd : g.lo ≤ s.dstack.length) (hk : s.dstack.length < k)
86
+ (hpc : x.pc = base) (hat : RAt code base (uf L (need g k) base)) :
87
+ RExec code x (.trapped .stackUnderflow) := by
88
+ rw [need_of_lt (by omega)] at hat
89
+ rw [uf_eq L hk0] at hat
90
  obtain ⟨h1, h2, h3, _⟩ := hat
91
+ let xa := x.mov t0 (L.dEnd - BitVec.ofNat 32 (4 * k))
92
  have hst1 : step code x = .next xa := by rw [rstep_of_fetch (by rw [hpc]; exact h1)]; rfl
93
  have hxa_pc : xa.pc = base + 1 := by simp [xa, M.mov, M.setReg, M.adv, hpc]
94
  have hholds : Cond.eval .ule (xa.regs s1) (xa.regs t0) = false := by
95
+ have := uf_cond hg hs hL hk0 hk3
96
+ have h : ¬ k ≤ s.dstack.length := by omega
97
  simpa [xa, M.mov, M.setReg, M.adv, h] using this
98
  exact RExec.of_steps (RSteps.single hst1)
99
  (guard_trap (code := code) (pc := base + 1) (m := xa) (t := .stackUnderflow)
 
150
  rw [hra s1 (by decide), hta, ovfD_cond hg hs hLd]; simpa using h
151
  exact RExec.of_steps hsa (ovf_trap hj he hpca hholds)
152
 
153
+ /-- The data-stack guard where the facts keep it: with room for one more word, it falls through
154
+ to `base + ovfSize g` (at once when the bound left the guard out). -/
155
+ theorem ovfG_pass {g : Facts} (hg : Geom c) (hs : Rel0 c p s x) (hLd : L.dLim = ofN (c.dBase + 4))
156
+ (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) (hpc : x.pc = base)
157
+ (hat : RAt code base (ovf L g base)) :
158
+ ∃ x1, RSteps code x x1 ∧ Rel0 c p s x1 ∧ x1.pc = base + ovfSize g ∧ x1.mem = x.mem ∧
159
+ (∀ r, r ≠ t0 → x1.regs r = x.regs r) := by
160
+ unfold ovf at hat
161
+ unfold ovfSize
162
+ cases hn : g.noOvf
163
+ · simp only [hn, Bool.false_eq_true, if_false] at hat ⊢
164
+ exact ovfD_pass hg hs hLd hfit hpc hat
165
+ · exact ⟨x, .refl, hs, by simp [hpc], rfl, fun _ _ => rfl⟩
166
+
167
+ /-- Data stack full: the guard is there (the bound did not claim room) and exits with
168
+ `overflow`. -/
169
+ theorem ovfG_trap {g : Facts} (hn : g.noOvf = false) (hg : Geom c) (hs : Rel0 c p s x)
170
+ (hLd : L.dLim = ofN (c.dBase + 4)) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd)
171
+ (hpc : x.pc = base) (hat : RAt code base (ovf L g base)) : RExec code x .overflow := by
172
+ unfold ovf at hat
173
+ simp only [hn, Bool.false_eq_true, if_false] at hat
174
+ exact ovfD_trap hg hs hLd h hpc hat
175
+
176
  /-- The return-stack guard's comparison, in terms of return-stack depth. -/
177
  theorem ovfR_cond (hg : Geom c) (hs : Rel0 c p s x) (hLr : L.rGap = ofN (4 * c.rcap - 8)) :
178
  Cond.eval .uge (x.regs Reg.s5) (x.regs Reg.s4 - L.rGap) =
backend/rv32/RV32/Init.lean CHANGED
@@ -28,7 +28,9 @@ be derived inside the model, so it is stated once, explicitly, as `Loader.Holds`
28
 
29
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
30
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
31
- only about the program.
 
 
32
  -/
33
 
34
  namespace WordDialect
@@ -45,7 +47,8 @@ structure Loader where
45
  /-- The runtime placement for one run, as a `Cfg`. -/
46
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
47
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
48
- M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase }
 
49
 
50
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
51
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
@@ -70,36 +73,38 @@ theorem prologue_run (r : Runtime) (ld : Loader) (x0 : M) :
70
  .next { entryState r ld x0 with pc := x0.pc + 6 } := by
71
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
72
 
73
- theorem isize_le (i : WordDialect.Instr 32) : isize i ≤ 17 := by
74
- cases i <;> simp [isize, ufSize]
75
-
76
- theorem sum_isize_le : ∀ l : Prog 32, (l.map isize).sum ≤ 17 * l.length
77
- | [] => by simp
78
- | i :: l => by
79
- have := isize_le i
80
- have := sum_isize_le l
81
- simp only [List.map_cons, List.sum_cons, List.length_cons]
 
 
 
 
82
  omega
83
 
84
  /-- Code indices are bounded by the program length. -/
85
- theorem offs_lt {p : Prog 32} (h : 17 * p.length < 2 ^ 32) (k : Nat) : offs p k < 2 ^ 32 := by
86
- have h1 := sum_isize_le (p.take k)
87
- have h2 : (p.take k).length ≤ p.length := by rw [List.length_take]; omega
88
- simp only [offs]
89
- omega
90
 
91
  theorem layout_ok (r : Runtime) (ld : Loader) :
92
- r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
93
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
94
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
95
- ⟨rfl, rfl, rfl, rfl, rfl, rfl⟩
96
 
97
  /-- After the prologue, the machine is related to the IR's initial state. -/
98
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
99
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
100
  have hg := h.geom
101
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
102
- ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init])
103
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
104
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
105
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
@@ -120,14 +125,17 @@ theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p :
120
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
121
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
122
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 17 * p.length < 2 ^ 32)
123
- (hreg : RegsOk (cfgOf r ld) p) {o : Outcome 32}
 
124
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
125
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 6 } ∧
126
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
127
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
128
- obtain ⟨hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
 
129
  exact ⟨prologue_run r ld x0,
130
- lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal (offs_lt hlen) hreg hx (entry_rel r ld h p)⟩
 
131
 
132
  end Emit
133
  end RV32
 
28
 
29
  `binary_correct`: under those loader facts, after the prologue the lowered code reaches the IR
30
  outcome from `State.init` on the memory image, or exits with `overflow`. Its other hypotheses are
31
+ only about the program, including `certOk` for the runtime's stack-depth certificate and
32
+ `UbSound` for its upper bound (the lowering leaves out the underflow and overflow guards they
33
+ cover).
34
  -/
35
 
36
  namespace WordDialect
 
47
  /-- The runtime placement for one run, as a `Cfg`. -/
48
  def cfgOf (r : Runtime) (ld : Loader) : Cfg :=
49
  { dEnd := r.dEnd, dBase := r.dBase, rf := ld.rf, nregs := r.nregs, mb := ld.mb,
50
+ M := r.memImage.length, sp0 := r.rEnd, rcap := r.rcap, aEnd := r.aEnd, aBase := r.aBase,
51
+ cert := r.cert, ub := r.ub }
52
 
53
  /-- What the loader guarantees about the machine state `x0` at `_start`. -/
54
  structure Loader.Holds (r : Runtime) (ld : Loader) (x0 : M) : Prop where
 
73
  .next { entryState r ld x0 with pc := x0.pc + 6 } := by
74
  simp [prologueCode, entryState, rseq, exec, M.mov, M.setReg, M.adv]
75
 
76
+ theorem isize_le (g : Facts) (i : WordDialect.Instr 32) : isize g i ≤ 17 := by
77
+ have hu : ∀ k, ufSize (need g k) ≤ 3 := fun k => by unfold ufSize; split <;> omega
78
+ have hv : ovfSize g ≤ 3 := by unfold ovfSize; split <;> omega
79
+ have h1 := hu 1; have h2 := hu 2; have h3 := hu 3
80
+ cases i <;> simp only [isize] <;> omega
81
+
82
+ theorem offs_le (cf : Nat → Facts) : ∀ (p : Prog 32) (k : Nat), offs cf p k ≤ 17 * p.length
83
+ | [], k => by cases k <;> simp [offs]
84
+ | i :: l, 0 => by simp [offs]
85
+ | i :: l, k + 1 => by
86
+ have := isize_le (cf 0) i
87
+ have := offs_le (fun j => cf (j + 1)) l k
88
+ simp only [offs, List.length_cons]
89
  omega
90
 
91
  /-- Code indices are bounded by the program length. -/
92
+ theorem offs_lt (cf : Nat → Facts) {p : Prog 32} (h : 17 * p.length < 2 ^ 32) (k : Nat) :
93
+ offs cf p k < 2 ^ 32 :=
94
+ Nat.lt_of_le_of_lt (offs_le cf p k) h
 
 
95
 
96
  theorem layout_ok (r : Runtime) (ld : Loader) :
97
+ r.layout.facts = (cfgOf r ld).facts ∧ r.layout.dEnd = ofN (cfgOf r ld).dEnd ∧ r.layout.memSize = (cfgOf r ld).M ∧
98
  r.layout.dLim = ofN ((cfgOf r ld).dBase + 4) ∧ r.layout.rGap = ofN (4 * (cfgOf r ld).rcap - 8) ∧
99
  r.layout.aEnd = ofN (cfgOf r ld).aEnd ∧ r.layout.aLim = ofN ((cfgOf r ld).aBase + 4) :=
100
+ ⟨funext fun _ => rfl, rfl, rfl, rfl, rfl, rfl, rfl⟩
101
 
102
  /-- After the prologue, the machine is related to the IR's initial state. -/
103
  theorem entry_rel (r : Runtime) (ld : Loader) {x0 : M} (h : ld.Holds r x0) (p : Prog 32) :
104
  Rel (cfgOf r ld) p (State.init (Memory.ofImage r.memImage)) (entryState r ld x0) := by
105
  have hg := h.geom
106
  refine init_rel hg rfl rfl rfl (by have := hg.rcap_ge; simp [cfgOf] at this ⊢; omega)
107
+ ?_ ?_ ?_ ?_ ?_ ?_ ?_ ?_ (fun _ => rfl) ?_ (by simp [entryState, offs, State.init, offs_zero])
108
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
109
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
110
  · simp [entryState, M.mov, M.setReg, M.adv, cfgOf]
 
125
  the outcome the IR reaches from `State.init` on the memory image, or exits with `overflow` (exit
126
  code 6). Program hypotheses: code indices fit in 32 bits and register indices are in range. -/
127
  theorem binary_correct (r : Runtime) (ld : Loader) (p : Prog 32) (hlen : 17 * p.length < 2 ^ 32)
128
+ (hreg : RegsOk (cfgOf r ld) p) (hok : certOk p r.cert = true)
129
+ (hub : UbSound p r.dCap r.ub) {o : Outcome 32}
130
  (hx : Exec p (State.init (Memory.ofImage r.memImage)) o) {x0 : M} (h : ld.Holds r x0) :
131
  rseq (prologueCode r ld) x0 = .next { entryState r ld x0 with pc := x0.pc + 6 } ∧
132
  (Final (cfgOf r ld) p (lowerProg r.layout p) (entryState r ld x0) o ∨
133
  RExec (lowerProg r.layout p) (entryState r ld x0) .overflow) := by
134
+ obtain ⟨hLc, hL, hMs, hLd, hLr, hLa, hLal⟩ := layout_ok r ld
135
+ obtain ⟨I, hI0, hIs, hIb⟩ := hub
136
  exact ⟨prologue_run r ld x0,
137
+ lowerProg_correct_or_overflow h.geom hL hMs hLd hLr hLa hLal hLc hok hIs hIb (offs_lt _ hlen)
138
+ hreg hx (entry_rel r ld h p) (DepthInv.init (certOk_entry hok) _) (hI0 _)⟩
139
 
140
  end Emit
141
  end RV32
backend/rv32/RV32/Lower.lean CHANGED
@@ -1,4 +1,5 @@
1
  import RV32.Isa
 
2
 
3
  /-!
4
  # RV32.Lower
@@ -45,6 +46,24 @@ structure Layout where
45
  rGap : W -- `4 rcap - 8`: a call has room iff `s5 ≥ s4 - rGap`
46
  aEnd : W -- empty auxiliary stack: `s6 = aEnd`
47
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `s6 ≥ aLim`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  /-- Stack-underflow guard for `k` operands: continue when `s1 ≤ dEnd - 4k`. -/
50
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
@@ -54,10 +73,25 @@ def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
54
 
55
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
56
 
 
 
 
 
 
 
 
 
 
57
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
58
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
59
  [.movImm t0 L.dLim, .bcc .uge s1 t0 (base + 3), .exitOvf]
60
 
 
 
 
 
 
 
61
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
62
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
63
  [.movRR t0 s4, .movImm t1 L.rGap, .sub t0 t1, .bcc .uge s5 t0 (base + 5), .exitOvf]
@@ -71,132 +105,145 @@ def emptyA (L : Layout) (base : Nat) : List (Instr Nat) :=
71
  [.movImm t0 L.aEnd, .bcc .ne s6 t0 (base + 3), .exitTrap .returnUnderflow]
72
 
73
  /-- Code size of one IR instruction. -/
74
- def isize : WordDialect.Instr 32 → Nat
75
- | .word _ | .ptr _ => 6
76
- | .load => ufSize 1 + 8
77
- | .store => ufSize 2 + 9
78
- | .add | .sub | .mul | .and | .or | .xor => ufSize 2 + 5
79
- | .div | .sdiv => ufSize 2 + 7
80
- | .not => ufSize 1 + 3
81
- | .shl | .shr => ufSize 2 + 8
82
- | .rotl | .rotr => ufSize 2 + 9
83
- | .cmp _ => ufSize 2 + 7
84
- | .select => ufSize 3 + 7
85
  | .jmp _ => 1
86
- | .branch _ => ufSize 1 + 3
87
  | .call _ => 6
88
  | .ret => 3
89
- | .push _ => 6
90
- | .pop _ => ufSize 1 + 3
91
- | .dup => ufSize 1 + 6
92
- | .drop => ufSize 1 + 1
93
- | .swap => ufSize 2 + 4
94
- | .over => ufSize 2 + 6
95
- | .rot => ufSize 3 + 6
96
- | .tor => ufSize 1 + 7
97
- | .fromr => 10
98
- | .rfetch => 9
99
  | .halt => 1
100
 
101
  /-- Code for one IR instruction placed at RV index `base`; `off t` is the RV index of IR
102
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
103
- def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) : WordDialect.Instr 32 → List (Instr Nat)
104
- | .word w => ovfD L base ++ [.movImm t0 w, .addImm s1 (-4), .store s1 0 t0]
105
- | .ptr p => ovfD L base ++ [.movImm t0 p.toWord, .addImm s1 (-4), .store s1 0 t0]
 
106
  | .load =>
107
- let b0 := base + ufSize 1
108
- uf L 1 base ++
109
  [.load t0 s1 0, .movImm t1 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t1 (b0 + 4),
110
  .exitTrap .badAddress, .shlImm t0 2, .add t0 s3, .load t0 t0 0, .store s1 0 t0]
111
  | .store =>
112
- let b0 := base + ufSize 2
113
- uf L 2 base ++
114
  [.load t0 s1 0, .load t1 s1 4, .movImm t2 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t2 (b0 + 5),
115
  .exitTrap .badAddress, .shlImm t0 2, .add t0 s3, .store t0 0 t1, .addImm s1 8]
116
- | .add => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .add t0 t1, .store s1 4 t0, .addImm s1 4]
117
- | .sub => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .sub t0 t1, .store s1 4 t0, .addImm s1 4]
118
- | .mul => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .mul t0 t1, .store s1 4 t0, .addImm s1 4]
119
- | .and => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .and t0 t1, .store s1 4 t0, .addImm s1 4]
120
- | .or => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .or t0 t1, .store s1 4 t0, .addImm s1 4]
121
- | .xor => uf L 2 base ++ [.load t1 s1 0, .load t0 s1 4, .xor t0 t1, .store s1 4 t0, .addImm s1 4]
122
  | .div =>
123
- let b0 := base + ufSize 2
124
- uf L 2 base ++
125
  [.load t1 s1 0, .load t0 s1 4, .bnez t1 (b0 + 4), .exitTrap .divideByZero, .divu t0 t0 t1,
126
  .store s1 4 t0, .addImm s1 4]
127
  | .sdiv =>
128
- let b0 := base + ufSize 2
129
- uf L 2 base ++
130
  [.load t1 s1 0, .load t0 s1 4, .bnez t1 (b0 + 4), .exitTrap .divideByZero, .div t0 t0 t1,
131
  .store s1 4 t0, .addImm s1 4]
132
- | .not => uf L 1 base ++ [.load t0 s1 0, .not t0, .store s1 0 t0]
133
  | .shl =>
134
- uf L 2 base ++
135
  [.load t1 s1 0, .load t0 s1 4, .sll t0 t1, .sltiu t2 t1 32, .neg t2, .and t0 t2,
136
  .store s1 4 t0, .addImm s1 4]
137
  | .shr =>
138
- uf L 2 base ++
139
  [.load t1 s1 0, .load t0 s1 4, .srl t0 t1, .sltiu t2 t1 32, .neg t2, .and t0 t2,
140
  .store s1 4 t0, .addImm s1 4]
141
  | .rotl =>
142
- uf L 2 base ++
143
  [.load t1 s1 0, .load t0 s1 4, .movRR t2 t0, .sll t0 t1, .neg t1, .srl t2 t1, .or t0 t2,
144
  .store s1 4 t0, .addImm s1 4]
145
  | .rotr =>
146
- uf L 2 base ++
147
  [.load t1 s1 0, .load t0 s1 4, .movRR t2 t0, .srl t0 t1, .neg t1, .sll t2 t1, .or t0 t2,
148
  .store s1 4 t0, .addImm s1 4]
149
  | .cmp c =>
150
- let b0 := base + ufSize 2
151
- uf L 2 base ++
152
  [.load t1 s1 0, .load t0 s1 4, .movImm t2 1#32, .bcc c t0 t1 (b0 + 5), .movImm t2 0#32,
153
  .store s1 4 t2, .addImm s1 4]
154
  | .select =>
155
- let b0 := base + ufSize 3
156
- uf L 3 base ++
157
  [.load t1 s1 0, .load t0 s1 4, .load t3 s1 8, .beqz t1 (b0 + 5), .movRR t0 t3,
158
  .store s1 8 t0, .addImm s1 8]
159
  | .jmp t => [.jmp (off t)]
160
- | .branch t => uf L 1 base ++ [.load t0 s1 0, .addImm s1 4, .bnez t0 (off t)]
161
  | .call t => ovfR L base ++ [.call (off t)]
162
  | .ret => [.bcc .ne s5 s4 (base + 2), .exitTrap .returnUnderflow, .ret]
163
- | .push r => ovfD L base ++ [.load t0 s2 (4 * (r : Int)), .addImm s1 (-4), .store s1 0 t0]
164
- | .pop r => uf L 1 base ++ [.load t0 s1 0, .addImm s1 4, .store s2 (4 * (r : Int)) t0]
165
  | .dup =>
166
- uf L 1 base ++ ovfD L (base + ufSize 1) ++ [.load t0 s1 0, .addImm s1 (-4), .store s1 0 t0]
167
- | .drop => uf L 1 base ++ [.addImm s1 4]
168
- | .swap => uf L 2 base ++ [.load t0 s1 0, .load t1 s1 4, .store s1 0 t1, .store s1 4 t0]
169
  | .over =>
170
- uf L 2 base ++ ovfD L (base + ufSize 2) ++ [.load t0 s1 4, .addImm s1 (-4), .store s1 0 t0]
171
  | .rot =>
172
- uf L 3 base ++
173
  [.load t0 s1 0, .load t1 s1 4, .load t2 s1 8, .store s1 0 t2, .store s1 4 t0,
174
  .store s1 8 t1]
175
  | .tor =>
176
- uf L 1 base ++ ovfA L (base + ufSize 1) ++
177
  [.load t0 s1 0, .addImm s1 4, .addImm s6 (-4), .store s6 0 t0]
178
  | .fromr =>
179
- emptyA L base ++ ovfD L (base + 3) ++
180
  [.load t0 s6 0, .addImm s6 4, .addImm s1 (-4), .store s1 0 t0]
181
  | .rfetch =>
182
- emptyA L base ++ ovfD L (base + 3) ++ [.load t0 s6 0, .addImm s1 (-4), .store s1 0 t0]
183
  | .halt => [.exitHalt]
184
 
185
- theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (i : WordDialect.Instr 32) :
186
- (lowerInstr L base off i).length = isize i := by
187
- cases i <;> simp [lowerInstr, isize, uf, ufSize, ovfD, ovfR, ovfA, emptyA] <;> (try split) <;> simp
 
 
 
 
 
 
188
 
189
- /-- Prefix sums of instruction sizes: `offs p k` is the RV index of IR instruction `k`.
190
- For `k` past the end it is the index of the final bad-pc stub. -/
191
- def offs (p : Prog 32) (k : Nat) : Nat := ((p.take k).map isize).sum
 
 
 
 
192
 
193
- def lowerGo (L : Layout) (off : Nat → Nat) : Nat → List (WordDialect.Instr 32) → List (Instr Nat)
194
- | _, [] => [.exitTrap .badPc]
195
- | b, i :: is => lowerInstr L b off i ++ lowerGo L off (b + isize i) is
 
196
 
197
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
198
- IR program traps `badPc` exactly as the IR semantics does. -/
199
- def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs p) 0 p
 
200
 
201
  end RV32
202
  end WordDialect
 
1
  import RV32.Isa
2
+ import WordDialect.Depth
3
 
4
  /-!
5
  # RV32.Lower
 
46
  rGap : W -- `4 rcap - 8`: a call has room iff `s5 ≥ s4 - rGap`
47
  aEnd : W -- empty auxiliary stack: `s6 = aEnd`
48
  aLim : W -- `aBase + 4`: the auxiliary stack has room for one more word iff `s6 ≥ aLim`
49
+ /-- A depth certificate (`WordDialect.Depth`): at IR instruction `k` the data stack holds at
50
+ least `cert k` words, so an operand-count guard for at most that many words is left out. -/
51
+ cert : Nat → Nat := fun _ => 0
52
+ /-- An upper bound on the data-stack depth at each IR instruction, and the data stack's
53
+ capacity in words. Where `ub k + 1 ≤ dCap` the data-stack overflow guard is left out. The
54
+ default capacity `0` leaves every guard in. -/
55
+ ub : Nat → Nat := fun _ => 0
56
+ dCap : Nat := 0
57
+
58
+ /-- What the lowering knows at one IR instruction: a lower bound on the data-stack depth, and
59
+ whether one more word is known to fit. -/
60
+ structure Facts where
61
+ lo : Nat := 0
62
+ noOvf : Bool := false
63
+
64
+ /-- The facts at IR instruction `k`. -/
65
+ def Layout.facts (L : Layout) (k : Nat) : Facts :=
66
+ { lo := L.cert k, noOvf := decide (L.ub k + 1 ≤ L.dCap) }
67
 
68
  /-- Stack-underflow guard for `k` operands: continue when `s1 ≤ dEnd - 4k`. -/
69
  def uf (L : Layout) (k base : Nat) : List (Instr Nat) :=
 
73
 
74
  def ufSize (k : Nat) : Nat := if k = 0 then 0 else 3
75
 
76
+ /-- The operand count an instruction popping `k` words still has to check when the data stack is
77
+ known to hold at least `g.lo` words: none if `k ≤ g.lo`. -/
78
+ def need (g : Facts) (k : Nat) : Nat := if k ≤ g.lo then 0 else k
79
+
80
+ theorem need_le (g : Facts) (k : Nat) : need g k ≤ k := by unfold need; split <;> omega
81
+
82
+ theorem need_of_lt {g : Facts} {k : Nat} (h : g.lo < k) : need g k = k := by
83
+ unfold need; split <;> omega
84
+
85
  /-- Data-stack overflow guard: exit 6 unless one more word fits. -/
86
  def ovfD (L : Layout) (base : Nat) : List (Instr Nat) :=
87
  [.movImm t0 L.dLim, .bcc .uge s1 t0 (base + 3), .exitOvf]
88
 
89
+ /-- The data-stack overflow guard where it is needed: none when the facts say one more word fits. -/
90
+ def ovf (L : Layout) (g : Facts) (base : Nat) : List (Instr Nat) :=
91
+ if g.noOvf then [] else ovfD L base
92
+
93
+ def ovfSize (g : Facts) : Nat := if g.noOvf then 0 else 3
94
+
95
  /-- Return-stack overflow guard: exit 6 unless a call has room on the return stack. -/
96
  def ovfR (L : Layout) (base : Nat) : List (Instr Nat) :=
97
  [.movRR t0 s4, .movImm t1 L.rGap, .sub t0 t1, .bcc .uge s5 t0 (base + 5), .exitOvf]
 
105
  [.movImm t0 L.aEnd, .bcc .ne s6 t0 (base + 3), .exitTrap .returnUnderflow]
106
 
107
  /-- Code size of one IR instruction. -/
108
+ def isize (g : Facts) : WordDialect.Instr 32 → Nat
109
+ | .word _ | .ptr _ => ovfSize g + 3
110
+ | .load => ufSize (need g 1) + 8
111
+ | .store => ufSize (need g 2) + 9
112
+ | .add | .sub | .mul | .and | .or | .xor => ufSize (need g 2) + 5
113
+ | .div | .sdiv => ufSize (need g 2) + 7
114
+ | .not => ufSize (need g 1) + 3
115
+ | .shl | .shr => ufSize (need g 2) + 8
116
+ | .rotl | .rotr => ufSize (need g 2) + 9
117
+ | .cmp _ => ufSize (need g 2) + 7
118
+ | .select => ufSize (need g 3) + 7
119
  | .jmp _ => 1
120
+ | .branch _ => ufSize (need g 1) + 3
121
  | .call _ => 6
122
  | .ret => 3
123
+ | .push _ => ovfSize g + 3
124
+ | .pop _ => ufSize (need g 1) + 3
125
+ | .dup => ufSize (need g 1) + ovfSize g + 3
126
+ | .drop => ufSize (need g 1) + 1
127
+ | .swap => ufSize (need g 2) + 4
128
+ | .over => ufSize (need g 2) + ovfSize g + 3
129
+ | .rot => ufSize (need g 3) + 6
130
+ | .tor => ufSize (need g 1) + 7
131
+ | .fromr => ovfSize g + 7
132
+ | .rfetch => ovfSize g + 6
133
  | .halt => 1
134
 
135
  /-- Code for one IR instruction placed at RV index `base`; `off t` is the RV index of IR
136
  instruction `t` (clamped to the bad-pc stub for out-of-range targets). -/
137
+ def lowerInstr (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts) :
138
+ WordDialect.Instr 32 → List (Instr Nat)
139
+ | .word w => ovf L g base ++ [.movImm t0 w, .addImm s1 (-4), .store s1 0 t0]
140
+ | .ptr p => ovf L g base ++ [.movImm t0 p.toWord, .addImm s1 (-4), .store s1 0 t0]
141
  | .load =>
142
+ let b0 := base + ufSize (need g 1)
143
+ uf L (need g 1) base ++
144
  [.load t0 s1 0, .movImm t1 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t1 (b0 + 4),
145
  .exitTrap .badAddress, .shlImm t0 2, .add t0 s3, .load t0 t0 0, .store s1 0 t0]
146
  | .store =>
147
+ let b0 := base + ufSize (need g 2)
148
+ uf L (need g 2) base ++
149
  [.load t0 s1 0, .load t1 s1 4, .movImm t2 (BitVec.ofNat 32 L.memSize), .bcc .ult t0 t2 (b0 + 5),
150
  .exitTrap .badAddress, .shlImm t0 2, .add t0 s3, .store t0 0 t1, .addImm s1 8]
151
+ | .add => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .add t0 t1, .store s1 4 t0, .addImm s1 4]
152
+ | .sub => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .sub t0 t1, .store s1 4 t0, .addImm s1 4]
153
+ | .mul => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .mul t0 t1, .store s1 4 t0, .addImm s1 4]
154
+ | .and => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .and t0 t1, .store s1 4 t0, .addImm s1 4]
155
+ | .or => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .or t0 t1, .store s1 4 t0, .addImm s1 4]
156
+ | .xor => uf L (need g 2) base ++ [.load t1 s1 0, .load t0 s1 4, .xor t0 t1, .store s1 4 t0, .addImm s1 4]
157
  | .div =>
158
+ let b0 := base + ufSize (need g 2)
159
+ uf L (need g 2) base ++
160
  [.load t1 s1 0, .load t0 s1 4, .bnez t1 (b0 + 4), .exitTrap .divideByZero, .divu t0 t0 t1,
161
  .store s1 4 t0, .addImm s1 4]
162
  | .sdiv =>
163
+ let b0 := base + ufSize (need g 2)
164
+ uf L (need g 2) base ++
165
  [.load t1 s1 0, .load t0 s1 4, .bnez t1 (b0 + 4), .exitTrap .divideByZero, .div t0 t0 t1,
166
  .store s1 4 t0, .addImm s1 4]
167
+ | .not => uf L (need g 1) base ++ [.load t0 s1 0, .not t0, .store s1 0 t0]
168
  | .shl =>
169
+ uf L (need g 2) base ++
170
  [.load t1 s1 0, .load t0 s1 4, .sll t0 t1, .sltiu t2 t1 32, .neg t2, .and t0 t2,
171
  .store s1 4 t0, .addImm s1 4]
172
  | .shr =>
173
+ uf L (need g 2) base ++
174
  [.load t1 s1 0, .load t0 s1 4, .srl t0 t1, .sltiu t2 t1 32, .neg t2, .and t0 t2,
175
  .store s1 4 t0, .addImm s1 4]
176
  | .rotl =>
177
+ uf L (need g 2) base ++
178
  [.load t1 s1 0, .load t0 s1 4, .movRR t2 t0, .sll t0 t1, .neg t1, .srl t2 t1, .or t0 t2,
179
  .store s1 4 t0, .addImm s1 4]
180
  | .rotr =>
181
+ uf L (need g 2) base ++
182
  [.load t1 s1 0, .load t0 s1 4, .movRR t2 t0, .srl t0 t1, .neg t1, .sll t2 t1, .or t0 t2,
183
  .store s1 4 t0, .addImm s1 4]
184
  | .cmp c =>
185
+ let b0 := base + ufSize (need g 2)
186
+ uf L (need g 2) base ++
187
  [.load t1 s1 0, .load t0 s1 4, .movImm t2 1#32, .bcc c t0 t1 (b0 + 5), .movImm t2 0#32,
188
  .store s1 4 t2, .addImm s1 4]
189
  | .select =>
190
+ let b0 := base + ufSize (need g 3)
191
+ uf L (need g 3) base ++
192
  [.load t1 s1 0, .load t0 s1 4, .load t3 s1 8, .beqz t1 (b0 + 5), .movRR t0 t3,
193
  .store s1 8 t0, .addImm s1 8]
194
  | .jmp t => [.jmp (off t)]
195
+ | .branch t => uf L (need g 1) base ++ [.load t0 s1 0, .addImm s1 4, .bnez t0 (off t)]
196
  | .call t => ovfR L base ++ [.call (off t)]
197
  | .ret => [.bcc .ne s5 s4 (base + 2), .exitTrap .returnUnderflow, .ret]
198
+ | .push r => ovf L g base ++ [.load t0 s2 (4 * (r : Int)), .addImm s1 (-4), .store s1 0 t0]
199
+ | .pop r => uf L (need g 1) base ++ [.load t0 s1 0, .addImm s1 4, .store s2 (4 * (r : Int)) t0]
200
  | .dup =>
201
+ uf L (need g 1) base ++ ovf L g (base + ufSize (need g 1)) ++ [.load t0 s1 0, .addImm s1 (-4), .store s1 0 t0]
202
+ | .drop => uf L (need g 1) base ++ [.addImm s1 4]
203
+ | .swap => uf L (need g 2) base ++ [.load t0 s1 0, .load t1 s1 4, .store s1 0 t1, .store s1 4 t0]
204
  | .over =>
205
+ uf L (need g 2) base ++ ovf L g (base + ufSize (need g 2)) ++ [.load t0 s1 4, .addImm s1 (-4), .store s1 0 t0]
206
  | .rot =>
207
+ uf L (need g 3) base ++
208
  [.load t0 s1 0, .load t1 s1 4, .load t2 s1 8, .store s1 0 t2, .store s1 4 t0,
209
  .store s1 8 t1]
210
  | .tor =>
211
+ uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
212
  [.load t0 s1 0, .addImm s1 4, .addImm s6 (-4), .store s6 0 t0]
213
  | .fromr =>
214
+ emptyA L base ++ ovf L g (base + 3) ++
215
  [.load t0 s6 0, .addImm s6 4, .addImm s1 (-4), .store s1 0 t0]
216
  | .rfetch =>
217
+ emptyA L base ++ ovf L g (base + 3) ++ [.load t0 s6 0, .addImm s1 (-4), .store s1 0 t0]
218
  | .halt => [.exitHalt]
219
 
220
+ theorem uf_length (L : Layout) (k base : Nat) : (uf L k base).length = ufSize k := by
221
+ unfold uf ufSize; split <;> simp
222
+
223
+ theorem ovf_length (L : Layout) (g : Facts) (base : Nat) : (ovf L g base).length = ovfSize g := by
224
+ unfold ovf ovfSize; split <;> simp [ovfD]
225
+
226
+ theorem lowerInstr_length (L : Layout) (base : Nat) (off : Nat → Nat) (g : Facts)
227
+ (i : WordDialect.Instr 32) : (lowerInstr L base off g i).length = isize g i := by
228
+ cases i <;> simp [lowerInstr, isize, uf_length, ovf_length, ovfR, ovfA, emptyA] <;> omega
229
 
230
+ /-- Prefix sums of instruction sizes: `offs cf p k` is the code index of IR instruction `k`,
231
+ where `cf j` are the facts at instruction `j` (its guards depend on them). For `k` past
232
+ the end it is the index of the final bad-pc stub. -/
233
+ def offs (cf : Nat → Facts) : Prog 32 → Nat → Nat
234
+ | _, 0 => 0
235
+ | [], _ + 1 => 0
236
+ | i :: is, k + 1 => isize (cf 0) i + offs (fun j => cf (j + 1)) is k
237
 
238
+ def lowerGo (L : Layout) (off : Nat → Nat) :
239
+ (Nat → Facts) → Nat → List (WordDialect.Instr 32) → List (Instr Nat)
240
+ | _, _, [] => [.exitTrap .badPc]
241
+ | cf, b, i :: is => lowerInstr L b off (cf 0) i ++ lowerGo L off (fun j => cf (j + 1)) (b + isize (cf 0) i) is
242
 
243
  /-- The whole program; the last instruction is the bad-pc stub, so jumping past the end of the
244
+ IR program traps `badPc` exactly as the IR semantics does. Instruction `k` leaves out the
245
+ guards that `L.facts k` makes redundant. -/
246
+ def lowerProg (L : Layout) (p : Prog 32) : List (Instr Nat) := lowerGo L (offs L.facts p) L.facts 0 p
247
 
248
  end RV32
249
  end WordDialect
backend/rv32/RV32/Rel.lean CHANGED
@@ -33,6 +33,17 @@ structure Cfg where
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  structure Geom (c : Cfg) : Prop where
38
  dEnd_lt : c.dEnd < 2 ^ 32
@@ -95,7 +106,7 @@ def MemRel (c : Cfg) (mem : Memory 32) (m : Memory 32) : Prop :=
95
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
96
 
97
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
98
- ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs p a))
99
 
100
  /-- The RISC-V memory's addressable set covers every region. -/
101
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
@@ -125,7 +136,7 @@ structure Rel0 (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop where
125
 
126
  /-- Full relation: everything in `Rel0`, and the RISC-V pc is the start of the IR pc's code. -/
127
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
128
- Rel0 c p s x ∧ x.pc = offs p s.pc
129
 
130
  /-- `Rel0` does not look at scratch registers or the pc. -/
131
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
 
33
  rcap : Nat
34
  aEnd : Nat
35
  aBase : Nat
36
+ /-- The depth certificate the code was lowered with (`Layout.cert`). -/
37
+ cert : Nat → Nat := fun _ => 0
38
+ /-- The upper bound on the data-stack depth the code was lowered with (`Layout.ub`). -/
39
+ ub : Nat → Nat := fun _ => 2 ^ 32
40
+
41
+ /-- The data stack's capacity in words. -/
42
+ def Cfg.dCap (c : Cfg) : Nat := (c.dEnd - c.dBase) / 4
43
+
44
+ /-- The facts the code was lowered with (`Layout.facts`). -/
45
+ def Cfg.facts (c : Cfg) (k : Nat) : Facts :=
46
+ { lo := c.cert k, noOvf := decide (c.ub k + 1 ≤ c.dCap) }
47
 
48
  structure Geom (c : Cfg) : Prop where
49
  dEnd_lt : c.dEnd < 2 ^ 32
 
106
  ∀ a, a < c.M → mem.read? (ofN (c.mb + 4 * a)) = some (m.cell (ofN a))
107
 
108
  def RsRel (c : Cfg) (p : Prog 32) (mem : Memory 32) (rs : List Nat) : Prop :=
109
+ ∀ i a, rs[i]? = some a → mem.read? (ofN (c.sp0 - 4 * rs.length + 4 * i)) = some (ofN (offs c.facts p a))
110
 
111
  /-- The RISC-V memory's addressable set covers every region. -/
112
  def RegionsValid (c : Cfg) (v : W → Bool) : Prop :=
 
136
 
137
  /-- Full relation: everything in `Rel0`, and the RISC-V pc is the start of the IR pc's code. -/
138
  def Rel (c : Cfg) (p : Prog 32) (s : State 32) (x : M) : Prop :=
139
+ Rel0 c p s x ∧ x.pc = offs c.facts p s.pc
140
 
141
  /-- `Rel0` does not look at scratch registers or the pc. -/
142
  theorem Rel0.congr {c : Cfg} {p : Prog 32} {s : State 32} {x x' : M} (h : Rel0 c p s x)
backend/rv32/RV32/Run.lean CHANGED
@@ -63,11 +63,10 @@ theorem rstep_of_fetch {code : List (Instr Nat)} {m : M} {i : Instr Nat}
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
- theorem offs_cons (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
- offs (i :: is) (k + 1) = isize i + offs is k := by
68
- simp [offs, List.take_succ_cons]
69
 
70
- theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by simp [offs]
71
 
72
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
73
  induction seg generalizing pre with
@@ -77,66 +76,70 @@ theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) p
77
  have := ih (pre ++ [i])
78
  simpa [List.append_assoc] using this
79
 
80
- /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs ps k`. -/
 
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
- ∀ (ps : Prog 32) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps k)
85
- (lowerInstr L (pre.length + offs ps k) off i) := by
86
  intro ps
87
  induction ps with
88
- | nil => intro pre k i h; simp at h
89
  | cons j js ih =>
90
- intro pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
- have := rat_embed pre (lowerInstr L pre.length off j) (lowerGo L off (pre.length + isize j) js)
 
96
  simpa [List.append_assoc] using this
97
  | succ k =>
98
  simp only [List.getElem?_cons_succ] at h
99
- have := ih (pre ++ lowerInstr L pre.length off j) k i h
100
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
101
  simp [lowerInstr_length]
102
  rw [hl] at this
103
  simp only [lowerGo, offs_cons]
104
- have e : pre.length + (isize j + offs js k) = pre.length + isize j + offs js k := by omega
 
105
  rw [e]
106
  simpa [List.append_assoc] using this
107
 
108
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
109
  (h : p[k]? = some i) :
110
- RAt (lowerProg L p) (offs p k) (lowerInstr L (offs p k) (offs p) i) := by
111
- have := lowerGo_at L (offs p) p [] k i h
112
  simpa [lowerProg] using this
113
 
114
- /-- The final stub (bad-pc trap) sits at `offs p p.length`. -/
115
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
116
- ∀ (ps : Prog 32) (pre : List (Instr Nat)),
117
- RAt (pre ++ lowerGo L off pre.length ps) (pre.length + offs ps ps.length) [.exitTrap .badPc] := by
 
118
  intro ps
119
  induction ps with
120
  | nil =>
121
- intro pre
122
- simp only [lowerGo, List.length_nil, offs, List.take_nil, List.map_nil, List.sum_nil,
123
- Nat.add_zero]
124
  have := rat_embed pre [.exitTrap .badPc] []
125
  simpa using this
126
  | cons j js ih =>
127
- intro pre
128
- have := ih (pre ++ lowerInstr L pre.length off j)
129
- have hl : (pre ++ lowerInstr L pre.length off j).length = pre.length + isize j := by
130
  simp [lowerInstr_length]
131
  rw [hl] at this
132
  simp only [lowerGo, List.length_cons, offs_cons]
133
- have e : pre.length + (isize j + offs js js.length) = pre.length + isize j + offs js js.length := by omega
 
134
  rw [e]
135
  simpa [List.append_assoc] using this
136
 
137
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
138
- RAt (lowerProg L p) (offs p p.length) [.exitTrap .badPc] := by
139
- have := lowerGo_stub L (offs p) p []
140
  simpa [lowerProg] using this
141
 
142
  end RV32
 
63
  simp [step, h]
64
 
65
  /-- Prefix sums: `offs` of a cons. -/
66
+ theorem offs_cons (cf : Nat → Facts) (i : WordDialect.Instr 32) (is : Prog 32) (k : Nat) :
67
+ offs cf (i :: is) (k + 1) = isize (cf 0) i + offs (fun j => cf (j + 1)) is k := rfl
 
68
 
69
+ theorem offs_zero (cf : Nat → Facts) (p : Prog 32) : offs cf p 0 = 0 := by cases p <;> rfl
70
 
71
  theorem rat_embed (pre seg post : List (Instr Nat)) : RAt (pre ++ seg ++ post) pre.length seg := by
72
  induction seg generalizing pre with
 
76
  have := ih (pre ++ [i])
77
  simpa [List.append_assoc] using this
78
 
79
+ /-- Where the lowered code of IR instruction `k` sits: at index `pre.length + offs cf ps k`, with
80
+ the guards for the facts `cf k`. -/
81
  theorem lowerGo_at (L : Layout) (off : Nat → Nat) :
82
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)) (k : Nat) (i : WordDialect.Instr 32),
83
  ps[k]? = some i →
84
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps k)
85
+ (lowerInstr L (pre.length + offs cf ps k) off (cf k) i) := by
86
  intro ps
87
  induction ps with
88
+ | nil => intro cf pre k i h; simp at h
89
  | cons j js ih =>
90
+ intro cf pre k i h
91
  cases k with
92
  | zero =>
93
  simp at h; subst h
94
  simp only [offs_zero, Nat.add_zero, lowerGo]
95
+ have := rat_embed pre (lowerInstr L pre.length off (cf 0) j)
96
+ (lowerGo L off (fun j => cf (j + 1)) (pre.length + isize (cf 0) j) js)
97
  simpa [List.append_assoc] using this
98
  | succ k =>
99
  simp only [List.getElem?_cons_succ] at h
100
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j) k i h
101
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
102
  simp [lowerInstr_length]
103
  rw [hl] at this
104
  simp only [lowerGo, offs_cons]
105
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js k) =
106
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js k := by omega
107
  rw [e]
108
  simpa [List.append_assoc] using this
109
 
110
  theorem lowerProg_at (L : Layout) (p : Prog 32) (k : Nat) (i : WordDialect.Instr 32)
111
  (h : p[k]? = some i) :
112
+ RAt (lowerProg L p) (offs L.facts p k) (lowerInstr L (offs L.facts p k) (offs L.facts p) (L.facts k) i) := by
113
+ have := lowerGo_at L (offs L.facts p) p L.facts [] k i h
114
  simpa [lowerProg] using this
115
 
116
+ /-- The final stub (bad-pc trap) sits at `offs cf p p.length`. -/
117
  theorem lowerGo_stub (L : Layout) (off : Nat → Nat) :
118
+ ∀ (ps : Prog 32) (cf : Nat → Facts) (pre : List (Instr Nat)),
119
+ RAt (pre ++ lowerGo L off cf pre.length ps) (pre.length + offs cf ps ps.length)
120
+ [.exitTrap .badPc] := by
121
  intro ps
122
  induction ps with
123
  | nil =>
124
+ intro cf pre
125
+ simp only [lowerGo, List.length_nil, offs_zero, Nat.add_zero]
 
126
  have := rat_embed pre [.exitTrap .badPc] []
127
  simpa using this
128
  | cons j js ih =>
129
+ intro cf pre
130
+ have := ih (fun j => cf (j + 1)) (pre ++ lowerInstr L pre.length off (cf 0) j)
131
+ have hl : (pre ++ lowerInstr L pre.length off (cf 0) j).length = pre.length + isize (cf 0) j := by
132
  simp [lowerInstr_length]
133
  rw [hl] at this
134
  simp only [lowerGo, List.length_cons, offs_cons]
135
+ have e : pre.length + (isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length) =
136
+ pre.length + isize (cf 0) j + offs (fun j => cf (j + 1)) js js.length := by omega
137
  rw [e]
138
  simpa [List.append_assoc] using this
139
 
140
  theorem lowerProg_stub (L : Layout) (p : Prog 32) :
141
+ RAt (lowerProg L p) (offs L.facts p p.length) [.exitTrap .badPc] := by
142
+ have := lowerGo_stub L (offs L.facts p) p L.facts []
143
  simpa [lowerProg] using this
144
 
145
  end RV32
backend/rv32/RV32/SimAux.lean CHANGED
@@ -203,7 +203,7 @@ end Steps
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
- {base : Nat}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
@@ -305,32 +305,32 @@ end Guards
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
- {L : Layout} {base : Nat} {off : Nat → Nat}
309
 
310
  /-- Placement of the `tor` code. -/
311
- theorem xat_tor (hat : RAt code base (lowerInstr L base off .tor)) :
312
- RAt code base (uf L 1 base) ∧ RAt code (base + 3) (ovfA L (base + 3)) ∧
313
- RAt code (base + 6) [.load t0 Reg.s1 0, .addImm Reg.s1 4, .addImm Reg.s6 (-4),
314
  .store Reg.s6 0 t0] := by
315
- have hat' : RAt code base (uf L 1 base ++ ovfA L (base + 3) ++
316
  [.load t0 Reg.s1 0, .addImm Reg.s1 4, .addImm Reg.s6 (-4), .store Reg.s6 0 t0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
- have hufl : (uf L 1 base).length = 3 := by simp [uf]
320
  rw [hufl] at hato
321
- have hl : (uf L 1 base ++ ovfA L (base + 3)).length = 6 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
- x'.pc = base + isize (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
@@ -343,39 +343,40 @@ theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
- by simp [isize, ufSize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
- obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
- /-- Placement of `emptyA L base ++ ovfD L (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
- (hat : RAt code base (emptyA L base ++ ovfD L (base + 3) ++ rest)) :
359
- RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovfD L (base + 3)) ∧
360
- RAt code (base + 6) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
- have hl : (emptyA L base ++ ovfD L (base + 3)).length = 6 := rfl
366
- rw [hl] at hatr
 
367
  exact ⟨hate, hato, hatr⟩
368
 
369
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
370
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
371
  {a : W} {as : List W} (hd : s.astack = a :: as)
372
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
373
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
374
- x'.pc = base + isize (.fromr : WordDialect.Instr 32) := by
375
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
376
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
377
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
378
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
379
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := t0)
380
  (by simp) (fetch_cast f0 (by omega))
381
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
@@ -386,30 +387,30 @@ theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = o
386
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
387
 
388
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
389
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr)) (he : s.astack = []) :
390
  RExec code x (.trapped .returnUnderflow) :=
391
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load t0 Reg.s6 0,
392
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat).1
393
 
394
- theorem sim_fromr_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
395
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .fromr))
396
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
397
  RExec code x .overflow := by
398
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
399
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
400
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
401
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
402
 
403
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
404
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
405
  {a : W} {as : List W} (hd : s.astack = a :: as)
406
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
407
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
408
- x'.pc = base + isize (.rfetch : WordDialect.Instr 32) := by
409
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
410
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
411
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
412
- obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfD_pass hg hr1 hLd hfit hpc1 hato
413
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := t0)
414
  (by simp) (fetch_cast f0 (by omega))
415
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 t0 (by decide) hfit
@@ -418,19 +419,19 @@ theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim =
418
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
419
 
420
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
421
- (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch)) (he : s.astack = []) :
422
  RExec code x (.trapped .returnUnderflow) :=
423
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load t0 Reg.s6 0,
424
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat).1
425
 
426
- theorem sim_rfetch_ovf (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
427
- (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off .rfetch))
428
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
429
  RExec code x .overflow := by
430
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
431
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
432
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
433
- exact RExec.of_steps hs1 (ovfD_trap hg hr1 hLd h hpc1 hato)
434
 
435
  end Ops
436
 
 
203
  section Guards
204
 
205
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)} {L : Layout}
206
+ {base : Nat} {g : Facts}
207
 
208
  /-- The auxiliary-stack guard's comparison, in terms of its depth. -/
209
  theorem ovfA_cond (hg : Geom c) (hs : Rel0 c p s x) (hLal : L.aLim = ofN (c.aBase + 4)) :
 
305
  section Ops
306
 
307
  variable {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
308
+ {L : Layout} {base : Nat} {off : Nat → Nat} {g : Facts}
309
 
310
  /-- Placement of the `tor` code. -/
311
+ theorem xat_tor (hat : RAt code base (lowerInstr L base off g .tor)) :
312
+ RAt code base (uf L (need g 1) base) ∧ RAt code (base + ufSize (need g 1)) (ovfA L (base + ufSize (need g 1))) ∧
313
+ RAt code (base + ufSize (need g 1) + 3) [.load t0 Reg.s1 0, .addImm Reg.s1 4, .addImm Reg.s6 (-4),
314
  .store Reg.s6 0 t0] := by
315
+ have hat' : RAt code base (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1)) ++
316
  [.load t0 Reg.s1 0, .addImm Reg.s1 4, .addImm Reg.s6 (-4), .store Reg.s6 0 t0]) := hat
317
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat'
318
  obtain ⟨hatuf, hato⟩ := rat_append.mp hatuo
319
+ have hufl := uf_length L (need g 1) base
320
  rw [hufl] at hato
321
+ have hl : (uf L (need g 1) base ++ ovfA L (base + ufSize (need g 1))).length = ufSize (need g 1) + 3 := by simp [hufl, ovfA]
322
  rw [hl] at hatr
323
  exact ⟨hatuf, hato, hatr⟩
324
 
325
  theorem sim_tor_ok (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
326
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
327
  {a : W} {d : List W} (hd : s.dstack = a :: d)
328
  (hfit : c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
329
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := d, astack := a :: s.astack } x' ∧
330
+ x'.pc = base + isize g (.tor : WordDialect.Instr 32) := by
331
  obtain ⟨hatuf, hato, f0, f1, f2, f3, _⟩ := xat_tor hat
332
  have hk : 1 ≤ s.dstack.length := by simp [hd]
333
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
334
  obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfA_pass hg hr1 hLal hfit hpc1 hato
335
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_step (code := code) hr1' (j := 0) (v := a)
336
  (by simp [hd]) (rd := t0) (by simp) (disp := 0) (by simp) (fetch_cast f0 (by omega))
 
343
  ⟨fetch_cast f2 (by omega), fetch_cast f3 (by omega), trivial⟩
344
  rw [hax3] at hr4
345
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4,
346
+ by simp [isize]; omega⟩
347
 
348
  theorem sim_tor_ovf (hg : Geom c) (hL : L.dEnd = ofN c.dEnd) (hLal : L.aLim = ofN (c.aBase + 4))
349
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .tor))
350
  (hk : 1 ≤ s.dstack.length) (h : ¬ c.aBase + 4 * (s.astack.length + 1) ≤ c.aEnd) :
351
  RExec code x .overflow := by
352
  obtain ⟨hatuf, hato, _⟩ := xat_tor hat
353
+ obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) hk hpc hatuf
354
  exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
355
 
356
+ /-- Placement of `emptyA L base ++ ovf L g (base + 3) ++ rest`. -/
357
  theorem xat_take {rest : List (Instr Nat)}
358
+ (hat : RAt code base (emptyA L base ++ ovf L g (base + 3) ++ rest)) :
359
+ RAt code base (emptyA L base) ∧ RAt code (base + 3) (ovf L g (base + 3)) ∧
360
+ RAt code (base + 3 + ovfSize g) rest := by
361
  obtain ⟨hatuo, hatr⟩ := rat_append.mp hat
362
  obtain ⟨hate, hato⟩ := rat_append.mp hatuo
363
  have hel : (emptyA L base).length = 3 := rfl
364
  rw [hel] at hato
365
+ have hl : (emptyA L base ++ ovf L g (base + 3)).length = 3 + ovfSize g := by
366
+ simp [ovf_length, emptyA]; omega
367
+ rw [hl, ← Nat.add_assoc] at hatr
368
  exact ⟨hate, hato, hatr⟩
369
 
370
  theorem sim_fromr_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
371
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
372
  {a : W} {as : List W} (hd : s.astack = a :: as)
373
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
374
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack, astack := as } x' ∧
375
+ x'.pc = base + isize g (.fromr : WordDialect.Instr 32) := by
376
  obtain ⟨hate, hato, f0, f1, f2, f3, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
377
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
378
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
379
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
380
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := t0)
381
  (by simp) (fetch_cast f0 (by omega))
382
  obtain ⟨x3, hs3, hr3, hpc3, ho3⟩ := aux_drop (code := code) hr2 hd (fetch_cast f1 (by omega))
 
387
  exact ⟨x4, (((hs1.trans hs1').trans hs2).trans hs3).trans hs4, hr4, by simp [isize]; omega⟩
388
 
389
  theorem sim_fromr_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
390
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr)) (he : s.astack = []) :
391
  RExec code x (.trapped .returnUnderflow) :=
392
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load t0 Reg.s6 0,
393
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat).1
394
 
395
+ theorem sim_fromr_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
396
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .fromr))
397
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
398
  RExec code x .overflow := by
399
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
400
  .addImm Reg.s6 4, .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
401
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
402
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
403
 
404
  theorem sim_rfetch_ok (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
405
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
406
  {a : W} {as : List W} (hd : s.astack = a :: as)
407
  (hfit : c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
408
  ∃ x', RSteps code x x' ∧ Rel0 c p { s with dstack := a :: s.dstack } x' ∧
409
+ x'.pc = base + isize g (.rfetch : WordDialect.Instr 32) := by
410
  obtain ⟨hate, hato, f0, f1, f2, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
411
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
412
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa (by simp [hd]) hpc hate
413
+ obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ := ovfG_pass hg hr1 hLd hfit hpc1 hato
414
  obtain ⟨x2, hs2, hr2, hpc2, hv2, _, _⟩ := ld_aux_step (code := code) hr1' hd (rd := t0)
415
  (by simp) (fetch_cast f0 (by omega))
416
  obtain ⟨x3, hs3, hr3, hpc3, _⟩ := push_pair hg hr2 t0 (by decide) hfit
 
419
  exact ⟨x3, ((hs1.trans hs1').trans hs2).trans hs3, hr3, by simp [isize]; omega⟩
420
 
421
  theorem sim_rfetch_trap (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hs : Rel0 c p s x)
422
+ (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch)) (he : s.astack = []) :
423
  RExec code x (.trapped .returnUnderflow) :=
424
  emptyA_trap hg hs hLa he hpc (xat_take (L := L) (rest := [.load t0 Reg.s6 0,
425
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat).1
426
 
427
+ theorem sim_rfetch_ovf (hn : g.noOvf = false) (hg : Geom c) (hLa : L.aEnd = ofN c.aEnd) (hLd : L.dLim = ofN (c.dBase + 4))
428
+ (hs : Rel0 c p s x) (hpc : x.pc = base) (hat : RAt code base (lowerInstr L base off g .rfetch))
429
  (hne : s.astack ≠ []) (h : ¬ c.dBase + 4 * (s.dstack.length + 1) ≤ c.dEnd) :
430
  RExec code x .overflow := by
431
  obtain ⟨hate, hato, _⟩ := xat_take (L := L) (rest := [.load t0 Reg.s6 0,
432
  .addImm Reg.s1 (-4), .store Reg.s1 0 t0]) hat
433
  obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := emptyA_pass hg hs hLa hne hpc hate
434
+ exact RExec.of_steps hs1 (ovfG_trap hn hg hr1 hLd h hpc1 hato)
435
 
436
  end Ops
437