ai-free / backend /arm64 /A64 /Micro.lean
SNAPKITTYWEST's picture
October 2026 main drop: sync from GitHub at 8d0f04c
9ad95e5 verified
Raw History Blame Contribute Delete
13.5 kB
import A64.Seq
/-!
# A64.Micro
Micro-lemmas: how single AArch64 instructions (and the push pair) act on a machine state related to
an IR state by `Rel0`. Every IR-instruction simulation proof is a chain of these.
-/
namespace WordDialect
namespace A64
open Reg
theorem ea_nat (a j : Nat) : ofN a + BitVec.ofInt 64 (8 * (j : Int)) = ofN (a + 8 * j) := by
rw [show (8 * (j : Int)) = ((8 * j : Nat) : Int) by omega, BitVec.ofInt_natCast]
exact ofN_add _ _
/-- Load stack slot `j` into a scratch register. -/
theorem ld_stack {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hs : Rel0 c p s x)
{j : Nat} {v : W} (hj : s.dstack[j]? = some v) (rd : Reg) {disp : Int}
(hd : disp = 8 * (j : Int)) :
exec (.load rd Reg.x19 disp) x = .next (x.mov rd v) := by
have hread := hs.stack j v hj
simp only [exec, M.ea, hs.x19, hd, ea_nat]
rw [hread]
theorem mov_rel0 {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hs : Rel0 c p s x) (rd : Reg)
(hr : rd ≠ x19 ∧ rd ≠ x20 ∧ rd ≠ x21 ∧ rd ≠ x22 ∧ rd ≠ x23 ∧ rd ≠ x24) (v : W) :
Rel0 c p s (x.mov rd v) := by
obtain ⟨h1, h2, h3, h4, h5, h6⟩ := hr
refine hs.congr rfl ?_ ?_ ?_ ?_ ?_ ?_ <;>
simp [M.mov, M.setReg, M.adv, Ne.symm h1, Ne.symm h2, Ne.symm h3, Ne.symm h4, Ne.symm h5,
Ne.symm h6]
theorem arith_rel0 {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hs : Rel0 c p s x) (rd : Reg)
(hr : rd ≠ x19 ∧ rd ≠ x20 ∧ rd ≠ x21 ∧ rd ≠ x22 ∧ rd ≠ x23 ∧ rd ≠ x24) (v : W) :
Rel0 c p s (x.arith rd v) := by
obtain ⟨h1, h2, h3, h4, h5, h6⟩ := hr
refine hs.congr rfl ?_ ?_ ?_ ?_ ?_ ?_ <;>
simp [M.arith, M.setReg, Ne.symm h1, Ne.symm h2, Ne.symm h3, Ne.symm h4, Ne.symm h5,
Ne.symm h6]
theorem flags_rel0 {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hs : Rel0 c p s x)
(f : Option Flags) (q : Nat) : Rel0 c p s { x with flags := f, pc := q } :=
hs.congr rfl rfl rfl rfl rfl rfl rfl
/-- Store a register into stack slot `j`: the relation holds for the stack with that slot replaced. -/
theorem st_stack {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hg : Geom c) (hs : Rel0 c p s x)
{j : Nat} (hj : j < s.dstack.length) (rs : Reg) {disp : Int} (hd : disp = 8 * (j : Int)) :
∃ mem', exec (.store Reg.x19 disp rs) x = .next { x.adv with mem := mem' } ∧
Rel0 c p { s with dstack := s.dstack.set j (x.regs rs) } { x.adv with mem := mem' } := by
have hcap := hs.capD
have hcapR := hs.capR
have hdE := hg.dEnd_lt
have hA : c.dBase ≤ c.dEnd - 8 * s.dstack.length + 8 * j := by omega
have hA' : c.dEnd - 8 * s.dstack.length + 8 * j < c.dEnd := by omega
have hvalid := hs.xvalid.1 _ hA hA'
obtain ⟨mem', hw⟩ : ∃ m', x.mem.write? (ofN (c.dEnd - 8 * s.dstack.length + 8 * j)) (x.regs rs)
= some m' := by simp [Memory.write?, hvalid]
refine ⟨mem', ?_, ?_⟩
· simp only [exec, M.ea, hs.x19, hd, ea_nat]; rw [hw]
· have hlen : (s.dstack.set j (x.regs rs)).length = s.dstack.length := by simp
have hAlt : c.dEnd - 8 * s.dstack.length + 8 * j < 2 ^ 64 := by omega
refine { x19 := ?_, x20 := ?_, x21 := ?_, x22 := ?_, x23 := ?_, x24 := ?_, stack := ?_,
regs := ?_, mem := ?_, rs := ?_, aux := ?_, irvalid := hs.irvalid, xvalid := ?_,
capD := ?_, capR := hs.capR, capA := hs.capA }
· simpa [M.adv, hlen] using hs.x19
· simpa [M.adv] using hs.x20
· simpa [M.adv] using hs.x21
· simpa [M.adv] using hs.x22
· simpa [M.adv] using hs.x23
· simpa [M.adv] using hs.x24
· intro i w hi
simp only [hlen]
have hik : i < s.dstack.length := by
have := (List.getElem?_eq_some_iff.mp hi).1; simpa using this
by_cases hij : i = j
· subst hij
have h1 : (s.dstack.set i (x.regs rs))[i]? = some (x.regs rs) := by simp [hj]
rw [h1] at hi
cases hi
rw [read_write_nat hw hAlt hAlt]; simp
· rw [List.getElem?_set_ne (Ne.symm hij)] at hi
have hne : c.dEnd - 8 * s.dstack.length + 8 * j ≠ c.dEnd - 8 * s.dstack.length + 8 * i := by
omega
rw [read_write_nat hw hAlt (by omega)]
simp only [hne, ite_false]
exact hs.stack i w hi
· intro r hr
have hrf := hg.rf_lt
have hne : c.dEnd - 8 * s.dstack.length + 8 * j ≠ c.rf + 8 * r := by
rcases hg.dS_F with h | h <;> omega
rw [read_write_nat hw hAlt (by omega)]
simp only [hne, ite_false]
exact hs.regs r hr
· intro a ha
have hmb := hg.mb_lt
have hne : c.dEnd - 8 * s.dstack.length + 8 * j ≠ c.mb + 8 * a := by
rcases hg.dS_M with h | h <;> omega
rw [read_write_nat hw hAlt (by omega)]
simp only [hne, ite_false]
exact hs.mem a ha
· intro i a hi
have hsp := hg.sp0_lt
have hrc := hg.rcap_le
have hi' : i < s.rstack.length := by
by_cases hh : i < s.rstack.length
· exact hh
· have hn : s.rstack.length ≤ i := by omega
rw [List.getElem?_eq_none hn] at hi; simp at hi
have hne : c.dEnd - 8 * s.dstack.length + 8 * j ≠
c.sp0 - 8 * s.rstack.length + 8 * i := by
rcases hg.dS_K with h | h <;> omega
have hkr : 8 * s.rstack.length ≤ c.sp0 := by omega
have hB : c.sp0 - 8 * s.rstack.length + 8 * i < 2 ^ 64 := by omega
rw [read_write_nat hw hAlt hB]
simp only [hne, ite_false]
exact hs.rs i a hi
· exact aux_write_other hg.aEnd_lt hs.capA hs.aux hw hAlt (by rcases hg.dS_A with h | h <;> omega)
· have := Memory.write?_valid hw
show RegionsValid c mem'.valid
rw [this]; exact hs.xvalid
· simpa [hlen] using hcap
/-- Adjust the stack pointer upward by `n` words (popping `n` elements). -/
theorem adj_drop {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hg : Geom c) (hs : Rel0 c p s x)
{n : Nat} (hn : n ≤ s.dstack.length) {δ : Int} (hd : δ = 8 * (n : Int)) :
exec (.addImm Reg.x19 δ) x = .next (x.arith Reg.x19 (ofN (c.dEnd - 8 * (s.dstack.length - n)))) ∧
Rel0 c p { s with dstack := s.dstack.drop n }
(x.arith Reg.x19 (ofN (c.dEnd - 8 * (s.dstack.length - n)))) := by
have hcap := hs.capD
have hval : x.regs Reg.x19 + BitVec.ofInt 64 δ = ofN (c.dEnd - 8 * (s.dstack.length - n)) := by
rw [hs.x19, hd, ea_nat]; congr 1; omega
refine ⟨by simp only [exec, hval], ?_⟩
refine { x19 := ?_, x20 := ?_, x21 := ?_, x22 := ?_, x23 := ?_, x24 := ?_, stack := ?_,
regs := ?_, mem := ?_, rs := ?_, aux := hs.aux, irvalid := hs.irvalid, xvalid := ?_,
capD := ?_, capR := hs.capR, capA := hs.capA }
· simp [M.arith, M.setReg]
· simpa [M.arith, M.setReg] using hs.x20
· simpa [M.arith, M.setReg] using hs.x21
· simpa [M.arith, M.setReg] using hs.x22
· simpa [M.arith, M.setReg] using hs.x23
· simpa [M.arith, M.setReg] using hs.x24
· intro i w hi
simp only [List.length_drop]
rw [List.getElem?_drop] at hi
have := hs.stack (n + i) w hi
have e : c.dEnd - 8 * (s.dstack.length - n) + 8 * i =
c.dEnd - 8 * s.dstack.length + 8 * (n + i) := by omega
simp only [M.arith, M.setReg]
rw [e]; exact this
· exact hs.regs
· exact hs.mem
· exact hs.rs
· exact hs.xvalid
· simp only [List.length_drop]; omega
theorem ea_neg8 {a : Nat} (h : 8 ≤ a) : ofN a + BitVec.ofInt 64 (-8) = ofN (a - 8) := by
have : BitVec.ofInt 64 (-8) = -(ofN 8) := by
rw [show (-8 : Int) = -((8 : Nat) : Int) by omega, BitVec.ofInt_neg, BitVec.ofInt_natCast]
rfl
rw [this, ← BitVec.sub_eq_add_neg, ofN_sub h]
/-- A write inside the data-stack region leaves the register-file, IR-memory and return-stack
views unchanged. -/
theorem others_write {c : Cfg} {p : Prog 64} {s : State 64} {x : M} (hg : Geom c)
(hs : Rel0 c p s x) {A : Nat} {v : W} {mem' : Memory 64} (hA1 : c.dBase ≤ A) (hA2 : A < c.dEnd)
(hw : x.mem.write? (ofN A) v = some mem') :
RegRel c mem' s.regs ∧ MemRel c mem' s.mem ∧ RsRel c p mem' s.rstack ∧
AuxRel c mem' s.astack := by
have hdE := hg.dEnd_lt
have hAlt : A < 2 ^ 64 := by omega
have hcapR := hs.capR
have hrc := hg.rcap_le
have hsp := hg.sp0_lt
refine ⟨?_, ?_, ?_, aux_write_other hg.aEnd_lt hs.capA hs.aux hw hAlt
(by rcases hg.dS_A with h | h <;> omega)⟩
· intro r hr
have hrf := hg.rf_lt
have hne : A ≠ c.rf + 8 * r := by rcases hg.dS_F with h | h <;> omega
rw [read_write_nat hw hAlt (by omega)]
simp only [hne, ite_false]
exact hs.regs r hr
· intro a ha
have hmb := hg.mb_lt
have hne : A ≠ c.mb + 8 * a := by rcases hg.dS_M with h | h <;> omega
rw [read_write_nat hw hAlt (by omega)]
simp only [hne, ite_false]
exact hs.mem a ha
· intro i a hi
have hi' : i < s.rstack.length := by
by_cases hh : i < s.rstack.length
· exact hh
· have hn : s.rstack.length ≤ i := by omega
rw [List.getElem?_eq_none hn] at hi; simp at hi
have hkr : 8 * s.rstack.length ≤ c.sp0 := by omega
have hB : c.sp0 - 8 * s.rstack.length + 8 * i < 2 ^ 64 := by omega
have hne : A ≠ c.sp0 - 8 * s.rstack.length + 8 * i := by rcases hg.dS_K with h | h <;> omega
rw [read_write_nat hw hAlt hB]
simp only [hne, ite_false]
exact hs.rs i a hi
/-- `addImm x19, -8; store [x19], rs` pushes the value of `rs`. -/
theorem push_pair {c : Cfg} {p : Prog 64} {s : State 64} {x : M} {code : List (Instr Nat)}
(hg : Geom c) (hs : Rel0 c p s x) (rs : Reg) (hrs : rs ≠ x19)
(hfit : c.dBase + 8 * (s.dstack.length + 1) ≤ c.dEnd)
(hat : AAt code x.pc [.addImm Reg.x19 (-8), .store Reg.x19 0 rs]) :
∃ x', ASteps code x x' ∧
Rel0 c p { s with dstack := x.regs rs :: s.dstack } x' ∧ x'.pc = x.pc + 2 ∧
(∀ r, r ≠ x19 → x'.regs r = x.regs r) := by
obtain ⟨h1, h2, _⟩ := hat
have hcap := hs.capD
have hdE := hg.dEnd_lt
have hA1 : c.dBase ≤ c.dEnd - 8 * (s.dstack.length + 1) := by omega
have hA2 : c.dEnd - 8 * (s.dstack.length + 1) < c.dEnd := by omega
have hAlt : c.dEnd - 8 * (s.dstack.length + 1) < 2 ^ 64 := by omega
-- step 1: x19 := x19 - 8
have hval : x.regs Reg.x19 + BitVec.ofInt 64 (-8) = ofN (c.dEnd - 8 * (s.dstack.length + 1)) := by
rw [hs.x19, ea_neg8 (by omega)]
congr 1
have e1 : exec (.addImm Reg.x19 (-8)) x = .next (x.arith Reg.x19 (ofN (c.dEnd - 8 * (s.dstack.length + 1)))) := by
simp only [exec, hval]
obtain ⟨x1, hx1⟩ : ∃ x1, x1 = x.arith Reg.x19 (ofN (c.dEnd - 8 * (s.dstack.length + 1))) := ⟨_, rfl⟩
rw [← hx1] at e1
have hst1 : step code x = .next x1 := by rw [astep_of_fetch h1, e1]
-- step 2: store [x19], rs
have hr15 : x1.regs Reg.x19 = ofN (c.dEnd - 8 * (s.dstack.length + 1)) := by simp [hx1, M.arith, M.setReg]
have hrsv : x1.regs rs = x.regs rs := by simp [hx1, M.arith, M.setReg, hrs]
have hvalid := hs.xvalid.1 _ hA1 hA2
obtain ⟨mem', hw⟩ : ∃ m', x.mem.write? (ofN (c.dEnd - 8 * (s.dstack.length + 1))) (x.regs rs) = some m' := by
simp [Memory.write?, hvalid]
have e2 : exec (.store Reg.x19 0 rs) x1 = .next { x1.adv with mem := mem' } := by
have : x1.mem = x.mem := by simp [hx1, M.arith, M.setReg]
simp only [exec, M.ea, hr15, hrsv, this]
have h0 : ofN (c.dEnd - 8 * (s.dstack.length + 1)) + BitVec.ofInt 64 0 = ofN (c.dEnd - 8 * (s.dstack.length + 1)) := by
simp
rw [h0, hw]
have hpc1 : x1.pc = x.pc + 1 := by simp [hx1, M.arith, M.setReg]
have hst2 : step code x1 = .next { x1.adv with mem := mem' } := by
rw [astep_of_fetch (m := x1) (by rw [hpc1]; exact h2), e2]
refine ⟨{ x1.adv with mem := mem' }, (ASteps.single hst1).trans (ASteps.single hst2), ?_, ?_, ?_⟩
· have ⟨hrg, hmm, hrr, hax⟩ := others_write hg hs hA1 hA2 hw
have hlen : (x.regs rs :: s.dstack).length = s.dstack.length + 1 := by simp
refine { x19 := ?_, x20 := ?_, x21 := ?_, x22 := ?_, x23 := ?_, x24 := ?_, stack := ?_,
regs := hrg, mem := hmm, rs := hrr, aux := hax, irvalid := hs.irvalid, xvalid := ?_,
capD := ?_, capR := hs.capR, capA := hs.capA }
· simpa [hlen, M.adv, hx1, M.arith, M.setReg] using rfl
· simpa [M.adv, hx1, M.arith, M.setReg] using hs.x20
· simpa [M.adv, hx1, M.arith, M.setReg] using hs.x21
· simpa [M.adv, hx1, M.arith, M.setReg] using hs.x22
· simpa [M.adv, hx1, M.arith, M.setReg] using hs.x23
· simpa [M.adv, hx1, M.arith, M.setReg] using hs.x24
· intro i w hi
simp only [hlen]
cases i with
| zero =>
simp at hi; subst hi
rw [show c.dEnd - 8 * (s.dstack.length + 1) + 8 * 0 = c.dEnd - 8 * (s.dstack.length + 1) by omega,
read_write_nat hw hAlt hAlt]; simp
| succ i =>
simp only [List.getElem?_cons_succ] at hi
have hik : i < s.dstack.length := by
have := (List.getElem?_eq_some_iff.mp hi).1; simpa using this
have hB : c.dEnd - 8 * (s.dstack.length + 1) + 8 * (i + 1) < 2 ^ 64 := by omega
have hne : c.dEnd - 8 * (s.dstack.length + 1) ≠ c.dEnd - 8 * (s.dstack.length + 1) + 8 * (i + 1) := by omega
rw [read_write_nat hw hAlt hB]
simp only [hne, ite_false]
have e : c.dEnd - 8 * (s.dstack.length + 1) + 8 * (i + 1) = c.dEnd - 8 * s.dstack.length + 8 * i := by omega
rw [e]; exact hs.stack i w hi
· have := Memory.write?_valid hw
show RegionsValid c mem'.valid
rw [this]; exact hs.xvalid
· simpa [hlen] using hfit
· simp [M.adv, hpc1]
· intro r hr
simp [M.adv, hx1, M.arith, M.setReg, hr]
end A64
end WordDialect