Sync from GitHub at 25c8330: hardware-in-the-loop rig, SAM D21 board, guard elimination on RV32/Cortex-M3
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .github/workflows/hardware.yml +33 -0
- .github/workflows/lean.yml +32 -1
- CHANGELOG.md +59 -0
- NEXT_STEPS.md +34 -6
- README.md +0 -0
- backend/common/Harness32.lean +130 -0
- backend/cortexm/CM/Boot.lean +4 -4
- backend/cortexm/CM/Correct.lean +54 -25
- backend/cortexm/CM/Emit.lean +67 -21
- backend/cortexm/CM/Guard.lean +51 -9
- backend/cortexm/CM/Init.lean +30 -22
- backend/cortexm/CM/Isa.lean +1 -1
- backend/cortexm/CM/Lower.lean +118 -71
- backend/cortexm/CM/Rel.lean +13 -2
- backend/cortexm/CM/Run.lean +31 -28
- backend/cortexm/CM/SimAux.lean +35 -34
- backend/cortexm/CM/SimBin.lean +9 -9
- backend/cortexm/CM/SimCtl.lean +29 -24
- backend/cortexm/CM/SimDiv.lean +43 -43
- backend/cortexm/CM/SimMemOps.lean +42 -42
- backend/cortexm/CM/SimOps.lean +45 -45
- backend/cortexm/CM/SimStack.lean +77 -75
- backend/cortexm/CM/SimStep.lean +35 -18
- backend/cortexm/CMMain.lean +89 -38
- backend/cortexm0/CM0/Boot.lean +4 -4
- backend/cortexm0/CM0/Correct.lean +54 -25
- backend/cortexm0/CM0/Emit.lean +135 -21
- backend/cortexm0/CM0/Guard.lean +51 -9
- backend/cortexm0/CM0/Init.lean +30 -22
- backend/cortexm0/CM0/Isa.lean +1 -1
- backend/cortexm0/CM0/Lower.lean +125 -74
- backend/cortexm0/CM0/Rel.lean +13 -2
- backend/cortexm0/CM0/Run.lean +31 -28
- backend/cortexm0/CM0/SimAux.lean +35 -34
- backend/cortexm0/CM0/SimBin.lean +9 -9
- backend/cortexm0/CM0/SimCtl.lean +29 -24
- backend/cortexm0/CM0/SimDiv.lean +51 -51
- backend/cortexm0/CM0/SimMemOps.lean +42 -42
- backend/cortexm0/CM0/SimOps.lean +45 -45
- backend/cortexm0/CM0/SimStack.lean +77 -75
- backend/cortexm0/CM0/SimStep.lean +35 -18
- backend/cortexm0/CM0Main.lean +123 -35
- backend/rv32/RV32/Correct.lean +54 -25
- backend/rv32/RV32/Emit.lean +12 -1
- backend/rv32/RV32/Guard.lean +51 -9
- backend/rv32/RV32/Init.lean +30 -22
- backend/rv32/RV32/Lower.lean +117 -70
- backend/rv32/RV32/Rel.lean +13 -2
- backend/rv32/RV32/Run.lean +31 -28
- 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,
|
| 67 |
-
|
| 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
|
| 70 |
-
uses
|
| 71 |
-
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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)
|
| 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) :
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
| 55 |
-
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 29 |
-
* implements `exitTrap t` as
|
| 30 |
status 6.
|
| 31 |
|
| 32 |
-
|
| 33 |
-
the
|
| 34 |
-
|
|
|
|
| 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`),
|
|
|
|
| 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 |
-
|
| 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 |
-
/--
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 231 |
-
"\
|
|
|
|
|
|
|
| 232 |
|
| 233 |
-
/--
|
| 234 |
-
|
| 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 .
|
| 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
|
| 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 |
-
/--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
|
| 67 |
-
{L : Layout} {base
|
| 68 |
-
(
|
| 69 |
-
(hat : RAt code base (uf L
|
| 70 |
-
|
|
|
|
|
|
|
| 71 |
obtain ⟨h1, h2, h3, _⟩ := hat
|
| 72 |
-
let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 *
|
| 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
|
| 77 |
-
have h : ¬
|
| 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 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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) :
|
| 92 |
-
|
| 93 |
-
|
| 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)
|
|
|
|
| 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
|
|
|
|
| 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
|
| 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 _ =>
|
| 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 _ =>
|
| 95 |
-
| .pop _ => ufSize 1 + 3
|
| 96 |
-
| .dup => ufSize 1 +
|
| 97 |
-
| .drop => ufSize 1 + 1
|
| 98 |
-
| .swap => ufSize 2 + 4
|
| 99 |
-
| .over => ufSize 2 +
|
| 100 |
-
| .rot => ufSize 3 + 6
|
| 101 |
-
| .tor => ufSize 1 + 7
|
| 102 |
-
| .fromr =>
|
| 103 |
-
| .rfetch =>
|
| 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)
|
| 109 |
-
|
| 110 |
-
| .
|
|
|
|
| 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 =>
|
| 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 ++
|
| 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 ++
|
| 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 ++
|
| 183 |
[.load r0 r9 0, .addImm r9 4, .addImm r4 (-4), .store r4 0 r0]
|
| 184 |
| .rfetch =>
|
| 185 |
-
emptyA L base ++
|
| 186 |
| .halt => [.exitHalt]
|
| 187 |
|
| 188 |
-
theorem
|
| 189 |
-
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
-
/-- Prefix sums of instruction sizes: `offs p k` is the code index of IR instruction `k`
|
| 193 |
-
|
| 194 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
|
| 196 |
-
def lowerGo (L : Layout) (off : Nat → Nat) :
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 :=
|
| 68 |
-
simp [offs, List.take_succ_cons]
|
| 69 |
|
| 70 |
-
theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by
|
| 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
|
|
|
|
| 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
|
|
|
|
| 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)
|
|
|
|
| 118 |
intro ps
|
| 119 |
induction ps with
|
| 120 |
| nil =>
|
| 121 |
-
intro pre
|
| 122 |
-
simp only [lowerGo, List.length_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
|
|
|
|
| 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 +
|
| 313 |
-
RAt code (base +
|
| 314 |
.store Reg.r9 0 r0] := by
|
| 315 |
-
have hat' : RAt code base (uf L 1 base ++ ovfA L (base +
|
| 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 :
|
| 320 |
rw [hufl] at hato
|
| 321 |
-
have hl : (uf L 1 base ++ ovfA L (base +
|
| 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)
|
| 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
|
| 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)
|
| 354 |
exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
|
| 355 |
|
| 356 |
-
/-- Placement of `emptyA L base ++
|
| 357 |
theorem xat_take {rest : List (Instr Nat)}
|
| 358 |
-
(hat : RAt code base (emptyA L base ++
|
| 359 |
-
RAt code base (emptyA L base) ∧ RAt code (base + 3) (
|
| 360 |
-
RAt code (base +
|
| 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 ++
|
| 366 |
-
|
|
|
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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 +
|
| 40 |
have hk : 2 ≤ s.dstack.length := by simp [hd]
|
| 41 |
obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
|
| 42 |
-
have hufl :
|
| 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)
|
| 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 +
|
| 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 +
|
| 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 +
|
| 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 +
|
| 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}
|
| 18 |
-
offs p (k + 1) = offs p k + isize i := by
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 :
|
| 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)
|
| 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
|
| 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) (
|
| 54 |
-
(hi : ∀ m : M, exec i m = .next (m.arith r0 (
|
| 55 |
-
(hfg : ∀ a b, b ≠ 0#32 →
|
| 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 :
|
| 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)
|
| 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
|
| 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 (
|
| 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
|
| 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 :
|
| 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)
|
| 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 :
|
| 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)
|
| 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,
|
| 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
|
| 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 :
|
| 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)
|
| 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 +
|
| 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,
|
| 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
|
| 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, _, _⟩ :=
|
| 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 +
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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) (
|
| 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 =
|
| 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)) (
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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 `
|
| 68 |
-
theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {
|
| 69 |
-
(hat : RAt code base (
|
| 70 |
-
RAt code base (
|
| 71 |
-
code[base +
|
| 72 |
obtain ⟨hato, hatr⟩ := rat_append.mp hat
|
| 73 |
-
|
| 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 ++
|
| 79 |
-
theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {
|
| 80 |
{i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
|
| 81 |
-
(hat : RAt code base (uf L n base ++
|
| 82 |
-
RAt code base (uf L n base) ∧ RAt code (base +
|
| 83 |
-
code[base +
|
|
|
|
|
|
|
| 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 :
|
| 89 |
rw [hufl] at hato
|
| 90 |
-
have hl : (uf L n base ++
|
|
|
|
| 91 |
rw [hl] at hatr
|
| 92 |
obtain ⟨f0, f1, f2, _⟩ := hatr
|
| 93 |
-
exact ⟨hatuf, hato, f0, f1,
|
|
|
|
| 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 :
|
| 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)
|
| 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
|
| 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 :=
|
| 127 |
have hk : 1 ≤ s.dstack.length := by simp [hd]
|
| 128 |
-
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide)
|
| 129 |
-
obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ :=
|
| 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
|
| 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 :=
|
| 142 |
-
obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by
|
| 143 |
-
exact RExec.of_steps hs1 (
|
| 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 :
|
| 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)
|
| 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
|
| 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, _, _⟩ :=
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :=
|
| 231 |
have hk : 2 ≤ s.dstack.length := by simp [hd]
|
| 232 |
-
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide)
|
| 233 |
-
obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ :=
|
| 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
|
| 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 :=
|
| 246 |
-
obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by
|
| 247 |
-
exact RExec.of_steps hs1 (
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
|
|
|
|
|
|
|
|
|
| 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)
|
|
|
|
| 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) =
|
| 242 |
-
|
|
|
|
| 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
|
|
|
|
| 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 |
-
|
| 27 |
-
`cmc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
def
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 68 |
-
def
|
| 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 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
| .error e => return .error e
|
| 94 |
-
| .ok
|
| 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 .
|
| 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
|
| 118 |
-
|
| 119 |
-
|
|
|
|
|
|
|
| 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 |
-
|
|
| 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 (
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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)
|
| 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) :
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
| 55 |
-
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 23 |
-
* implements `exitTrap t` as
|
| 24 |
status 6.
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
| 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`),
|
| 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 |
-
|
| 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 |
-
/--
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
"\t.thumb_func\nputc:\n" ++
|
| 223 |
-
s!"\t{la "r2"
|
| 224 |
-
"1:\
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 233 |
-
"\
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
|
| 235 |
-
/--
|
| 236 |
-
def uartOn (
|
| 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
|
| 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
|
| 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 |
-
/--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
|
| 67 |
-
{L : Layout} {base
|
| 68 |
-
(
|
| 69 |
-
(hat : RAt code base (uf L
|
| 70 |
-
|
|
|
|
|
|
|
| 71 |
obtain ⟨h1, h2, h3, _⟩ := hat
|
| 72 |
-
let xa := x.mov r0 (L.dEnd - BitVec.ofNat 32 (4 *
|
| 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
|
| 77 |
-
have h : ¬
|
| 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 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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) :
|
| 94 |
-
|
| 95 |
-
|
| 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)
|
|
|
|
| 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
|
|
|
|
| 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
|
| 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 |
-
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
| 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 _ =>
|
| 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 _ =>
|
| 119 |
-
| .pop _ => ufSize 1 + 3
|
| 120 |
-
| .dup => ufSize 1 +
|
| 121 |
-
| .drop => ufSize 1 + 1
|
| 122 |
-
| .swap => ufSize 2 + 4
|
| 123 |
-
| .over => ufSize 2 +
|
| 124 |
-
| .rot => ufSize 3 + 6
|
| 125 |
-
| .tor => ufSize 1 + 7
|
| 126 |
-
| .fromr =>
|
| 127 |
-
| .rfetch =>
|
| 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)
|
| 133 |
-
|
| 134 |
-
| .
|
|
|
|
| 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 =>
|
| 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 ++
|
| 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 ++
|
| 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 ++
|
| 207 |
[.load r0 r6 0, .addImm r6 4, .addImm r4 (-4), .store r4 0 r0]
|
| 208 |
| .rfetch =>
|
| 209 |
-
emptyA L base ++
|
| 210 |
| .halt => [.exitHalt]
|
| 211 |
|
| 212 |
-
theorem
|
| 213 |
-
|
| 214 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
-
/-- Prefix sums of instruction sizes: `offs p k` is the code index of IR instruction `k`
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
-
def lowerGo (L : Layout) (off : Nat → Nat) :
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 :=
|
| 68 |
-
simp [offs, List.take_succ_cons]
|
| 69 |
|
| 70 |
-
theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by
|
| 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
|
|
|
|
| 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
|
|
|
|
| 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)
|
|
|
|
| 118 |
intro ps
|
| 119 |
induction ps with
|
| 120 |
| nil =>
|
| 121 |
-
intro pre
|
| 122 |
-
simp only [lowerGo, List.length_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
|
|
|
|
| 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 +
|
| 313 |
-
RAt code (base +
|
| 314 |
.store Reg.r6 0 r0] := by
|
| 315 |
-
have hat' : RAt code base (uf L 1 base ++ ovfA L (base +
|
| 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 :
|
| 320 |
rw [hufl] at hato
|
| 321 |
-
have hl : (uf L 1 base ++ ovfA L (base +
|
| 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)
|
| 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
|
| 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)
|
| 354 |
exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
|
| 355 |
|
| 356 |
-
/-- Placement of `emptyA L base ++
|
| 357 |
theorem xat_take {rest : List (Instr Nat)}
|
| 358 |
-
(hat : RAt code base (emptyA L base ++
|
| 359 |
-
RAt code base (emptyA L base) ∧ RAt code (base + 3) (
|
| 360 |
-
RAt code (base +
|
| 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 ++
|
| 366 |
-
|
|
|
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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 +
|
| 40 |
have hk : 2 ≤ s.dstack.length := by simp [hd]
|
| 41 |
obtain ⟨hatuf, hatrest⟩ := rat_append.mp hat
|
| 42 |
-
have hufl :
|
| 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)
|
| 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 +
|
| 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 +
|
| 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 +
|
| 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 +
|
| 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}
|
| 18 |
-
offs p (k + 1) = offs p k + isize i := by
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 :
|
| 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)
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
| 86 |
obtain ⟨x5, hs5, hpc5, hax5, hm5, hfr5⟩ := hseg x4 a b
|
| 87 |
-
(by simpa [
|
| 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
|
| 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
|
| 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 |
-
|
| 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 :
|
| 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)
|
| 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 :
|
| 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)
|
| 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,
|
| 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
|
| 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 :
|
| 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)
|
| 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 +
|
| 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,
|
| 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
|
| 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, _, _⟩ :=
|
| 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 +
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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) (
|
| 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 =
|
| 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)) (
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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
|
| 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 `
|
| 68 |
-
theorem xat_ovf3 {code : List (Instr Nat)} {L : Layout} {
|
| 69 |
-
(hat : RAt code base (
|
| 70 |
-
RAt code base (
|
| 71 |
-
code[base +
|
| 72 |
obtain ⟨hato, hatr⟩ := rat_append.mp hat
|
| 73 |
-
|
| 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 ++
|
| 79 |
-
theorem xat_uf_ovf {code : List (Instr Nat)} {L : Layout} {
|
| 80 |
{i0 i1 i2 : Instr Nat} {rest : List (Instr Nat)} (hrest : rest = [i0, i1, i2])
|
| 81 |
-
(hat : RAt code base (uf L n base ++
|
| 82 |
-
RAt code base (uf L n base) ∧ RAt code (base +
|
| 83 |
-
code[base +
|
|
|
|
|
|
|
| 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 :
|
| 89 |
rw [hufl] at hato
|
| 90 |
-
have hl : (uf L n base ++
|
|
|
|
| 91 |
rw [hl] at hatr
|
| 92 |
obtain ⟨f0, f1, f2, _⟩ := hatr
|
| 93 |
-
exact ⟨hatuf, hato, f0, f1,
|
|
|
|
| 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 :
|
| 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)
|
| 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
|
| 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 :=
|
| 127 |
have hk : 1 ≤ s.dstack.length := by simp [hd]
|
| 128 |
-
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide)
|
| 129 |
-
obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ :=
|
| 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
|
| 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 :=
|
| 142 |
-
obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by
|
| 143 |
-
exact RExec.of_steps hs1 (
|
| 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 :
|
| 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)
|
| 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
|
| 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, _, _⟩ :=
|
| 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
|
| 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 :
|
| 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)
|
| 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
|
| 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 :=
|
| 231 |
have hk : 2 ≤ s.dstack.length := by simp [hd]
|
| 232 |
-
obtain ⟨x1, hs1, hr1, hpc1, hm1, _⟩ := uf_pass hg hs hL (by decide)
|
| 233 |
-
obtain ⟨x1', hs1', hr1', hpc1', _, _⟩ :=
|
| 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
|
| 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 :=
|
| 246 |
-
obtain ⟨x1, hs1, hr1, hpc1, _, _⟩ := uf_pass hg hs hL (by decide) (by
|
| 247 |
-
exact RExec.of_steps hs1 (
|
| 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 :
|
| 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)
|
| 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
|
| 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
|
|
|
|
|
|
|
|
|
|
| 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)
|
|
|
|
| 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) =
|
| 242 |
-
|
|
|
|
| 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
|
|
|
|
| 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 |
-
|
| 27 |
-
`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
CM0.Emit.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 =
|
| 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
|
| 68 |
-
def
|
| 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 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 (
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 126 |
-
|
|
|
|
|
|
| 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) :
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
| 55 |
-
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)) (
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 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 |
-
/--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
theorem uf_trap {c : Cfg} {p : Prog 32} {s : State 32} {x : M} {code : List (Instr Nat)}
|
| 67 |
-
{L : Layout} {base
|
| 68 |
-
(
|
| 69 |
-
(hat : RAt code base (uf L
|
| 70 |
-
|
|
|
|
|
|
|
| 71 |
obtain ⟨h1, h2, h3, _⟩ := hat
|
| 72 |
-
let xa := x.mov t0 (L.dEnd - BitVec.ofNat 32 (4 *
|
| 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
|
| 77 |
-
have h : ¬
|
| 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 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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) :
|
| 86 |
-
|
| 87 |
-
|
| 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)
|
|
|
|
| 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
|
|
|
|
| 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 _ =>
|
| 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 _ =>
|
| 90 |
-
| .pop _ => ufSize 1 + 3
|
| 91 |
-
| .dup => ufSize 1 +
|
| 92 |
-
| .drop => ufSize 1 + 1
|
| 93 |
-
| .swap => ufSize 2 + 4
|
| 94 |
-
| .over => ufSize 2 +
|
| 95 |
-
| .rot => ufSize 3 + 6
|
| 96 |
-
| .tor => ufSize 1 + 7
|
| 97 |
-
| .fromr =>
|
| 98 |
-
| .rfetch =>
|
| 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)
|
| 104 |
-
|
| 105 |
-
| .
|
|
|
|
| 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 =>
|
| 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 ++
|
| 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 ++
|
| 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 ++
|
| 180 |
[.load t0 s6 0, .addImm s6 4, .addImm s1 (-4), .store s1 0 t0]
|
| 181 |
| .rfetch =>
|
| 182 |
-
emptyA L base ++
|
| 183 |
| .halt => [.exitHalt]
|
| 184 |
|
| 185 |
-
theorem
|
| 186 |
-
|
| 187 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
|
| 189 |
-
/-- Prefix sums of instruction sizes: `offs p k` is the
|
| 190 |
-
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
|
| 193 |
-
def lowerGo (L : Layout) (off : Nat → Nat) :
|
| 194 |
-
|
| 195 |
-
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 :=
|
| 68 |
-
simp [offs, List.take_succ_cons]
|
| 69 |
|
| 70 |
-
theorem offs_zero (p : Prog 32) : offs p 0 = 0 := by
|
| 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
|
|
|
|
| 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
|
|
|
|
| 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)
|
|
|
|
| 118 |
intro ps
|
| 119 |
induction ps with
|
| 120 |
| nil =>
|
| 121 |
-
intro pre
|
| 122 |
-
simp only [lowerGo, List.length_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
|
|
|
|
| 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 +
|
| 313 |
-
RAt code (base +
|
| 314 |
.store Reg.s6 0 t0] := by
|
| 315 |
-
have hat' : RAt code base (uf L 1 base ++ ovfA L (base +
|
| 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 :
|
| 320 |
rw [hufl] at hato
|
| 321 |
-
have hl : (uf L 1 base ++ ovfA L (base +
|
| 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)
|
| 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
|
| 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)
|
| 354 |
exact RExec.of_steps hs1 (ovfA_trap hg hr1 hLal h hpc1 hato)
|
| 355 |
|
| 356 |
-
/-- Placement of `emptyA L base ++
|
| 357 |
theorem xat_take {rest : List (Instr Nat)}
|
| 358 |
-
(hat : RAt code base (emptyA L base ++
|
| 359 |
-
RAt code base (emptyA L base) ∧ RAt code (base + 3) (
|
| 360 |
-
RAt code (base +
|
| 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 ++
|
| 366 |
-
|
|
|
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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', _, _⟩ :=
|
| 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 (
|
| 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 |
|