Proof of correctness for individual instructions
Require Import Coqlib Errors Maps Zbits.
Require Import AST Integers Floats Values Memory Globalenvs Linking Compopts Events.
Require Import Op Locations Machblock Conventions Lia.
Require Import Asmblock Asmblockgen Asmblockgenproof0 Asmblockprops.
Require Import OptionMonad.
Require Import MemcpyTypes.
Module MB :=
Machblock.
Module AB :=
Asmblock.
Local Open Scope option_monad_scope.
Local Opaque PregEq.eq.
Arithmetic helper used in the Ocmp Ceq clz lowering.
Lemma int_sub_eq_zero:
forall i j,
Int.eq (
Int.sub i j)
Int.zero =
Int.eq i j.
Proof.
Useful properties of special registers.
Lemma preg_of_not_R13:
forall r,
preg_of r <>
IR13.
Proof.
destruct r; simpl; discriminate.
Qed.
Lemma ireg_of_not_R13:
forall m r,
ireg_of m =
OK r ->
r <>
IR13.
Proof.
unfold ireg_of.
intros.
destruct (
preg_of m)
eqn:
E;
inv H.
red.
intros.
elim (
preg_of_not_R13 m).
destruct d.
destruct i;
inv H1;
auto.
all:
try discriminate.
Qed.
Lemma ireg_of_not_R13':
forall m r,
ireg_of m =
OK r ->
DR (
IR r) <>
IR13.
Proof.
Global Hint Resolve preg_of_not_R13 ireg_of_not_R13 ireg_of_not_R13':
asmgen.
Lemma preg_of_not_R14:
forall r,
preg_of r <>
IR14.
Proof.
destruct r; simpl; discriminate.
Qed.
Lemma ireg_of_not_R14:
forall m r,
ireg_of m =
OK r ->
IR r <>
IR IR14.
Proof.
unfold ireg_of.
intros.
destruct (
preg_of m)
eqn:
E;
inv H.
red.
intros.
elim (
preg_of_not_R14 m).
destruct d.
destruct i;
inv H1;
auto.
all:
try discriminate.
Qed.
Lemma ireg_of_not_R14':
forall m r,
ireg_of m =
OK r ->
DR (
IR r) <>
IR14.
Proof.
Global Hint Resolve preg_of_not_R14 ireg_of_not_R14 ireg_of_not_R14':
asmgen.
Definition if_preg (
r:
preg) :
bool :=
match r with
|
IR _ =>
true
|
FR _ =>
true
|
CR _ =>
false
|
PC =>
false
end.
Lemma data_if_preg:
forall r,
data_preg r =
true ->
if_preg r =
true.
Proof.
intros. destruct r. destruct d.
all: reflexivity || discriminate.
Qed.
Lemma data_preg_not_R14:
forall r,
data_preg r =
true ->
r <>
IR14.
Proof.
intros. destruct r. destruct d. destruct i.
all: simpl in *; congruence.
Qed.
Lemma if_preg_not_PC:
forall r,
if_preg r =
true ->
r <>
PC.
Proof.
intros; red; intros; subst; discriminate.
Qed.
Global Hint Resolve data_if_preg if_preg_not_PC:
asmgen.
Lemma undef_flags_rs_eq:
forall rs r,
if_preg r =
true ->
undef_flags rs r =
rs r.
Proof.
intros. destruct r; reflexivity || discriminate.
Qed.
Lemma undef_flags_rs_eq':
forall rs (
r:
ireg),
undef_flags rs r =
rs r.
Proof.
intros. destruct r; reflexivity || discriminate.
Qed.
Useful simplification tactic
Ltac Simplif :=
((
rewrite undef_flags_rs_eq by eauto with asmgen)
|| (
rewrite undef_flags_rs_eq' by eauto with asmgen)
|| (
rewrite Pregmap.gss)
|| (
rewrite Pregmap.gso by eauto with asmgen));
auto with asmgen.
Ltac Simpl :=
repeat Simplif.
Correctness of ARM constructor functions
Section CONSTRUCTORS.
Variable ge:
genv.
Local Transparent Archi.ptr64.
Lemma iterate_op_correct:
forall op1 op2 (
f:
val ->
int ->
val) (
rs:
regset) (
r:
ireg)
m v0 is_addsub n k,
(
forall (
rs:
regset)
n,
exec_basic ge (
op2 (
SOimm n))
rs m =
Next (
undef_flags rs#
r <- (
f (
rs#
r)
n))
m) ->
(
forall n,
exec_basic ge (
op1 (
SOimm n))
rs m =
Next (
undef_flags rs#
r <- (
f v0 n))
m) ->
exists rs',
exec_straight ge (
iterate_op op1 op2 (
decompose_int is_addsub n)
k)
rs m k rs' m
/\
rs'#
r =
List.fold_left f (
decompose_int is_addsub n)
v0
/\
forall r':
preg,
r' <>
r ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Loading a constant.
Lemma loadimm_correct:
forall r n k rs m,
exists rs',
exec_straight ge (
loadimm r n k)
rs m k rs' m
/\
rs'#
r =
Vint n
/\
forall r':
preg,
r' <>
r ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Add integer immediate.
Lemma addimm_correct:
forall r1 r2 n k rs m,
exists rs',
exec_straight ge (
addimm r1 r2 n k)
rs m k rs' m
/\
rs'#
r1 =
Val.add rs#
r2 (
Vint n)
/\
forall r':
preg,
r' <>
r1 ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Lemma andimm_correct:
forall r1 r2 n k rs m,
exists rs',
exec_straight ge (
andimm r1 r2 n k)
rs m k rs' m
/\
rs'#
r1 =
Val.and rs#
r2 (
Vint n)
/\
forall r':
preg,
r' <>
r1 ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Reverse sub immediate
Lemma rsubimm_correct:
forall r1 r2 n k rs m,
exists rs',
exec_straight ge (
rsubimm r1 r2 n k)
rs m k rs' m
/\
rs'#
r1 =
Val.sub (
Vint n)
rs#
r2
/\
forall r':
preg,
r' <>
r1 ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Or immediate
Lemma orimm_correct:
forall r1 r2 n k rs m,
exists rs',
exec_straight ge (
orimm r1 r2 n k)
rs m k rs' m
/\
rs'#
r1 =
Val.or rs#
r2 (
Vint n)
/\
forall r':
preg,
r' <>
r1 ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Xor immediate
Lemma xorimm_correct:
forall r1 r2 n k rs m,
exists rs',
exec_straight ge (
xorimm r1 r2 n k)
rs m k rs' m
/\
rs'#
r1 =
Val.xor rs#
r2 (
Vint n)
/\
forall r':
preg,
r' <>
r1 ->
if_preg r' =
true ->
rs'#
r' =
rs#
r'.
Proof.
Indexed memory loads.
Lemma indexed_memory_access_correct:
forall (
P:
regset ->
Prop) (
mk_instr:
ireg ->
int ->
basic)
(
mk_immed:
int ->
int) (
base:
ireg)
n k (
rs:
regset)
m m',
(
forall (
r1:
ireg) (
rs1:
regset)
n1 k,
Val.add rs1#
r1 (
Vint n1) =
Val.add rs#
base (
Vint n) ->
(
forall (
r:
preg),
if_preg r =
true ->
r <>
IR14 ->
rs1 r =
rs r) ->
exists rs',
exec_straight ge (
mk_instr r1 n1 ::
k)
rs1 m k rs' m' /\
P rs') ->
exists rs',
exec_straight ge
(
indexed_memory_access mk_instr mk_immed base n k)
rs m
k rs' m'
/\
P rs'.
Proof.
Lemma loadind_int_correct:
forall (
base:
ireg)
ofs dst (
rs:
regset)
m v k,
Mem.loadv Mint32 m (
Val.offset_ptr rs#
base ofs) =
Some v ->
exists rs',
exec_straight ge (
loadind_int base ofs dst k)
rs m k rs' m
/\
rs'#
dst =
v
/\
forall r,
if_preg r =
true ->
r <>
IR14 ->
r <>
dst ->
rs'#
r =
rs#
r.
Proof.
Lemma loadind_correct:
forall (
base:
ireg)
ofs ty dst k c (
rs:
regset)
m v,
loadind base ofs ty dst k =
OK c ->
Mem.loadv (
chunk_of_type ty)
m (
Val.offset_ptr rs#
base ofs) =
Some v ->
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of dst) =
v
/\
forall r,
if_preg r =
true ->
r <>
IR14 ->
r <>
preg_of dst ->
rs'#
r =
rs#
r.
Proof.
Indexed memory stores.
Lemma storeind_correct:
forall (
base:
ireg)
ofs ty src k c (
rs:
regset)
m m',
storeind src base ofs ty k =
OK c ->
Mem.storev (
chunk_of_type ty)
m (
Val.offset_ptr rs#
base ofs) (
rs#(
preg_of src)) =
Some m' ->
exists rs',
exec_straight ge c rs m k rs' m'
/\
forall r,
if_preg r =
true ->
r <>
IR14 ->
rs'#
r =
rs#
r.
Proof.
unfold storeind;
intros.
assert (
DATA:
data_preg (
preg_of src) =
true)
by eauto with asmgen.
assert (
Val.offset_ptr (
rs base)
ofs =
Val.add (
rs base) (
Vint (
Ptrofs.to_int ofs))).
{
destruct (
rs base);
try discriminate.
simpl.
f_equal;
f_equal.
symmetry;
auto with ptrofs. }
destruct ty;
destruct (
preg_of src);
try destruct d;
inv H;
simpl in H0.
-
apply indexed_memory_access_correct;
intros.
econstructor;
split.
apply exec_straight_one.
simpl.
unfold exec_store.
rewrite H, <-
H1.
unfold exec_store_aux.
rewrite H2,
H0 by auto with asmgen;
eauto.
auto.
-
apply indexed_memory_access_correct;
intros.
econstructor;
split.
apply exec_straight_one.
simpl.
unfold exec_store.
rewrite H, <-
H1.
unfold exec_store_aux.
rewrite H2,
H0 by auto with asmgen;
eauto.
auto.
-
apply indexed_memory_access_correct;
intros.
econstructor;
split.
apply exec_straight_one.
simpl.
unfold exec_store.
rewrite H, <-
H1.
unfold exec_store_aux.
rewrite H2,
H0 by auto with asmgen;
eauto.
auto.
-
apply indexed_memory_access_correct;
intros.
econstructor;
split.
apply exec_straight_one.
simpl.
unfold exec_store.
rewrite H, <-
H1.
unfold exec_store_aux.
rewrite H2,
H0 by auto with asmgen;
eauto.
auto.
-
apply indexed_memory_access_correct;
intros.
econstructor;
split.
apply exec_straight_one.
simpl.
unfold exec_store.
rewrite H, <-
H1.
unfold exec_store_aux.
rewrite H2,
H0 by auto with asmgen;
eauto.
auto.
Qed.
Saving the link register
Lemma save_lr_correct:
forall ofs k (
rs:
regset)
m m',
Mem.storev Mint32 m (
Val.offset_ptr rs#
IR13 ofs) (
rs#
IR14) =
Some m' ->
exists rs',
exec_straight ge (
save_lr ofs k)
rs m k rs' m'
/\ (
forall r,
if_preg r =
true ->
r <>
IR12 ->
rs'#
r =
rs#
r)
/\ (
save_lr_preserves_R12 ofs =
true ->
rs'#
IR12 =
rs#
IR12).
Proof.
Translation of shift immediates
Lemma transl_shift_correct:
forall s (
r:
ireg) (
rs:
regset),
eval_shift_op (
transl_shift s r)
rs =
eval_shift s (
rs#
r).
Proof.
intros. destruct s; simpl; auto.
Qed.
Translation of conditions
Lemma compare_int_spec:
forall rs v1 v2 m,
let rs1 :=
compare_int rs v1 v2 m in
rs1#
CN =
Val.negative (
Val.sub v1 v2)
/\
rs1#
CZ =
Val.cmpu (
Mem.valid_pointer m)
Ceq v1 v2
/\
rs1#
CC =
Val.cmpu (
Mem.valid_pointer m)
Cge v1 v2
/\
rs1#
CV =
Val.sub_overflow v1 v2.
Proof.
intros. unfold rs1. intuition.
Qed.
Lemma compare_int_inv:
forall rs v1 v2 m,
let rs1 :=
compare_int rs v1 v2 m in
forall r',
data_preg r' =
true ->
rs1#
r' =
rs#
r'.
Proof.
Lemma compare_int_test_spec:
forall rs v1 v2,
let rs1 :=
compare_int_test rs v1 v2 in
rs1#
CN =
Val.negative (
Val.and v1 v2)
/\
rs1#
CZ =
Val.cmp Ceq (
Val.and v1 v2) (
Vint Int.zero)
/\
rs1#
CC =
Vundef
/\
rs1#
CV =
Vundef.
Proof.
Lemma compare_int_test_inv:
forall rs v1 v2,
let rs1 :=
compare_int_test rs v1 v2 in
forall r',
data_preg r' =
true ->
rs1#
r' =
rs#
r'.
Proof.
Lemma cond_for_maskzero_correct:
forall n v rs b,
Val.cmp_bool Ceq (
Val.and v (
Vint n)) (
Vint Int.zero) =
Some b ->
eval_testcond TCeq (
compare_int_test rs v (
Vint n)) =
Some b.
Proof.
Lemma cond_for_masknotzero_correct:
forall n v rs b,
Val.cmp_bool Cne (
Val.and v (
Vint n)) (
Vint Int.zero) =
Some b ->
eval_testcond TCne (
compare_int_test rs v (
Vint n)) =
Some b.
Proof.
Lemma int_signed_eq:
forall x y,
Int.eq x y =
zeq (
Int.signed x) (
Int.signed y).
Proof.
Lemma int_not_lt:
forall x y,
negb (
Int.lt y x) = (
Int.lt x y ||
Int.eq x y).
Proof.
Lemma int_lt_not:
forall x y,
Int.lt y x =
negb (
Int.lt x y) &&
negb (
Int.eq x y).
Proof.
Lemma int_not_ltu:
forall x y,
negb (
Int.ltu y x) = (
Int.ltu x y ||
Int.eq x y).
Proof.
Lemma int_ltu_not:
forall x y,
Int.ltu y x =
negb (
Int.ltu x y) &&
negb (
Int.eq x y).
Proof.
Lemma cond_for_signed_cmp_correct:
forall c v1 v2 rs m b,
Val.cmp_bool c v1 v2 =
Some b ->
eval_testcond (
cond_for_signed_cmp c)
(
compare_int rs v1 v2 m) =
Some b.
Proof.
Lemma cond_for_unsigned_cmp_correct:
forall c v1 v2 rs m b,
Val.cmpu_bool (
Mem.valid_pointer m)
c v1 v2 =
Some b ->
eval_testcond (
cond_for_unsigned_cmp c)
(
compare_int rs v1 v2 m) =
Some b.
Proof.
Lemma compare_float_spec:
forall rs f1 f2,
let rs1 :=
compare_float rs (
Vfloat f1) (
Vfloat f2)
in
rs1#
CN =
Val.of_bool (
Float.cmp Clt f1 f2)
/\
rs1#
CZ =
Val.of_bool (
Float.cmp Ceq f1 f2)
/\
rs1#
CC =
Val.of_bool (
negb (
Float.cmp Clt f1 f2))
/\
rs1#
CV =
Val.of_bool (
negb (
Float.cmp Ceq f1 f2 ||
Float.cmp Clt f1 f2 ||
Float.cmp Cgt f1 f2)).
Proof.
intros. intuition.
Qed.
Lemma compare_float_inv:
forall rs v1 v2,
let rs1 :=
compare_float rs v1 v2 in
forall r',
data_preg r' =
true ->
rs1#
r' =
rs#
r'.
Proof.
Lemma cond_for_float_cmp_correct:
forall c v1 v2 b rs,
Val.cmpf_bool c v1 v2 =
Some b ->
eval_testcond (
cond_for_float_cmp c) (
compare_float rs v1 v2) =
Some b.
Proof.
Lemma cond_for_float_not_cmp_correct:
forall c v1 v2 b rs,
option_map negb (
Val.cmpf_bool c v1 v2) =
Some b ->
eval_testcond (
cond_for_float_not_cmp c) (
compare_float rs v1 v2) =
Some b.
Proof.
Lemma compare_float32_spec:
forall rs f1 f2,
let rs1 :=
compare_float32 rs (
Vsingle f1) (
Vsingle f2)
in
rs1#
CN =
Val.of_bool (
Float32.cmp Clt f1 f2)
/\
rs1#
CZ =
Val.of_bool (
Float32.cmp Ceq f1 f2)
/\
rs1#
CC =
Val.of_bool (
negb (
Float32.cmp Clt f1 f2))
/\
rs1#
CV =
Val.of_bool (
negb (
Float32.cmp Ceq f1 f2 ||
Float32.cmp Clt f1 f2 ||
Float32.cmp Cgt f1 f2)).
Proof.
intros. intuition.
Qed.
Lemma compare_float32_inv:
forall rs v1 v2,
let rs1 :=
compare_float32 rs v1 v2 in
forall r',
data_preg r' =
true ->
rs1#
r' =
rs#
r'.
Proof.
Lemma cond_for_float32_cmp_correct:
forall c v1 v2 b rs,
Val.cmpfs_bool c v1 v2 =
Some b ->
eval_testcond (
cond_for_float_cmp c) (
compare_float32 rs v1 v2) =
Some b.
Proof.
Lemma cond_for_float32_not_cmp_correct:
forall c v1 v2 b rs,
option_map negb (
Val.cmpfs_bool c v1 v2) =
Some b ->
eval_testcond (
cond_for_float_not_cmp c) (
compare_float32 rs v1 v2) =
Some b.
Proof.
Ltac ArgsInv :=
repeat (
match goal with
| [
H:
Error _ =
OK _ |- _ ] =>
discriminate
| [
H:
match ?
args with nil => _ | _ :: _ => _
end =
OK _ |- _ ] =>
destruct args
| [
H:
bind _ _ =
OK _ |- _ ] =>
monadInv H
| [
H:
match _
with left _ => _ |
right _ =>
assertion_failed end =
OK _ |- _ ] =>
monadInv H
| [
H:
match _
with true => _ |
false =>
assertion_failed end =
OK _ |- _ ] =>
monadInv H
end);
subst;
repeat (
match goal with
| [
H:
ireg_of ?
x =
OK ?
y |- _ ] =>
simpl in *;
rewrite (
ireg_of_eq _ _
H)
in *
| [
H:
freg_of ?
x =
OK ?
y |- _ ] =>
simpl in *;
rewrite (
freg_of_eq _ _
H)
in *
end).
Key bit-level fact: after cmp lo1 lo2 sets C := lo1 >=u lo2 and
sbcs r hi1 hi2 computes Int.add_carry hi1 (Int.not hi2) C, the
resulting carry equals Int.one iff (hi1:lo1) >=u (hi2:lo2) (unsigned
64-bit comparison). The proof avoids a 12-way destruct by separating
lo1 <? lo2 first, then hi1 vs hi2, leaving 6 simple zlt _ Int.modulus
goals each closed by lia.
Signed analog of cmp_sbcs_carry_correct: after cmp+sbcs, N XOR V
equals signed 64-bit less-than. The c1=1 (lo1>=lo2, bin=0) branch is
direct from Int.lt_sub_overflow; the c1=0 (bin=1) branch is the
borrow-in generalisation, proven inline with the same modular-arithmetic
argument as Int.lt_sub_overflow.
Lemma cmp_sbcs_signed_correct:
forall hi1 lo1 hi2 lo2,
let c1 :=
if Int.ltu lo1 lo2 then Int.zero else Int.one in
let bin :=
Int.sub Int.one c1 in
Int.xor (
Int.sub_overflow hi1 hi2 bin)
(
Int.negative (
Int.sub (
Int.sub hi1 hi2)
bin)) =
(
if Int64.lt (
Int64.ofwords hi1 lo1) (
Int64.ofwords hi2 lo2)
then Int.one else Int.zero).
Proof.
Lemma cmp_sbcs_carry_correct:
forall hi1 lo1 hi2 lo2,
let c1 :=
if Int.ltu lo1 lo2 then Int.zero else Int.one in
Int.add_carry hi1 (
Int.not hi2)
c1 =
(
if Int64.ltu (
Int64.ofwords hi1 lo1) (
Int64.ofwords hi2 lo2)
then Int.zero else Int.one).
Proof.
Lemma transl_cond_correct:
forall cond args k c rs m,
transl_cond cond args k =
OK c ->
exists rs',
exec_straight ge c rs m k rs' m
/\ (
forall b,
eval_condition cond (
map rs (
map preg_of args))
m =
Some b ->
eval_testcond (
cond_for_cond cond)
rs' =
Some b)
/\
forall r,
data_preg r =
true ->
rs'#
r =
rs#
r.
Proof.
intros until m;
intros TR.
unfold transl_cond in TR;
destruct cond;
ArgsInv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
apply cond_for_signed_cmp_correct.
apply compare_int_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_unsigned_cmp_correct;
auto.
apply compare_int_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split;
rewrite transl_shift_correct.
intros.
apply cond_for_signed_cmp_correct;
auto.
apply compare_int_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split;
rewrite transl_shift_correct.
intros.
apply cond_for_unsigned_cmp_correct;
auto.
apply compare_int_inv.
-
destruct (
is_immed_arith OTHER i); [|
destruct (
is_immed_arith OTHER (
Int.neg i))].
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_signed_cmp_correct.
auto.
apply compare_int_inv.
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_signed_cmp_correct.
rewrite Int.neg_involutive.
auto.
apply compare_int_inv.
+
exploit (
loadimm_correct IR14).
intros [
rs' [
P [
Q R]]].
econstructor;
split.
eapply exec_straight_trans.
eexact P.
apply exec_straight_one.
simpl.
rewrite Q,
R by eauto with asmgen.
auto.
split.
intros.
apply cond_for_signed_cmp_correct.
auto.
intros.
rewrite compare_int_inv by auto.
auto with asmgen.
-
destruct (
is_immed_arith OTHER i); [|
destruct (
is_immed_arith OTHER (
Int.neg i))].
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_unsigned_cmp_correct.
auto.
apply compare_int_inv.
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_unsigned_cmp_correct.
rewrite Int.neg_involutive.
auto.
apply compare_int_inv.
+
exploit (
loadimm_correct IR14).
intros [
rs' [
P [
Q R]]].
econstructor;
split.
eapply exec_straight_trans.
eexact P.
apply exec_straight_one.
simpl.
rewrite Q,
R by eauto with asmgen.
auto.
split.
intros.
apply cond_for_unsigned_cmp_correct.
auto.
intros.
rewrite compare_int_inv by auto.
auto with asmgen.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float_cmp_correct.
auto.
apply compare_float_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float_not_cmp_correct.
auto.
apply compare_float_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float_cmp_correct.
auto.
apply compare_float_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float_not_cmp_correct.
auto.
apply compare_float_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float32_cmp_correct.
auto.
apply compare_float32_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float32_not_cmp_correct.
auto.
apply compare_float32_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float32_cmp_correct.
auto.
apply compare_float32_inv.
-
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_float32_not_cmp_correct.
auto.
apply compare_float32_inv.
-
destruct (
is_immed_arith OTHER i).
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_maskzero_correct.
auto.
intros.
apply compare_int_test_inv.
auto.
+
exploit (
loadimm_correct IR14).
intros [
rs' [
P [
Q R]]].
econstructor;
split.
eapply exec_straight_trans.
eexact P.
apply exec_straight_one.
simpl.
rewrite Q,
R by eauto with asmgen.
auto.
split.
intros.
apply cond_for_maskzero_correct.
auto.
intros.
rewrite compare_int_test_inv by auto.
auto with asmgen.
-
destruct (
is_immed_arith OTHER i).
+
econstructor;
split.
apply exec_straight_one.
simpl.
auto.
split.
intros.
apply cond_for_masknotzero_correct.
auto.
intros.
apply compare_int_test_inv.
auto.
+
exploit (
loadimm_correct IR14).
intros [
rs' [
P [
Q R]]].
econstructor;
split.
eapply exec_straight_trans.
eexact P.
apply exec_straight_one.
simpl.
rewrite Q,
R by eauto with asmgen.
auto.
split.
intros.
apply cond_for_masknotzero_correct.
auto.
intros.
rewrite compare_int_test_inv by auto.
auto with asmgen.
-
match goal with
|
H :
match c0 with Ceq | _ => _
end =
OK _ |- _ =>
destruct c0;
cbn in H;
inv H
end.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity).
cbn.
rewrite (
cmp_sbcs_carry_correct i i0 i1 i2).
destruct (
Int64.ltu (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity).
cbn.
rewrite (
cmp_sbcs_carry_correct i1 i2 i i0).
destruct (
Int64.ltu (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity).
cbn.
rewrite (
cmp_sbcs_carry_correct i1 i2 i i0).
destruct (
Int64.ltu (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity).
cbn.
rewrite (
cmp_sbcs_carry_correct i i0 i1 i2).
destruct (
Int64.ltu (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
-
match goal with
|
H :
match c0 with Ceq | _ => _
end =
OK _ |- _ =>
destruct c0;
cbn in H;
inv H
end.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite !
Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gss.
rewrite !
Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity).
cbn.
pose proof (
cmp_sbcs_signed_correct i i0 i1 i2)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign.
destruct (
Int64.lt (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite !
Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gss.
rewrite !
Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity).
cbn.
pose proof (
cmp_sbcs_signed_correct i1 i2 i i0)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign.
destruct (
Int64.lt (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite !
Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gss.
rewrite !
Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity).
cbn.
pose proof (
cmp_sbcs_signed_correct i1 i2 i i0)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign.
destruct (
Int64.lt (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
+
eexists.
split.
{
eapply exec_straight_two;
cbn;
reflexivity. }
cbn.
split.
*
intros b EVAL.
cbn in EVAL.
destruct (
rs (
IR x))
eqn:
Hr0;
cbn in *;
try discriminate;
destruct (
rs (
IR x0))
eqn:
Hr1;
cbn in *;
try discriminate;
destruct (
rs (
IR x1))
eqn:
Hr2;
cbn in *;
try discriminate;
destruct (
rs (
IR x2))
eqn:
Hr3;
cbn in *;
try discriminate.
inv EVAL.
rewrite !
Pregmap.gso by discriminate.
unfold compare_int_sbc;
cbn.
rewrite Pregmap.gss.
rewrite !
Pregmap.gso by discriminate.
rewrite Pregmap.gss.
unfold compare_int.
rewrite !
Pregmap.gso by discriminate.
rewrite !
Pregmap.gss.
rewrite Hr0,
Hr2.
cbn.
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity).
cbn.
pose proof (
cmp_sbcs_signed_correct i i0 i1 i2)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign.
destruct (
Int64.lt (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
reflexivity.
*
intros r DR.
cbn.
rewrite Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
unfold compare_int_sbc,
compare_int;
cbn.
rewrite !
Pregmap.gso
by (
intro Heq;
subst r;
cbn in DR;
discriminate).
reflexivity.
Qed.
Lemma transl_cond_correct':
forall cond args k c tbb rs m,
transl_cond cond args k =
OK c ->
exists rs',
exec_straight ge c rs m k rs' m
/\ (
forall b,
eval_condition cond (
map rs (
map preg_of args))
m =
Some b ->
eval_testcond (
cond_for_cond cond) (
incrPC (
Ptrofs.repr (
size tbb))
rs') =
Some b)
/\
forall r,
data_preg r =
true ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_cbranch_pbc:
forall cond args lbl near_labels bdy,
transl_cbranch cond args lbl near_labels =
OK (
bdy,
PCtlFlow (
Pbc (
cond_for_cond cond)
lbl)) ->
transl_cond cond args nil =
OK bdy.
Proof.
Definition outcome_undef_flags (
o:
outcome) :
outcome :=
match o with Next rs m =>
Next (
undef_flags rs)
m |
Stuck =>
Stuck end.
Lemma transl_cbranch_correct_gen:
forall f cond args lbl near_labels b m rs tbb bdy ctl,
transl_cbranch cond args lbl near_labels =
OK (
bdy,
ctl) ->
eval_condition cond (
map rs (
map preg_of args))
m =
Some b ->
exists rs' cfi (
wrap:
outcome ->
outcome),
ctl =
PCtlFlow cfi
/\
exec_straight_opt ge bdy rs m nil rs' m
/\
exec_cfi ge f cfi (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m =
wrap (
if b then goto_label f lbl (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m else
Next (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m)
/\ (
wrap Stuck =
Stuck)
/\ (
forall rs0 m0,
exists rs1,
wrap (
Next rs0 m0) =
Next rs1 m0
/\ (
forall r,
data_preg r =
true ->
rs1 r =
rs0 r)
/\
rs1 PC =
rs0 PC
/\
rs1 IR14 =
rs0 IR14)
/\
forall r,
data_preg r =
true ->
rs'#
r =
rs#
r.
Proof.
assert (
wrap_id_props:
forall (
f0:
outcome ->
outcome),
f0 = (
fun x =>
x) ->
f0 Stuck =
Stuck /\
(
forall rs0 m0,
exists rs1,
f0 (
Next rs0 m0) =
Next rs1 m0
/\ (
forall r,
data_preg r =
true ->
rs1 r =
rs0 r) /\
rs1 PC =
rs0 PC /\
rs1 IR14 =
rs0 IR14)).
{
intros.
subst.
split;
auto.
intros.
eexists;
split; [
reflexivity |
repeat split;
auto]. }
assert (
wrap_undef_props:
outcome_undef_flags Stuck =
Stuck /\
(
forall rs0 m0,
exists rs1,
outcome_undef_flags (
Next rs0 m0) =
Next rs1 m0
/\ (
forall r,
data_preg r =
true ->
rs1 r =
rs0 r) /\
rs1 PC =
rs0 PC /\
rs1 IR14 =
rs0 IR14)).
{
split;
auto.
intros.
eexists;
split; [
reflexivity |].
simpl.
repeat split;
auto;
intros;
unfold undef_flags;
destruct r;
simpl in *;
auto;
discriminate. }
intros until ctl.
intros TR EV.
unfold transl_cbranch in TR.
destruct cond;
try (
monadInv TR;
exploit transl_cond_correct';
eauto;
intros (
rs' &
A &
B &
C);
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |];
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]]).
-
destruct c;
try (
monadInv TR;
exploit transl_cond_correct';
eauto;
intros (
rs' &
A &
B &
C);
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |];
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]]).
+
destruct args as [|
a1 [|]];
try discriminate.
destruct (
Compopts.thumb tt &&
Compopts.short_branches tt &&
Int.eq i Int.zero &&
is_near_label lbl near_labels)
eqn:
Hn;
[
monadInv TR;
destruct (
is_low_ireg x)
eqn:
Hlow;
monadInv EQ0 |
monadInv TR].
*
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
apply exec_straight_one;
simpl;
auto |].
split; [|
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
simpl.
unfold eval_condition in *.
assert (
Hgso: (
incrPC (
Ptrofs.repr (
size tbb))
rs)
x =
rs x)
by (
unfold incrPC;
rewrite Pregmap.gso;
auto;
congruence).
simpl in EV.
rewrite (
ireg_of_eq _ _
EQ)
in EV.
unfold eval_branch.
rewrite Hgso.
unfold eval_testzero,
Val.mxcmpu_bool,
Val.cmpu_bool,
Val.cmp_bool,
Int.cmp,
Int.cmpu in *.
destruct (
rs x);
cbv beta iota in *;
try congruence.
apply andb_true_iff in Hn.
destruct Hn as [
Hn _].
apply andb_true_iff in Hn.
destruct Hn as [_
Hn].
apply Int.same_if_eq in Hn.
subst i.
injection EV;
intro Hb;
subst b.
reflexivity.
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
+
destruct args as [|
a1 [|]];
try discriminate.
destruct (
Compopts.thumb tt &&
Compopts.short_branches tt &&
Int.eq i Int.zero &&
is_near_label lbl near_labels)
eqn:
Hn;
[
monadInv TR;
destruct (
is_low_ireg x)
eqn:
Hlow;
monadInv EQ0 |
monadInv TR].
*
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
apply exec_straight_one;
simpl;
auto |].
split; [|
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
simpl.
unfold eval_condition in *.
assert (
Hgso: (
incrPC (
Ptrofs.repr (
size tbb))
rs)
x =
rs x)
by (
unfold incrPC;
rewrite Pregmap.gso;
auto;
congruence).
simpl in EV.
rewrite (
ireg_of_eq _ _
EQ)
in EV.
unfold eval_neg_branch.
rewrite Hgso.
unfold eval_testzero,
Val.mxcmpu_bool,
Val.cmpu_bool,
Val.cmp_bool,
Int.cmp,
Int.cmpu in *.
destruct (
rs x);
cbv beta iota in *;
try congruence.
apply andb_true_iff in Hn.
destruct Hn as [
Hn _].
apply andb_true_iff in Hn.
destruct Hn as [_
Hn].
apply Int.same_if_eq in Hn.
subst i.
injection EV;
intro Hb;
subst b.
destruct (
Int.eq _ _);
reflexivity.
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
-
destruct c;
try (
monadInv TR;
exploit transl_cond_correct';
eauto;
intros (
rs' &
A &
B &
C);
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |];
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]]).
+
destruct args as [|
a1 [|]];
try discriminate.
destruct (
Compopts.thumb tt &&
Compopts.short_branches tt &&
Int.eq i Int.zero &&
is_near_label lbl near_labels)
eqn:
Hn;
[
monadInv TR;
destruct (
is_low_ireg x)
eqn:
Hlow;
monadInv EQ0 |
monadInv TR].
*
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
apply exec_straight_one;
simpl;
auto |].
split; [|
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
simpl.
assert (
Hgso: (
incrPC (
Ptrofs.repr (
size tbb))
rs)
x =
rs x)
by (
unfold incrPC;
rewrite Pregmap.gso;
auto;
congruence).
unfold eval_branch.
rewrite Hgso.
apply andb_true_iff in Hn;
destruct Hn as [
Hn _].
apply andb_true_iff in Hn;
destruct Hn as [_
Hn].
apply Int.same_if_eq in Hn;
try subst.
unfold eval_condition in EV.
simpl in EV.
try rewrite (
ireg_of_eq _ _
EQ)
in EV.
assert (
HEV:
eval_testzero (
rs x) =
Some b).
{
unfold eval_testzero.
apply (
Val.mxcmpu_bool_correct (
Mem.valid_pointer m)).
exact EV. }
rewrite HEV.
destruct b;
reflexivity.
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
+
destruct args as [|
a1 [|]];
try discriminate.
destruct (
Compopts.thumb tt &&
Compopts.short_branches tt &&
Int.eq i Int.zero &&
is_near_label lbl near_labels)
eqn:
Hn;
[
monadInv TR;
destruct (
is_low_ireg x)
eqn:
Hlow;
monadInv EQ0 |
monadInv TR].
*
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
apply exec_straight_one;
simpl;
auto |].
split; [|
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
simpl.
assert (
Hgso: (
incrPC (
Ptrofs.repr (
size tbb))
rs)
x =
rs x)
by (
unfold incrPC;
rewrite Pregmap.gso;
auto;
congruence).
unfold eval_neg_branch.
rewrite Hgso.
apply andb_true_iff in Hn;
destruct Hn as [
Hn _].
apply andb_true_iff in Hn;
destruct Hn as [_
Hn].
apply Int.same_if_eq in Hn;
try subst.
unfold eval_condition in EV.
simpl in EV.
try rewrite (
ireg_of_eq _ _
EQ)
in EV.
unfold eval_testzero,
Val.mxcmpu_bool,
Val.cmpu_bool.
destruct (
rs x);
simpl in *;
try congruence.
injection EV;
intro;
subst.
destruct (
Int.eq _ _);
reflexivity.
all:
try (
destruct Archi.ptr64;
simpl in *;
try congruence;
destruct (_ && _)%
bool eqn:?;
simpl in *;
try congruence;
injection EV;
intro;
subst;
reflexivity).
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
*
exploit transl_cond_correct'; [
eassumption|].
intros (
rs' &
A &
B &
C).
do 2
eexists;
exists (
fun x =>
x);
split; [
reflexivity |];
split; [
apply exec_straight_opt_intro;
eexact A |].
split; [
simpl;
rewrite (
B b)
by auto;
auto |
split; [
auto |
split; [
intros;
eexists;
split; [
reflexivity |
split;
auto] |
auto]]].
Unshelve.
all:
try exact tbb.
Qed.
Lemma transl_cbranch_correct:
forall fm f cond args lbl near_labels b m rs tbb bdy,
transl_control fm (
MBcond cond args lbl)
near_labels =
OK (
bdy,
PCtlFlow (
Pbc (
cond_for_cond cond)
lbl)) ->
eval_condition cond (
map rs (
map preg_of args))
m =
Some b ->
exists rs',
exec_straight_opt ge bdy rs m nil rs' m
/\
exec_cfi ge f (
Pbc (
cond_for_cond cond)
lbl) (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m =
(
if b then goto_label f lbl (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m else
Next (
incrPC (
Ptrofs.repr (
size tbb))
rs')
m)
/\
forall r,
data_preg r =
true ->
rs'#
r =
rs#
r.
Proof.
intros until bdy.
intros TR EV.
unfold transl_control in TR.
monadInv TR.
exploit transl_cbranch_pbc;
eauto.
intros TCOND.
exploit transl_cond_correct';
eauto.
intros (
rs' &
A &
B &
C).
eexists;
split.
apply exec_straight_opt_intro.
eexact A.
split;
auto.
simpl.
rewrite (
B b)
by auto.
auto.
Qed.
Translation of arithmetic operations.
Ltac TranslOpSimpl :=
econstructor;
split;
[
apply exec_straight_one;
simpl;
unfold arith_uf_fn;
simpl;
eauto
|
split; [
try rewrite transl_shift_correct;
repeat Simpl |
intros;
repeat Simpl] ].
Correctness of the default fallback: transl_cond + Pmovite[1, 0].
Lemma transl_op_cmp_default_correct:
forall cmp args r k bc (
rs:
regset)
m,
transl_op_cmp_default cmp args r k =
OK bc ->
exists rs',
exec_straight ge bc rs m k rs' m
/\
Val.lessdef
(
Val.of_optbool (
eval_condition cmp (
map rs (
map preg_of args))
m))
(
rs' r)
/\
forall r0,
data_preg r0 =
true ->
r0 <>
r ->
rs' r0 =
rs r0.
Proof.
Correctness of the Cne special-case: Psubs/Padds + Pmovite TCeq r (SOreg r) (SOimm 1).
Lemma transl_op_cmp_cne_correct:
forall cmp args r k bc (
rs:
regset)
m,
transl_op_cmp_cne cmp args r k =
Some (
OK bc) ->
exists rs',
exec_straight ge bc rs m k rs' m
/\
Val.lessdef
(
Val.of_optbool (
eval_condition cmp (
map rs (
map preg_of args))
m))
(
rs' r)
/\
forall r0,
data_preg r0 =
true ->
r0 <>
r ->
rs' r0 =
rs r0.
Proof.
Correctness of the Ceq CLZ special-case: Psub/Padd + Pclz + Pmov(lsr #5).
Lemma transl_op_cmp_ceq_clz_correct:
forall cmp args r k bc (
rs:
regset)
m,
transl_op_cmp_ceq_clz cmp args r k =
Some (
OK bc) ->
exists rs',
exec_straight ge bc rs m k rs' m
/\
Val.lessdef
(
Val.of_optbool (
eval_condition cmp (
map rs (
map preg_of args))
m))
(
rs' r)
/\
forall r0,
data_preg r0 =
true ->
r0 <>
r ->
rs' r0 =
rs r0.
Proof.
Correctness of transl_op_cmp: dispatches to the right helper.
Lemma transl_op_cmp_correct:
forall cmp args r k bc (
rs:
regset)
m,
transl_op_cmp cmp args r k =
OK bc ->
exists rs',
exec_straight ge bc rs m k rs' m
/\
Val.lessdef
(
Val.of_optbool (
eval_condition cmp (
map rs (
map preg_of args))
m))
(
rs' r)
/\
forall r0,
data_preg r0 =
true ->
r0 <>
r ->
rs' r0 =
rs r0.
Proof.
Lemma transl_op_correct_same:
forall op args res k c (
rs:
regset)
m v,
transl_op op args res k =
OK c ->
eval_operation ge rs#
IR13 op (
map rs (
map preg_of args))
m =
Some v ->
match op with
|
Ocopy |
Ocopyimm _ |
Ocmp _ |
Osel _ |
Oselimm _ _ |
Oselimm2 _ _ _
|
Ocmpcarryu _ |
Ocmpcarry _ |
Oaddrstack _ =>
False
| _ =>
True end ->
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of res) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of res ->
preg_notin r (
destroyed_by_op op) ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_op_correct:
forall op args res k c (
rs:
regset)
m v,
transl_op op args res k =
OK c ->
eval_operation ge rs#
SP op (
map rs (
map preg_of args))
m =
Some v ->
exists rs',
exec_straight ge c rs m k rs' m
/\
Val.lessdef v rs'#(
preg_of res)
/\
forall r,
data_preg r =
true ->
r <>
preg_of res ->
preg_notin r (
destroyed_by_op op) ->
rs'#
r =
rs#
r.
Proof.
intros.
assert (
SAME:
(
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of res) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of res ->
preg_notin r (
destroyed_by_op op) ->
rs'#
r =
rs#
r) ->
exists rs',
exec_straight ge c rs m k rs' m
/\
Val.lessdef v rs'#(
preg_of res)
/\
forall r,
data_preg r =
true ->
r <>
preg_of res ->
preg_notin r (
destroyed_by_op op) ->
rs'#
r =
rs#
r).
{
intros (
rs' &
A &
B &
C).
subst v;
exists rs';
auto. }
destruct op;
try (
apply SAME;
eapply transl_op_correct_same;
eauto;
fail).
-
clear SAME;
simpl in *;
ArgsInv.
cbn in H0.
inv H0.
eexists.
split.
{
apply exec_straight_one;
reflexivity. }
split.
{
apply Val.lessdef_refl. }
reflexivity.
-
clear SAME;
simpl in *;
ArgsInv.
cbn in H0.
inv H0.
eexists.
split.
{
apply exec_straight_one;
reflexivity. }
split.
{
apply Val.lessdef_refl. }
reflexivity.
-
clear SAME;
simpl in *;
ArgsInv.
destruct (
addimm_correct x IR13 (
Ptrofs.to_int i)
k rs m)
as [
rs' [
EX [
RES OTH]]].
exists rs';
split.
auto.
split.
rewrite RES;
inv H0.
destruct (
rs IR13);
simpl;
auto.
rewrite Ptrofs.of_int_to_int;
auto.
intros;
apply OTH;
eauto with asmgen.
-
clear SAME.
simpl in H.
monadInv H.
rename x into r.
rewrite (
ireg_of_eq _ _
EQ).
exploit transl_op_cmp_correct;
eauto.
intros [
rs' [
A [
B C]]].
exists rs';
split; [
exact A|
split; [|
intros;
eapply C;
eauto]].
simpl in H0.
inv H0.
exact B.
-
clear SAME.
unfold transl_op in H;
ArgsInv.
simpl in H0;
inv H0.
assert (
D1:
data_preg (
preg_of m0) =
true)
by auto with asmgen.
assert (
D2:
data_preg (
preg_of m1) =
true)
by auto with asmgen.
destruct (
preg_of res)
as [[
ir|
fr]|
cr|]
eqn:
RES;
monadInv H.
+
inv EQ2.
rewrite (
ireg_of_eq _ _
EQ), (
ireg_of_eq _ _
EQ1)
in *.
destruct (
ireg_eq x x0);
inv H0.
*
econstructor;
split.
apply exec_straight_one;
simpl;
eauto.
split;
intros;
Simpl.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m);
simpl;
eauto.
destruct b;
eauto using Val.lessdef_normalize.
*
exploit transl_cond_correct;
eauto.
instantiate (1 :=
rs).
instantiate (1 :=
m).
intros (
rs1 &
A &
B &
C).
econstructor;
split.
eapply exec_straight_trans.
eexact A.
apply exec_straight_one.
simpl;
eauto.
auto.
split;
intros;
Simpl.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m)
as [
b|];
simpl;
auto.
rewrite (
B b)
by auto.
destruct b;
rewrite !
C by auto;
apply Val.lessdef_refl.
+
inv EQ2.
rewrite (
freg_of_eq _ _
EQ), (
freg_of_eq _ _
EQ1)
in *.
destruct (
freg_eq x x0);
inv H0.
*
econstructor;
split.
apply exec_straight_one;
simpl;
eauto.
split;
intros;
Simpl.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m);
simpl;
eauto.
destruct b;
eauto using Val.lessdef_normalize.
*
exploit transl_cond_correct;
eauto.
instantiate (1 :=
rs).
instantiate (1 :=
m).
intros [
rs1 [
A [
B C]]].
econstructor;
split.
eapply exec_straight_trans.
eexact A.
apply exec_straight_one.
simpl;
eauto.
auto.
split;
intros;
Simpl.
rewrite !
C by auto.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m)
as [
b|];
simpl;
auto.
rewrite (
B b)
by auto.
destruct b;
apply Val.lessdef_refl.
-
clear SAME.
unfold transl_op in H;
ArgsInv.
simpl in H0;
inv H0.
assert (
D1:
data_preg (
preg_of m0) =
true)
by auto with asmgen.
rewrite (
ireg_of_eq _ _
EQ1)
in *.
exploit transl_cond_correct;
eauto.
instantiate (1 :=
rs).
instantiate (1 :=
m).
intros (
rs1 &
A &
B &
C).
econstructor;
split.
eapply exec_straight_trans.
eexact A.
apply exec_straight_one.
simpl;
eauto.
auto.
split;
intros;
Simpl.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m)
as [
b|];
simpl;
auto.
rewrite (
B b)
by auto.
destruct b;
simpl.
+
rewrite C by auto.
apply Val.lessdef_refl.
+
apply Val.lessdef_refl.
-
clear SAME.
simpl in H.
monadInv H.
simpl in H0.
inv H0.
rewrite (
ireg_of_eq _ _
EQ).
exploit transl_cond_correct;
eauto.
instantiate (1 :=
rs).
instantiate (1 :=
m).
intros (
rs1 &
A &
B &
C).
econstructor;
split.
eapply exec_straight_trans.
eexact A.
apply exec_straight_one.
simpl;
eauto.
auto.
split;
intros;
Simpl.
destruct (
eval_condition c0 (
map rs (
map preg_of args))
m)
as [
b|];
simpl;
auto.
rewrite (
B b)
by auto.
destruct b;
apply Val.lessdef_refl.
-
clear SAME.
unfold transl_op in H.
ArgsInv.
cbn in H0.
inv H0.
destruct c0;
cbn in EQ5;
inv EQ5.
+
pose (
rs1 :=
compare_int rs (
rs x1) (
rs x3)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x1) (
rs x3))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity);
rewrite (
cmp_sbcs_carry_correct i i0 i1 i2);
destruct (
Int64.ltu (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x3) (
rs x1)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x3) (
rs x1))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity);
rewrite (
cmp_sbcs_carry_correct i1 i2 i i0);
destruct (
Int64.ltu (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x3) (
rs x1)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x3) (
rs x1))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity);
rewrite (
cmp_sbcs_carry_correct i1 i2 i i0);
destruct (
Int64.ltu (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x1) (
rs x3)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x1) (
rs x3))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity);
rewrite (
cmp_sbcs_carry_correct i i0 i1 i2);
destruct (
Int64.ltu (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
-
clear SAME.
unfold transl_op in H.
ArgsInv.
cbn in H0.
inv H0.
destruct c0;
cbn in EQ5;
inv EQ5.
+
pose (
rs1 :=
compare_int rs (
rs x1) (
rs x3)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x1) (
rs x3))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity);
cbn;
pose proof (
cmp_sbcs_signed_correct i i0 i1 i2)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign;
destruct (
Int64.lt (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x3) (
rs x1)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x3) (
rs x1))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity);
cbn;
pose proof (
cmp_sbcs_signed_correct i1 i2 i i0)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign;
destruct (
Int64.lt (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x3) (
rs x1)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x3) (
rs x1))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i2 i0)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i2 i0 then Int.zero else Int.one))
by (
destruct (
Int.ltu i2 i0);
reflexivity);
cbn;
pose proof (
cmp_sbcs_signed_correct i1 i2 i i0)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign;
destruct (
Int64.lt (
Int64.ofwords i1 i2) (
Int64.ofwords i i0));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
+
pose (
rs1 :=
compare_int rs (
rs x1) (
rs x3)
m).
assert (
Hx0:
rs1 x0 =
rs x0)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ1);
auto with asmgen).
assert (
Hx2:
rs1 x2 =
rs x2)
by (
subst rs1;
apply compare_int_inv;
rewrite <- (
ireg_of_eq _ _
EQ2);
auto with asmgen).
assert (
HCC:
rs1 CC =
Val.cmpu (
Mem.valid_pointer m)
Cge (
rs x1) (
rs x3))
by (
subst rs1;
reflexivity).
eexists.
split.
eapply exec_straight_three;
cbn;
reflexivity.
fold rs1;
rewrite Hx0,
Hx2,
HCC.
split.
*
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
unfold compare_int_sbc;
cbn;
rewrite Pregmap.gss;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gso by discriminate;
rewrite Pregmap.gss;
destruct (
rs x0)
eqn:
Hr0;
cbn;
try (
constructor;
fail);
destruct (
rs x1)
eqn:
Hr1;
cbn;
try (
constructor;
fail);
destruct (
rs x2)
eqn:
Hr2;
cbn;
try (
constructor;
fail);
destruct (
rs x3)
eqn:
Hr3;
cbn;
try (
constructor;
fail);
replace (
if negb (
Int.ltu i0 i2)
then Vtrue else Vfalse)
with (
Vint (
if Int.ltu i0 i2 then Int.zero else Int.one))
by (
destruct (
Int.ltu i0 i2);
reflexivity);
cbn;
pose proof (
cmp_sbcs_signed_correct i i0 i1 i2)
as Hsign;
cbv zeta in Hsign;
rewrite Hsign;
destruct (
Int64.lt (
Int64.ofwords i i0) (
Int64.ofwords i1 i2));
apply Val.lessdef_refl.
*
intros r DR Hne _;
rewrite Pregmap.gso by auto;
rewrite Pregmap.gso by auto;
unfold compare_int_sbc;
cbn;
rewrite !
Pregmap.gso by auto with asmgen;
subst rs1;
apply compare_int_inv;
auto.
Qed.
Lemma transl_memory_access_correct:
forall (
P:
regset ->
Prop) (
mk_instr_imm:
ireg ->
int ->
basic)
(
mk_instr_gen:
option (
ireg ->
shift_op ->
basic))
(
mk_immed:
int ->
int)
addr args k c (
rs:
regset)
a m m',
transl_memory_access mk_instr_imm mk_instr_gen mk_immed addr args k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
match a with Vptr _ _ =>
True | _ =>
False end ->
(
forall (
r1:
ireg) (
rs1:
regset)
n k,
Val.add rs1#
r1 (
Vint n) =
a ->
(
forall (
r:
preg),
if_preg r =
true ->
r <>
IR14 ->
rs1 r =
rs r) ->
exists rs',
exec_straight ge (
mk_instr_imm r1 n ::
k)
rs1 m k rs' m' /\
P rs') ->
match mk_instr_gen with
|
None =>
True
|
Some mk =>
(
forall (
r1:
ireg) (
sa:
shift_op)
k,
Val.add rs#
r1 (
eval_shift_op sa rs) =
a ->
exists rs',
exec_straight ge (
mk r1 sa ::
k)
rs m k rs' m' /\
P rs')
end ->
exists rs',
exec_straight ge c rs m k rs' m' /\
P rs'.
Proof.
Lemma transl_load_int_correct:
forall mk_instr is_immed dst addr args k c (
rs:
regset)
a chunk m v,
transl_memory_access_int mk_instr is_immed dst addr args k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.loadv chunk m a =
Some v ->
(
forall (
r1 r2:
ireg) (
sa:
shift_op) (
rs1:
regset),
exec_basic ge (
mk_instr r1 r2 sa)
rs1 m =
exec_load_aux chunk (
Val.add rs1#
r2 (
eval_shift_op sa rs1))
r1 rs1 m) ->
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of dst) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of dst ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_load_float_correct:
forall mk_instr is_immed dst addr args k c (
rs:
regset)
a chunk m v,
transl_memory_access_float mk_instr is_immed dst addr args k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.loadv chunk m a =
Some v ->
(
forall (
r1:
freg) (
r2:
ireg) (
n:
int) (
rs1:
regset),
exec_basic ge (
mk_instr r1 r2 n)
rs1 m =
exec_load_aux chunk (
Val.add rs1#
r2 (
Vint n))
r1 rs1 m) ->
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of dst) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of dst ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_store_int_correct:
forall mr mk_instr is_immed src addr args k c (
rs:
regset)
a chunk m m',
transl_memory_access_int mk_instr is_immed src addr args k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.storev chunk m a rs#(
preg_of src) =
Some m' ->
(
forall (
r1 r2:
ireg) (
sa:
shift_op) (
rs1:
regset),
exec_basic ge (
mk_instr r1 r2 sa)
rs1 m =
exec_store_aux chunk (
Val.add rs1#
r2 (
eval_shift_op sa rs1))
r1 rs1 m) ->
exists rs',
exec_straight ge c rs m k rs' m'
/\
forall r,
data_preg r =
true ->
preg_notin r mr ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_store_float_correct:
forall mr mk_instr is_immed src addr args k c (
rs:
regset)
a chunk m m',
transl_memory_access_float mk_instr is_immed src addr args k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.storev chunk m a rs#(
preg_of src) =
Some m' ->
(
forall (
r1:
freg) (
r2:
ireg) (
n:
int) (
rs1:
regset),
exec_basic ge (
mk_instr r1 r2 n)
rs1 m =
exec_store_aux chunk (
Val.add rs1#
r2 (
Vint n))
r1 rs1 m) ->
exists rs',
exec_straight ge c rs m k rs' m'
/\
forall r,
data_preg r =
true ->
preg_notin r mr ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_load_correct:
forall trap chunk addr args dst k c (
rs:
regset)
a m v,
transl_load trap chunk addr args dst k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.loadv chunk m a =
Some v ->
exists rs',
exec_straight ge c rs m k rs' m
/\
rs'#(
preg_of dst) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of dst ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_store_correct:
forall chunk addr args src k c (
rs:
regset)
a m m',
transl_store chunk addr args src k =
OK c ->
eval_addressing ge (
rs#
SP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.storev chunk m a rs#(
preg_of src) =
Some m' ->
exists rs',
exec_straight ge c rs m k rs' m'
/\
forall r,
data_preg r =
true ->
preg_notin r (
destroyed_by_store chunk addr) ->
rs'#
r =
rs#
r.
Proof.
Lemma extract_memcpy_builtin_arg_correct:
forall ba r i rs m b ofs,
evalopt_builtin_arg ge (
fun r:
dreg =>
rs r) (
rs#
SP)
m (
map_builtin_arg dreg_of ba) =
Some (
Vptr b i) ->
extract_memcpy_builtin_arg ba =
OK (
r,
ofs) ->
Val.add (
rs#
r) (
Vint ofs) =
Vptr b i.
Proof.
intros.
destruct ba;
try destruct ba1,
ba2;
simpl in *;
try congruence;
monadInv H0.
-
apply ireg_of_eq' in EQ.
rewrite EQ in H.
symmetry in H.
inv H.
simpl.
unfold Ptrofs.of_int.
rewrite Int.unsigned_zero,
Ptrofs.add_zero.
auto.
-
revert H.
unfold Val.offset_ptr.
autodestruct.
simpl.
rewrite Ptrofs.of_int_to_int;
auto.
intros.
inv H.
auto.
-
apply ireg_of_eq' in EQ.
rewrite EQ in H.
inv H.
auto.
Qed.
Lemma extract_memcpy_builtin_arg_data:
forall ba x ofs,
extract_memcpy_builtin_arg ba =
OK (
x,
ofs) ->
data_preg x =
true.
Proof.
intros. destruct ba; try destruct ba1, ba2; simpl in *; try monadInv H;
try congruence; destruct x0; inv EQ; auto.
Qed.
Lemma indexed_memcpy_access_correct:
forall (
mk_instr:
ireg ->
ireg ->
int ->
int ->
basic)
(
mk_immed:
int ->
int) (
ras rad:
ireg)
ofss ofsd k (
rs:
regset)
m m' l,
data_preg ras =
true ->
data_preg rad =
true ->
(
forall (
r1 r2:
ireg) (
rs1:
regset)
n1 n2 k,
data_preg r1 =
true ->
data_preg r2 =
true ->
r1 =
ras \/
r1 =
IR2 \/
r1 =
IR3 ->
r2 =
rad \/
r2 =
IR2 \/
r2 =
IR3 ->
Val.add rs1#
r1 (
Vint n1) =
Val.add rs#
ras (
Vint ofss) ->
Val.add rs1#
r2 (
Vint n2) =
Val.add rs#
rad (
Vint ofsd) ->
(
forall r:
preg,
data_preg r =
true ->
preg_notin r (
R2 ::
R3 ::
l) ->
rs1 r =
rs r) ->
exists rs',
exec_straight ge (
mk_instr r1 r2 n1 n2 ::
k)
rs1 m k rs' m'
/\
(
forall r:
preg,
data_preg r =
true ->
preg_notin r (
R2 ::
R3 ::
l) ->
rs r =
rs' r)) ->
exists rs',
exec_straight ge
(
indexed_memcpy_access mk_instr mk_immed ras rad ofss ofsd k)
rs m k rs' m'
/\
(
forall r:
preg,
data_preg r =
true ->
preg_notin r (
R2 ::
R3 ::
l) ->
rs r =
rs' r).
Proof.
intros until l.
intros HDS HDD SEM.
unfold indexed_memcpy_access;
destruct (
Int.eq ofss (
mk_immed ofss))
eqn:
HIMM1,
(
Int.eq ofsd (
mk_immed ofsd))
eqn:
HIMM2,
(
PregEq.eq ras IR3), (
PregEq.eq rad IR3),
(
PregEq.eq ras IR2), (
PregEq.eq rad IR2);
try (
apply Int.same_if_eq in HIMM1;
rewrite <-
HIMM1);
try (
apply Int.same_if_eq in HIMM2;
rewrite <-
HIMM2);
simpl;
try congruence;
auto.
1-3,8:
destruct (
addimm_correct IR2 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr ras IR2 ofss (
mk_immed ofsd) ::
bi k)
rs m)
as (
rs1 &
A &
B &
C);
specialize SEM with ras IR2 rs1 ofss (
mk_immed ofsd)
k.
10,13,14,16,18:
destruct (
addimm_correct IR2 ras (
Int.sub ofss (
mk_immed ofss))
(
mk_instr IR2 rad (
mk_immed ofss)
ofsd ::
bi k)
rs m)
as (
rs1 &
A &
B &
C);
specialize SEM with IR2 rad rs1 (
mk_immed ofss)
ofsd k.
5-9:
destruct (
addimm_correct IR3 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr ras IR3 ofss (
mk_immed ofsd) ::
bi k)
rs m)
as (
rs1 &
A &
B &
C);
specialize SEM with ras IR3 rs1 ofss (
mk_immed ofsd)
k.
15-18:
destruct (
addimm_correct IR3 ras (
Int.sub ofss (
mk_immed ofss))
(
mk_instr IR3 rad (
mk_immed ofss)
ofsd ::
bi k)
rs m)
as (
rs1 &
A &
B &
C);
specialize SEM with IR3 rad rs1 (
mk_immed ofss)
ofsd k.
1-18:
destruct SEM as (
rs2 &
D &
E);
try congruence;
simpl;
auto;
try (
rewrite C;
auto;
try congruence;
fail);
try rewrite B,
Val.add_assoc;
f_equal;
simpl;
try rewrite Int.sub_add_opp,
Int.add_assoc,
(
Int.add_commut (
Int.neg _)),
Int.add_neg_zero,
Int.add_zero;
auto;
try (
destruct l;
intros ? ?; (
intros (? & ? & ?) ||
intros (? & ?));
apply C;
try apply data_if_preg;
auto);
exists rs2;
split;
auto;
eapply exec_straight_trans;
eauto.
1:
destruct (
addimm_correct IR2 rad (
Int.sub ofsd (
mk_immed ofsd))
(
addimm IR3 ras (
Int.sub ofss (
mk_immed ofss))
(
mk_instr IR3 IR2 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k))
rs m)
as (
rs1 &
A &
B &
C);
destruct (
addimm_correct IR3 ras (
Int.sub ofss (
mk_immed ofss))
(
mk_instr IR3 IR2 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k)
rs1 m)
as (
rs2 &
D &
E &
F);
specialize SEM with IR3 IR2 rs2 (
mk_immed ofss) (
mk_immed ofsd)
k.
2,3,6,8:
destruct (
addimm_correct IR3 ras (
Int.sub ofss (
mk_immed ofss))
(
addimm IR2 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr IR3 IR2 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k))
rs m)
as (
rs1 &
A &
B &
C);
destruct (
addimm_correct IR2 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr IR3 IR2 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k)
rs1 m)
as (
rs2 &
D &
E &
F);
specialize SEM with IR3 IR2 rs2 (
mk_immed ofss) (
mk_immed ofsd)
k.
6-9:
destruct (
addimm_correct IR2 ras (
Int.sub ofss (
mk_immed ofss))
(
addimm IR3 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr IR2 IR3 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k))
rs m)
as (
rs1 &
A &
B &
C);
destruct (
addimm_correct IR3 rad (
Int.sub ofsd (
mk_immed ofsd))
(
mk_instr IR2 IR3 (
mk_immed ofss) (
mk_immed ofsd) ::
bi k)
rs1 m)
as (
rs2 &
D &
E &
F);
specialize SEM with IR2 IR3 rs2 (
mk_immed ofss) (
mk_immed ofsd)
k.
all:
destruct SEM as (
rs3 &
G &
H);
try congruence;
simpl;
try (
rewrite F;
simpl;
try congruence;
rewrite B,
Val.add_assoc;
f_equal);
try (
rewrite E,
Val.add_assoc;
f_equal;
try (
rewrite C;
try congruence));
simpl;
try rewrite Int.sub_add_opp,
Int.add_assoc, (
Int.add_commut (
Int.neg _)),
Int.add_neg_zero,
Int.add_zero;
auto;
try (
destruct l;
intros ? ?; (
intros (? & ? & ?) ||
intros (? & ?));
rewrite F;
try apply data_if_preg;
auto;
apply C;
try apply data_if_preg;
auto);
exists rs3;
split;
auto;
do 2 (
eapply exec_straight_trans;
eauto).
Qed.
Lemma exec_memcpy_aux_general:
forall (
rs rs1:
regset) (
r1 r2 r1' r2':
ireg)
i1 i2 i1' i2' sz m m' va1 va2 vargs b1 b2 l
(
HVARGS:
va2 ::
va1 ::
nil =
vargs)
(
VA1:
evalopt_builtin_arg ge (
fun r :
dreg =>
rs r) (
rs IR13)
m (
map_builtin_arg dreg_of b1) =
Some va1)
(
VA2:
evalopt_builtin_arg ge (
fun r :
dreg =>
rs r) (
rs IR13)
m (
map_builtin_arg dreg_of b2) =
Some va2)
(
HRS:
extract_memcpy_builtin_arg b1 =
OK (
r1,
i1))
(
HRD:
extract_memcpy_builtin_arg b2 =
OK (
r2,
i2))
(
VD1:
Val.add (
rs1 r1') (
Vint i1') =
Val.add (
rs r1) (
Vint i1))
(
VD2:
Val.add (
rs1 r2') (
Vint i2') =
Val.add (
rs r2) (
Vint i2))
(
HMEM:
memcpy_run (
atomic sz)
vargs m =
Some m')
(
HL:
forall r:
preg,
In r (
map DR l) -> (
DR r2) <>
r),
exec_memcpy_aux l r1' r2' (
Ofs i1') (
Ofs i2') (
Zpos sz)
rs1 m =
Next (
undef_regs (
map DR l)
rs1)
m'.
Proof.
Lemma transl_memcpy_correct:
forall sz sz' args vargs vargs' m k c (
rs:
regset)
m',
Val.lessdef_list vargs vargs' ->
Z_to_memcpy_typ (
Zpos sz) =
Some sz' ->
transl_memcpy sz' args k =
OK c ->
evalopt_builtin_args ge (
fun r:
dreg =>
rs r) (
rs SP)
m (
map (
map_builtin_arg dreg_of)
args) =
Some vargs' ->
memcpy_run (
atomic sz)
vargs' m =
Some m' ->
exists rs',
exec_straight ge c rs m k rs' m'
/\
forall r,
data_preg r =
true ->
preg_notin r (
destroyed_by_memcpy sz') ->
rs#
r =
rs'#
r.
Proof.
assert (
forall x r,
proj_sumbool (
preg_eq x r) =
true ->
x =
r)
as HPREGEQ.
{
intros.
destruct (
preg_eq x r);
auto.
simpl in *.
congruence. }
intros.
apply memcpy_typ_Z in H0.
destruct args as [|
a1[|
a2[]]];
simpl in H1;
try congruence.
monadInv H1.
unfold select_memcpy_inst in *.
assert (
Z.to_pos (
memcpy_typ_to_Z sz') =
Z.to_pos (
Z.pos sz)).
{
destruct sz';
rewrite H0;
auto. }
simpl in H2.
revert H2.
do 2
autodestruct.
intros.
destruct sz';
inv H0.
1-3:
apply indexed_memcpy_access_correct;
eauto;
try eapply extract_memcpy_builtin_arg_data;
eauto;
intros;
eexists;
split;
try (
apply exec_straight_one;
simpl;
destruct (
PregEq.eq r2 IR14)
as [
HEQ1|
HEQ1];
simpl;
try (
apply data_preg_not_R14 in HEQ1;
intuition);
inversion H2;
eapply exec_memcpy_aux_general;
eauto;
intros;
inv H10;
exploit extract_memcpy_builtin_arg_data;
try apply data_preg_not_R14;
eauto);
intros;
simpl;
rewrite Pregmap.gso,
H9;
try apply data_if_preg;
try apply data_preg_not_R14;
auto.
repeat autodestruct;
intros.
-
unfold destroyed_by_memcpy.
rewrite EQ3.
apply indexed_memcpy_access_correct;
eauto.
1,2:
eapply extract_memcpy_builtin_arg_data;
eauto.
intros.
eexists.
split.
+
apply exec_straight_one.
simpl.
inversion H2.
eapply exec_memcpy_aux_general;
eauto.
intros.
inv H10.
congruence.
inv H12.
+
intros.
revert H11.
simpl.
intros (? & ? & ?).
rewrite Pregmap.gso,
H9;
simpl;
auto.
-
unfold destroyed_by_memcpy.
rewrite EQ5,
EQ4.
apply indexed_memcpy_access_correct;
eauto.
1,2:
eapply extract_memcpy_builtin_arg_data;
eauto.
clear EQ3.
inv e.
intros.
eexists.
split.
+
apply exec_straight_one.
simpl.
rewrite EQ4,
orb_true_l.
apply data_preg_not_R14 in H4.
destruct (
PregEq.eq r2 IR10), (
PregEq.eq r2 IR14);
try congruence;
simpl.
inv e.
destruct H6 as [|[]];
congruence.
inversion H2.
eapply exec_memcpy_aux_general;
eauto.
intros.
inv H10.
congruence.
inv H12.
congruence.
inv H10.
+
intros.
revert H11.
simpl.
intros (? & ? & ? & ?).
rewrite !
Pregmap.gso,
H9;
auto.
simpl.
auto.
apply data_preg_not_R14.
auto.
-
unfold destroyed_by_memcpy.
rewrite EQ5,
EQ4.
apply indexed_memcpy_access_correct;
eauto.
1,2:
eapply extract_memcpy_builtin_arg_data;
eauto.
intros.
eexists.
split.
+
apply exec_straight_one.
simpl.
rewrite EQ4,
orb_true_l.
apply data_preg_not_R14 in H4.
destruct (
PregEq.eq r2 IR11), (
PregEq.eq r2 IR14);
try congruence;
simpl.
inv e.
destruct H6 as [|[]];
congruence.
inversion H2.
eapply exec_memcpy_aux_general;
eauto.
intros.
inv H10.
congruence.
inv H12.
eapply extract_memcpy_builtin_arg_data in EQ1;
eauto.
apply data_preg_not_R14.
auto.
inv H10.
+
intros.
revert H11.
simpl.
intros (? & ? & ? & ?).
rewrite !
Pregmap.gso,
H9;
simpl;
auto.
apply data_preg_not_R14.
auto.
-
unfold destroyed_by_memcpy.
rewrite EQ5,
EQ4.
apply indexed_memcpy_access_correct;
eauto.
1,2:
eapply extract_memcpy_builtin_arg_data;
eauto.
intros.
eexists.
split.
+
apply exec_straight_one.
simpl.
unfold ls_double_valid_regs,
ls_double_next_reg.
destruct (
PregEq.eq IR11 IR11);
try congruence.
assert (
x1 <>
IR10 /\
x1 <>
IR11)
as [
HR1 HR2].
{
apply orb_prop in EQ3.
destruct EQ3;
apply HPREGEQ in H10;
inv H10;
intuition congruence. }
rewrite EQ4.
simpl.
clear e.
destruct (
PregEq.eq r2 IR10), (
PregEq.eq r2 IR11);
try congruence;
simpl.
1,2:
inv e;
destruct H6 as [|[]];
congruence.
inversion H2.
eapply exec_memcpy_aux_general;
eauto.
intros.
inv H10.
congruence.
inv H12.
congruence.
inv H10.
+
intros.
revert H11.
simpl.
intros (? & ? & ? & ? & ? & ?).
rewrite !
Pregmap.gso,
H9;
auto.
simpl.
repeat split;
auto.
-
unfold destroyed_by_memcpy.
rewrite EQ5,
EQ4.
apply indexed_memcpy_access_correct;
eauto.
1,2:
eapply extract_memcpy_builtin_arg_data;
eauto.
intros.
eexists.
split.
+
apply exec_straight_one.
simpl.
unfold ls_double_valid_regs,
ls_double_next_reg.
destruct (
PregEq.eq IR9 IR9);
try congruence.
rewrite EQ4.
simpl.
clear e.
destruct (
PregEq.eq x1 IR8).
inv e.
simpl in *.
congruence.
destruct (
PregEq.eq x1 IR9).
inv e.
simpl in *.
congruence.
destruct (
PregEq.eq r2 IR8), (
PregEq.eq r2 IR9);
try congruence;
simpl.
1,2:
inv e;
destruct H6 as [|[]];
congruence.
inversion H2.
eapply exec_memcpy_aux_general;
eauto.
intros.
inv H10.
congruence.
inv H12.
congruence.
inv H10.
+
intros.
revert H11.
simpl.
intros (? & ? & ? & ? & ? & ?).
rewrite !
Pregmap.gso,
H9;
auto.
simpl.
repeat split;
auto.
Qed.
Lemma make_epilogue_correct:
forall tge f m stk soff cs m' ms rs tm,
Mach.load_stack m (
Vptr stk soff)
Tptr (
fn_link_ofs f) =
Some (
parent_sp cs) ->
Mach.load_stack m (
Vptr stk soff)
Tptr (
fn_retaddr_ofs f) =
Some (
PAC.pointer_auth_encode (
fn_retaddr_pac f) (
parent_ra cs) (
parent_sp cs)) ->
Mem.free m stk 0 (
fn_stacksize f) =
Some m' ->
agree ms (
Vptr stk soff)
rs ->
Mem.extends m tm ->
match_stack tge cs ->
(
function_preserves_IR14 f =
true ->
rs#
RA =
parent_ra cs) ->
exists rs' tm',
exec_straight ge (
make_epilogue f)
rs tm nil rs' tm'
/\
agree ms (
parent_sp cs)
rs'
/\
Mem.extends m' tm'
/\
rs'#
SP =
parent_sp cs
/\
rs'#
RA =
parent_ra cs
/\ (
forall r,
if_preg r =
true ->
r <>
SP ->
r <>
RA ->
rs'#
r =
rs#
r).
Proof.
Correctness of preserves_IR14
Lemma undef_flags_IR14:
forall rs,
undef_flags rs IR14 =
rs IR14.
Proof.
reflexivity.
Qed.
Lemma compare_int_IR14:
forall rs v1 v2 m,
compare_int rs v1 v2 m IR14 =
rs IR14.
Proof.
Lemma compare_int_add_IR14:
forall rs v1 v2 m,
compare_int_add rs v1 v2 m IR14 =
rs IR14.
Proof.
Lemma compare_int_test_IR14:
forall rs v1 v2,
compare_int_test rs v1 v2 IR14 =
rs IR14.
Proof.
Lemma compare_float_IR14:
forall rs v1 v2,
compare_float rs v1 v2 IR14 =
rs IR14.
Proof.
intros.
unfold compare_float.
destruct v1;
destruct v2;
Simpl.
Qed.
Lemma compare_float32_IR14:
forall rs v1 v2,
compare_float32 rs v1 v2 IR14 =
rs IR14.
Proof.
Remark indexed_memory_access_eq:
forall mk_instr mk_immed base n k,
Int.eq n (
mk_immed n) =
true ->
indexed_memory_access mk_instr mk_immed base n k =
mk_instr base n ::
k.
Proof.
Lemma exec_load_aux_IR14:
forall chunk addr (
rd:
ireg)
rs m rs' m',
exec_load_aux chunk addr rd rs m =
Next rs' m' ->
IR rd <>
IR IR14 ->
rs' IR14 =
rs IR14.
Proof.
Lemma exec_store_aux_IR14:
forall chunk addr (
rf:
preg)
rs m rs' m',
exec_store_aux chunk addr rf rs m =
Next rs' m' ->
rs' IR14 =
rs IR14.
Proof.
Lemma exec_straight_length:
forall c rs m c' rs' m',
exec_straight ge c rs m c' rs' m' ->
(
length c >
length c')%
nat.
Proof.
induction 1; simpl; lia.
Qed.
Lemma exec_straight_singleton:
forall i k rs m rs' m',
exec_straight ge (
i ::
k)
rs m k rs' m' ->
exec_basic ge i rs m =
Next rs' m'.
Proof.
Lemma exec_straight_singleton_bi:
forall (
i:
basic)
k rs m rs' m',
exec_straight ge (
i ::
bi k)
rs m k rs' m' ->
exec_basic ge i rs m =
Next rs' m'.
Proof.
Lemma exec_straight_IR14:
forall c rs m k rs' m',
exec_straight ge c rs m k rs' m' ->
(
forall i rs1 m1 rs2 m2,
In i c ->
exec_basic ge i rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
rs' IR14 =
rs IR14.
Proof.
induction 1;
intros.
-
eapply H0;
eauto.
left;
auto.
-
transitivity (
rs2 IR14).
+
apply IHexec_straight.
intros.
eapply H1;
eauto.
right;
auto.
+
eapply H1;
eauto.
left;
auto.
Qed.
Lemma exec_straight_determ:
forall c rs m c' rs1 m1 rs2 m2,
exec_straight ge c rs m c' rs1 m1 ->
exec_straight ge c rs m c' rs2 m2 ->
rs1 =
rs2 /\
m1 =
m2.
Proof.
induction 1;
intros H2;
inv H2;
try (
exfalso;
exploit exec_straight_length;
eauto;
simpl;
lia).
-
match goal with H1:
exec_basic _ _ _ _ = _,
H2:
exec_basic _ _ _ _ = _ |- _ =>
rewrite H1 in H2;
inv H2;
auto end.
-
match goal with H1:
exec_basic _ _ _ _ = _,
H2:
exec_basic _ _ _ _ = _ |- _ =>
rewrite H1 in H2;
inv H2;
eauto end.
Qed.
Remark compare_int_IR14':
forall rs v1 v2 m r,
arith_comparison_ro_compare r rs v1 v2 m IR14 =
rs IR14.
Proof.
Remark compare_float_IR14':
forall rs v1 v2 r,
arith_comparison_ff_compare r rs v1 v2 IR14 =
rs IR14.
Proof.
Remark compare_float_zero_IR14:
forall r rs v1 v2,
arith_comparison_f_compare r rs v1 v2 IR14 =
rs IR14.
Proof.
Lemma compare_int_if_preg:
forall rs v1 v2 m r,
if_preg r =
true ->
compare_int rs v1 v2 m r =
rs r.
Proof.
intros.
unfold compare_int.
destruct r;
try discriminate;
reflexivity.
Qed.
Lemma compare_int_test_if_preg:
forall rs v1 v2 r,
if_preg r =
true ->
compare_int_test rs v1 v2 r =
rs r.
Proof.
intros.
unfold compare_int_test.
destruct r;
try discriminate;
reflexivity.
Qed.
Lemma compare_float_if_preg:
forall rs v1 v2 r,
if_preg r =
true ->
compare_float rs v1 v2 r =
rs r.
Proof.
intros.
unfold compare_float.
destruct v1;
destruct v2;
(
destruct r;
try discriminate;
reflexivity).
Qed.
Lemma compare_float32_if_preg:
forall rs v1 v2 r,
if_preg r =
true ->
compare_float32 rs v1 v2 r =
rs r.
Proof.
intros.
unfold compare_float32.
destruct v1;
destruct v2;
(
destruct r;
try discriminate;
reflexivity).
Qed.
Lemma transl_cond_correct_strong:
forall cond args k c rs m,
transl_cond cond args k =
OK c ->
cond_preserves_IR14 cond =
true ->
exists rs',
exec_straight ge c rs m k rs' m
/\
forall r,
if_preg r =
true ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_cond_preserves_IR14:
forall cond args k c rs m,
transl_cond cond args k =
OK c ->
cond_preserves_IR14 cond =
true ->
forall rs' m',
exec_straight ge c rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
Lemma exec_straight_pnop_IR14:
forall rs m rs' m',
exec_straight ge (
Pnop false ::
nil)
rs m nil rs' m' ->
rs' IR14 =
rs IR14.
Proof.
intros. inv H. simpl in *. inv H4. auto.
inv H8.
Qed.
Lemma transl_cbranch_preserves_IR14:
forall cond args lbl near_labels bdy ctl rs m,
transl_cbranch cond args lbl near_labels =
OK (
bdy,
ctl) ->
cond_preserves_IR14 cond =
true ->
forall rs' m',
exec_straight_opt ge bdy rs m nil rs' m' ->
rs' IR14 =
rs IR14.
Proof.
IR14 preservation for transl_op
Local Hint Extern 1 (
FR _ <>
IR _) =>
discriminate :
asmgen.
Local Hint Extern 1 (
IR _ <>
FR _) =>
discriminate :
asmgen.
Local Hint Extern 1 (_ <> _) =>
apply not_eq_sym :
asmgen.
Lemma exec_straight_two_IR14:
forall i1 i2 k0 rs0 m0 rs0' m0',
exec_straight ge (
i1 ::
i2 ::
k0)
rs0 m0 k0 rs0' m0' ->
(
forall rs1 m1 rs2 m2,
exec_basic ge i1 rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
(
forall rs1 m1 rs2 m2,
exec_basic ge i2 rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
rs0' IR14 =
rs0 IR14.
Proof.
intros i1 i2 k0 rs0 m0 rs0' m0' EXEC HI1 HI2.
remember (
i1 ::
i2 ::
k0)
as c.
remember k0 as c'.
revert i1 i2 k0 Heqc Heqc' HI1 HI2.
induction EXEC;
intros;
subst.
-
injection Heqc;
intros;
subst.
exfalso.
assert (
length (
i2 ::
k0) =
length k0)
by congruence.
simpl in *.
lia.
-
injection Heqc;
intros;
subst.
inversion EXEC;
subst.
+
transitivity (
rs2 IR14); [
eapply HI2;
eauto |
eapply HI1;
eauto].
+
exfalso.
exploit exec_straight_length;
eauto.
simpl.
lia.
Qed.
Lemma exec_straight_three_IR14:
forall i1 i2 i3 k0 rs0 m0 rs0' m0',
exec_straight ge (
i1 ::
i2 ::
i3 ::
k0)
rs0 m0 k0 rs0' m0' ->
(
forall rs1 m1 rs2 m2,
exec_basic ge i1 rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
(
forall rs1 m1 rs2 m2,
exec_basic ge i2 rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
(
forall rs1 m1 rs2 m2,
exec_basic ge i3 rs1 m1 =
Next rs2 m2 ->
rs2 IR14 =
rs1 IR14) ->
rs0' IR14 =
rs0 IR14.
Proof.
intros i1 i2 i3 k0 rs0 m0 rs0' m0' EXEC HI1 HI2 HI3.
remember (
i1 ::
i2 ::
i3 ::
k0)
as c.
remember k0 as c'.
revert i1 i2 i3 k0 Heqc Heqc' HI1 HI2 HI3.
induction EXEC;
intros;
subst.
-
injection Heqc;
intros;
subst.
exfalso.
assert (
length (
i2 ::
i3 ::
k0) =
length k0)
by congruence.
simpl in *.
lia.
-
injection Heqc;
intros;
subst.
transitivity (
rs2 IR14); [|
eapply HI1;
eauto].
eapply exec_straight_two_IR14;
eauto.
Qed.
Default-fallback IR14 preservation.
Lemma transl_op_cmp_default_preserves_IR14:
forall cmp args res r k bc (
rs:
regset)
m,
ireg_of res =
OK r ->
transl_op_cmp_default cmp args r k =
OK bc ->
cond_preserves_IR14 cmp =
true ->
forall rs' m',
exec_straight ge bc rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
Cne special-case IR14 preservation.
Lemma transl_op_cmp_cne_preserves_IR14:
forall cmp args res r k bc (
rs:
regset)
m,
ireg_of res =
OK r ->
transl_op_cmp_cne cmp args r k =
Some (
OK bc) ->
forall rs' m',
exec_straight ge bc rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
intros cmp args res r k bc rs m IRG TR rs' m' EXEC.
unfold transl_op_cmp_cne in TR.
destruct cmp;
try discriminate.
-
destruct c;
try discriminate.
destruct args as [|
a1 [|
a2 [|? ?]]];
try discriminate.
inv TR.
monadInv H0.
eapply exec_straight_two_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
rewrite Pregmap.gso by (
intro;
apply (
ireg_of_not_R14' _ _
IRG);
congruence).
apply compare_int_IR14.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
-
destruct c;
try discriminate.
destruct args as [|
a1 [|? ?]];
try discriminate.
destruct (
is_immed_arith OTHER i)
eqn:
HIM.
{
inv TR.
monadInv H0.
eapply exec_straight_two_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
rewrite Pregmap.gso by (
intro;
apply (
ireg_of_not_R14' _ _
IRG);
congruence).
apply compare_int_IR14.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl. }
destruct (
is_immed_arith OTHER (
Int.neg i))
eqn:
HIMN;
try discriminate.
inv TR.
monadInv H0.
eapply exec_straight_two_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
rewrite Pregmap.gso by (
intro;
apply (
ireg_of_not_R14' _ _
IRG);
congruence).
apply compare_int_add_IR14.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
Qed.
Ceq CLZ special-case IR14 preservation.
Lemma transl_op_cmp_ceq_clz_preserves_IR14:
forall cmp args res r k bc (
rs:
regset)
m,
ireg_of res =
OK r ->
transl_op_cmp_ceq_clz cmp args r k =
Some (
OK bc) ->
forall rs' m',
exec_straight ge bc rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
intros cmp args res r k bc rs m IRG TR rs' m' EXEC.
unfold transl_op_cmp_ceq_clz in TR.
destruct cmp;
try discriminate.
-
destruct c;
try discriminate.
destruct args as [|
a1 [|
a2 [|? ?]]];
try discriminate.
inv TR.
monadInv H0.
eapply exec_straight_three_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
-
destruct c;
try discriminate.
destruct args as [|
a1 [|
a2 [|? ?]]];
try discriminate.
inv TR.
monadInv H0.
eapply exec_straight_three_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
-
destruct c;
try discriminate.
destruct args as [|
a1 [|? ?]];
try discriminate.
destruct (
Int.eq i Int.zero)
eqn:
HNZ.
{
inv TR.
monadInv H0.
eapply exec_straight_two_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl. }
destruct (
is_immed_arith OTHER i)
eqn:
HIM.
{
inv TR.
monadInv H0.
eapply exec_straight_three_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl. }
destruct (
is_immed_arith OTHER (
Int.neg i))
eqn:
HIMN;
try discriminate.
inv TR.
monadInv H0.
eapply exec_straight_three_IR14.
**
exact EXEC.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
**
intros ?
rs1 ?
m1 ?
rs2 ?
m2 HEX.
simpl in HEX.
inv HEX.
Simpl.
Qed.
Top-level dispatcher: matches the structure of transl_op_cmp.
Lemma transl_op_cmp_preserves_IR14:
forall cmp args res r k bc (
rs:
regset)
m,
ireg_of res =
OK r ->
transl_op_cmp cmp args r k =
OK bc ->
cond_preserves_IR14 cmp =
true ->
forall rs' m',
exec_straight ge bc rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
Lemma transl_op_preserves_IR14:
forall op args res k c (
rs:
regset)
m,
transl_op op args res k =
OK c ->
preserves_IR14 (
MBop op args res) =
true ->
forall rs' m',
exec_straight ge c rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
Lemma undef_regs_pres:
forall rl (
rs:
regset)
r,
~
In r rl ->
undef_regs rl rs r =
rs r.
Proof.
induction rl;
simpl;
intros;
auto.
rewrite IHrl by tauto.
apply Pregmap.gso.
intuition.
Qed.
Lemma exec_memcpy_aux_Ofs_IR14:
forall dregs ras rad ofs1 ofs2 sz (
rs:
regset)
m rs' m',
exec_memcpy_aux dregs ras rad (
Ofs ofs1) (
Ofs ofs2)
sz rs m =
Next rs' m' ->
~
In (
IR IR14 :
dreg)
dregs ->
rs' IR14 =
rs IR14.
Proof.
Lemma addimm_preserves_IR14:
forall r1 r2 n k (
rs:
regset)
m rs' m',
exec_straight ge (
addimm r1 r2 n k)
rs m k rs' m' ->
r1 <>
IR14 ->
rs' IR14 =
rs IR14.
Proof.
intros.
destruct (
addimm_correct r1 r2 n k rs m)
as (
rs1 &
EX1 & _ &
OTH1).
exploit exec_straight_determ.
eexact H.
eexact EX1.
intros [<- _].
apply OTH1;
eauto with asmgen.
Qed.
Lemma exec_straight_suffix:
forall c rs m c2 rs2 m2 c3 rs3 m3,
exec_straight ge c rs m c3 rs3 m3 ->
exec_straight ge c rs m c2 rs2 m2 ->
(
length c2 >
length c3)%
nat ->
exec_straight ge c2 rs2 m2 c3 rs3 m3.
Proof.
induction 1;
intros EX2 HLEN;
inv EX2;
match goal with
|
H1:
exec_basic _ ?
i _ _ = _,
H2:
exec_basic _ ?
i _ _ = _ |- _ =>
rewrite H1 in H2;
inv H2
end.
-
lia.
-
exploit exec_straight_length;
eauto;
lia.
-
auto.
-
eapply IHexec_straight;
eauto.
Qed.
Lemma indexed_memcpy_access_preserves_IR14:
forall mk_instr mk_immed ras rad n1 n2 k (
rs:
regset)
m rs' m',
exec_straight ge (
indexed_memcpy_access mk_instr mk_immed ras rad n1 n2 k)
rs m k rs' m' ->
(
forall ras' rad' n1' n2' rs0 m0 rs0' m0',
exec_basic ge (
mk_instr ras' rad' n1' n2')
rs0 m0 =
Next rs0' m0' ->
rs0' IR14 =
rs0 IR14) ->
rs' IR14 =
rs IR14.
Proof.
Lemma transl_memcpy_preserves_IR14:
forall sz bargs k c (
rs:
regset)
m,
transl_memcpy sz bargs k =
OK c ->
preserves_IR14 (
MBmemcpy sz bargs) =
true ->
forall rs' m',
exec_straight ge c rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
intros sz bargs k c rs m TR PRES rs' m' EXEC.
destruct sz;
simpl in PRES;
try discriminate.
unfold transl_memcpy in TR.
destruct bargs as [|
ba1 [|
ba2 [|]]];
monadInv TR.
apply orb_true_iff in PRES.
destruct (
Archi.expanse_memcpy_fpu)
eqn:
EFPU;
destruct (
thumb tt)
eqn:
ETHUMB;
try (
exfalso;
destruct PRES;
discriminate).
all:
cbv delta [
select_memcpy_inst]
in EXEC;
rewrite ?
EFPU in EXEC;
cbv beta iota in EXEC.
all:
try rewrite ETHUMB in EXEC.
all:
cbv beta zeta in EXEC.
all:
try (
destruct (
preg_eq x1 IR8 ||
preg_eq x1 IR9);
cbv beta iota in EXEC).
all:
eapply indexed_memcpy_access_preserves_IR14; [
eexact EXEC |].
all:
intros;
cbv beta in *.
all:
first
[
eapply exec_memcpy_aux_Ofs_IR14; [
eassumption |];
simpl;
intuition discriminate
|
simpl in *;
match goal with H: (
if ?
b then _
else _) = _ |- _ =>
destruct b;
try discriminate end;
eapply exec_memcpy_aux_Ofs_IR14; [
eassumption |];
simpl;
intuition discriminate ].
Qed.
Lemma transl_instr_basic_preserves_IR14:
forall f i r12 k c (
rs:
regset)
m,
transl_instr_basic f i r12 k =
OK c ->
preserves_IR14 i =
true ->
forall rs' m',
exec_straight ge c rs m k rs' m' ->
rs' IR14 =
rs IR14.
Proof.
End CONSTRUCTORS.