Correctness proof for x86-64 generation: auxiliary results.
Require Import Coqlib.
Require Import AST Errors Integers Floats Values Memory Globalenvs.
Require Import Op Locations Conventions Mach Asm.
Require Import Asmgen Asmgenproof0.
Require Import Blockset Footprint InteractionSemantics MemOpFP Op_fp
Mach_local ASM_local asmgen asmgen_proof0 Asmgenproof1.
Local Open Scope error_monad_scope.
Local Notation footprint :=
FP.t.
Local Notation empfp :=
FP.emp.
Correspondence between Mach registers and x86 registers
Useful properties of the PC register.
Useful simplification tactic
Correctness of x86-64 constructor functions
TODO: strenghening correctness with footprint
Section CONSTRUCTORS.
Variable ge:
genv.
Variable fn:
function.
Smart constructor for moves.
Lemma mk_mov_correct:
forall rd rs k c rs1 m,
mk_mov rd rs k =
OK c ->
exists rs2,
exec_straight ge fn c rs1 m empfp k rs2 m
/\
rs2#
rd =
rs1#
rs
/\
forall r,
data_preg r =
true ->
r <>
rd ->
rs2#
r =
rs1#
r.
Proof.
unfold mk_mov;
intros.
destruct rd;
try (
monadInv H);
destruct rs;
monadInv H.
mov *)
econstructor.
split.
apply exec_straight_one.
simpl.
eauto.
auto.
auto.
split.
Simplifs.
intros;
Simplifs.
movsd *)
econstructor.
split.
apply exec_straight_one.
simpl.
eauto.
auto.
auto.
split.
Simplifs.
intros;
Simplifs.
Qed.
Properties of division
Smart constructor for shrx
Lemma mk_shrximm_correct:
forall n k c (
rs1:
regset)
v m,
mk_shrximm n k =
OK c ->
Val.shrx (
rs1#
RAX) (
Vint n) =
Some v ->
exists rs2,
exec_straight ge fn c rs1 m empfp k rs2 m
/\
rs2#
RAX =
v
/\
forall r,
data_preg r =
true ->
r <>
RAX ->
r <>
RCX ->
rs2#
r =
rs1#
r.
Proof.
Smart constructor for shrxl
Lemma mk_shrxlimm_correct:
forall n k c (
rs1:
regset)
v m,
mk_shrxlimm n k =
OK c ->
Val.shrxl (
rs1#
RAX) (
Vint n) =
Some v ->
exists rs2,
exec_straight ge fn c rs1 m empfp k rs2 m
/\
rs2#
RAX =
v
/\
forall r,
data_preg r =
true ->
r <>
RAX ->
r <>
RDX ->
rs2#
r =
rs1#
r.
Proof.
Smart constructor for integer conversions
Lemma mk_intconv_correct:
forall mk sem rd rs k c rs1 m fp,
mk_intconv mk rd rs k =
OK c ->
(
forall c rd rs r m,
exec_instr ge c (
mk rd rs)
r m =
Next (
nextinstr (
r#
rd <- (
sem r#
rs)))
m) ->
(
fp =
if Archi.ptr64 ||
low_ireg rs
then exec_instr_fp ge fn (
mk rd rs)
rs1 m
else exec_instr_fp ge fn (
mk rd RAX) (
nextinstr rs1 #
RAX <- (
rs1 rs))
m) ->
exists rs2,
exec_straight ge fn c rs1 m fp k rs2 m
/\
rs2#
rd =
sem rs1#
rs
/\
forall r,
data_preg r =
true ->
r <>
rd ->
r <>
RAX ->
rs2#
r =
rs1#
r.
Proof.
Smart constructor for small stores
Lemma addressing_mentions_correct:
forall a r (
rs1 rs2:
regset),
(
forall (
r':
ireg),
r' <>
r ->
rs1 r' =
rs2 r') ->
addressing_mentions a r =
false ->
eval_addrmode32 ge a rs1 =
eval_addrmode32 ge a rs2.
Proof.
intros until rs2;
intro AG.
unfold addressing_mentions,
eval_addrmode32.
destruct a.
intros.
destruct (
orb_false_elim _ _ H).
unfold proj_sumbool in *.
decEq.
destruct base;
auto.
apply AG.
destruct (
ireg_eq r i);
congruence.
decEq.
destruct ofs as [[
r'
sc] | ];
auto.
rewrite AG;
auto.
destruct (
ireg_eq r r');
congruence.
Qed.
Lemma mk_storebyte_correct:
forall addr r k c rs1 m1 m2,
mk_storebyte addr r k =
OK c ->
Mem.storev Mint8unsigned m1 (
eval_addrmode ge addr rs1) (
rs1 r) =
Some m2 ->
exists rs2,
exec_straight ge fn c rs1 m1 (
storev_fp Mint8unsigned (
eval_addrmode ge addr rs1))
k rs2 m2
/\
forall r,
data_preg r =
true ->
preg_notin r (
if Archi.ptr64 then nil else AX ::
CX ::
nil) ->
rs2#
r =
rs1#
r.
Proof.
Accessing slots in the stack frame
Remark eval_addrmode_indexed:
forall (
base:
ireg)
ofs (
rs:
regset),
match rs#
base with Vptr _ _ =>
True |
_ =>
False end ->
eval_addrmode ge (
Addrmode (
Some base)
None (
inl _ (
Ptrofs.unsigned ofs)))
rs =
Val.offset_ptr rs#
base ofs.
Proof.
Ltac loadind_correct_solve :=
match goal with
|
H:
Error _ =
OK _ |-
_ =>
discriminate H
|
H:
OK _ =
OK _ |-
_ =>
inv H
|
H:
match ?
x with _ =>
_ end =
OK _ |-
_ =>
destruct x eqn:?;
loadind_correct_solve
|
_ =>
idtac
end.
Lemma loadind_correct:
forall (
base:
ireg)
ofs ty dst k (
rs:
regset)
c 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 fn c rs m (
loadv_fp (
chunk_of_type ty) (
Val.offset_ptr rs#
base ofs))
k rs'
m
/\
rs'#(
preg_of dst) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of dst ->
rs'#
r =
rs#
r.
Proof.
Lemma storeind_correct:
forall (
base:
ireg)
ofs ty src k (
rs:
regset)
c 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 fn c rs m (
storev_fp (
chunk_of_type ty) (
Val.offset_ptr rs#
base ofs))
k rs'
m'
/\
forall r,
data_preg r =
true ->
preg_notin r (
destroyed_by_setstack ty) ->
rs'#
r =
rs#
r.
Proof.
Translation of addressing modes
Lemma transl_addressing_mode_32_correct:
forall addr args am (
rs:
regset)
v,
transl_addressing addr args =
OK am ->
eval_addressing32 ge (
rs RSP)
addr (
List.map rs (
List.map preg_of args)) =
Some v ->
Val.lessdef v (
eval_addrmode32 ge am rs).
Proof.
Lemma transl_addressing_mode_64_correct:
forall addr args am (
rs:
regset)
v,
transl_addressing addr args =
OK am ->
eval_addressing64 ge (
rs RSP)
addr (
List.map rs (
List.map preg_of args)) =
Some v ->
Val.lessdef v (
eval_addrmode64 ge am rs).
Proof.
Lemma transl_addressing_mode_correct:
forall addr args am (
rs:
regset)
v,
transl_addressing addr args =
OK am ->
eval_addressing ge (
rs RSP)
addr (
List.map rs (
List.map preg_of args)) =
Some v ->
Val.lessdef v (
eval_addrmode ge am rs).
Proof.
Lemma normalize_addrmode_32_correct:
forall am rs,
eval_addrmode32 ge (
normalize_addrmode_32 am)
rs =
eval_addrmode32 ge am rs.
Proof.
intros;
destruct am as [
base ofs [
n|
r]];
simpl;
auto.
rewrite Int.repr_signed.
auto.
Qed.
Lemma normalize_addrmode_64_correct:
forall am rs,
eval_addrmode64 ge am rs =
match normalize_addrmode_64 am with
| (
am',
None) =>
eval_addrmode64 ge am'
rs
| (
am',
Some delta) =>
Val.addl (
eval_addrmode64 ge am'
rs) (
Vlong delta)
end.
Proof.
Processor conditions and comparisons
TODO: move to Footprint.v
Lemma loc_union_2:
forall ls,
Locs.union ls ls =
ls.
Proof.
Lemma fp_union_2:
forall fp,
FP.union fp fp =
fp.
Proof.
Ltac SimplifFP :=
match goal with
|
H:
match ?
x with _ =>
_ end =
Some _ |-
_ =>
destruct x eqn:
C;
try inv C;
try discriminate
|
H: ?
x =
Some _ |-
context[?
x] =>
destruct x eqn:
C;
try inv C;
try discriminate
| |-
match ?
x with _ =>
_ end =
_ =>
destruct x eqn:
C;
try inv C;
try discriminate
| |-
context[
FP.union ?
fp empfp] =>
rewrite FP.fp_union_emp;
auto
| |-
context[
FP.union ?
fp ?
fp] =>
rewrite fp_union_2;
auto
end.
Ltac SimplifFPs :=
repeat SimplifFP.
Lemma transl_cond_correct:
forall cond args k c rs m,
transl_cond cond args k =
OK c ->
exists rs'
fp,
match eval_condition cond (
map rs (
map preg_of args))
m with
|
None =>
True
|
Some b =>
exec_straight ge fn c rs m fp k rs'
m /\
eval_extcond (
testcond_for_condition cond)
rs' =
Some b /\
eval_condition_fp cond (
map rs (
map preg_of args))
m =
Some fp /\
forall r,
data_preg r =
true ->
rs'#
r =
rs r
end.
Proof.
unfold transl_cond;
intros.
destruct cond;
repeat (
destruct args;
try discriminate);
monadInv H.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
rewrite (
ireg_of_eq _ _ EQ1).
destruct (
Val.cmp_bool c0 (
rs x) (
rs x0))
eqn:?.
econstructor.
eexists.
split.
apply exec_straight_one.
simpl.
erewrite cmp_bool_check_compare_ints;
eauto.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x), (
rs x0);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_signed_comparison_32_correct;
eauto.
split.
fp *)
simpl.
unfold compare_ints_fp.
destruct (
rs x), (
rs x0);
try discriminate;
simpl.
f_equal.
intros.
unfold compare_ints.
Simplifs.
repeat econstructor.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
rewrite (
ireg_of_eq _ _ EQ1).
destruct (
Val.cmpu_bool (
Mem.valid_pointer m)
c0 (
rs x) (
rs x0))
eqn:?; [|
repeat econstructor].
econstructor.
eexists.
split.
apply exec_straight_one.
simpl.
erewrite cmpu_bool_check_compare_ints;
eauto.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x), (
rs x0);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_unsigned_comparison_32_correct;
eauto.
split.
fp *) {
simpl.
unfold compare_ints_fp.
destruct (
rs x), (
rs x0);
try discriminate;
simpl in *;
try (
f_equal;
fail);
SimplifFPs;
repeat rewrite FP.fp_union_emp;
auto. }
intros.
unfold compare_ints.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
Int.eq_dec n Int.zero).
destruct (
rs x)
eqn:
VAL;
simpl;
auto;
try (
repeat econstructor;
fail).
subst.
econstructor;
eexists;
split.
apply exec_straight_one.
simpl.
rewrite VAL.
simpl.
eauto.
eauto.
eauto.
split.
rewrite Int.and_idem.
eapply testcond_for_signed_comparison_32_correct;
eauto.
split.
fp *)
simpl.
unfold compare_ints_fp.
rewrite VAL.
simpl.
f_equal.
intros.
unfold compare_ints.
Simplifs.
destruct (
Val.cmp_bool c0 (
rs x) (
Vint n))
eqn:?; [|
repeat econstructor].
econstructor;
eexists;
split.
apply exec_straight_one.
simpl.
erewrite cmp_bool_check_compare_ints;
eauto.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_signed_comparison_32_correct;
eauto.
split.
fp *)
simpl.
unfold compare_ints_fp.
destruct (
rs x);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_ints.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
Val.cmpu_bool (
Mem.valid_pointer m)
c0 (
rs x) (
Vint n))
eqn:?; [|
repeat econstructor].
econstructor.
eexists.
split.
apply exec_straight_one.
simpl.
erewrite cmpu_bool_check_compare_ints;
eauto.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_unsigned_comparison_32_correct;
eauto.
split.
fp *)
simpl.
unfold compare_ints_fp.
destruct (
rs x);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_ints.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
rewrite (
ireg_of_eq _ _ EQ1).
destruct (
Val.cmpl_bool c0 (
rs x) (
rs x0))
eqn:?; [|
repeat econstructor].
econstructor.
eexists;
split.
apply exec_straight_one.
simpl.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x), (
rs x0);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_signed_comparison_64_correct;
eauto.
split.
fp *)
simpl.
unfold compare_longs_fp.
destruct (
rs x), (
rs x0);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_longs.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
rewrite (
ireg_of_eq _ _ EQ1).
destruct (
Val.cmplu_bool (
Mem.valid_pointer m)
c0 (
rs x) (
rs x0))
eqn:?; [|
repeat econstructor].
econstructor.
eexists;
split.
apply exec_straight_one.
simpl.
destruct check_vundef eqn:?;
eauto.
exfalso;
destruct (
rs x), (
rs x0);
simpl in *;
discriminate.
eauto.
eauto.
split.
eapply testcond_for_unsigned_comparison_64_correct;
eauto.
split.
fp *)
simpl.
unfold compare_longs_fp.
destruct (
rs x), (
rs x0);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_longs.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
Int64.eq_dec n Int64.zero).
destruct (
rs x)
eqn:
VAL;
simpl;
try repeat constructor.
econstructor;
eexists;
split.
apply exec_straight_one.
simpl;
eauto.
rewrite VAL.
simpl.
eauto.
eauto.
eauto.
split.
subst.
rewrite Int64.and_idem.
eapply testcond_for_signed_comparison_64_correct;
eauto.
split.
fp *)
simpl.
unfold compare_longs_fp.
destruct (
rs x);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_longs.
Simplifs.
destruct (
rs x)
eqn:
VAL;
simpl;
try repeat constructor.
econstructor;
eexists;
split.
apply exec_straight_one.
simpl;
eauto.
rewrite VAL.
simpl.
eauto.
eauto.
eauto.
split.
eapply testcond_for_signed_comparison_64_correct;
eauto.
split.
fp *)
simpl.
unfold compare_longs_fp.
destruct (
rs x);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_longs.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
Val.cmplu_bool (
Mem.valid_pointer m)
c0 (
rs x) (
Vlong n))
eqn:
CMP;
repeat constructor.
destruct (
rs x)
eqn:
VAL;
simpl in *;
inv CMP.
eauto.
econstructor.
eexists.
split.
apply exec_straight_one.
simpl.
rewrite VAL.
simpl.
eauto.
eauto.
auto.
split.
eapply testcond_for_unsigned_comparison_64_correct;
eauto.
split.
fp *)
simpl.
unfold compare_longs_fp.
destruct (
rs x);
try discriminate;
simpl in *;
SimplifFPs.
intros.
unfold compare_longs.
Simplifs.
-
simpl.
rewrite (
freg_of_eq _ _ EQ).
rewrite (
freg_of_eq _ _ EQ1).
destruct (
rs x)
eqn:
VAL;
destruct (
rs x0)
eqn:
VAL';
simpl;
repeat constructor.
exists (
nextinstr (
compare_floats (
swap_floats c0 (
rs x) (
rs x0)) (
swap_floats c0 (
rs x0) (
rs x))
rs)).
eexists.
split.
apply exec_straight_one.
destruct c0;
simpl;
auto.
auto.
unfold nextinstr.
rewrite Pregmap.gss.
rewrite compare_floats_inv;
auto with asmgen.
split.
rewrite VAL,
VAL'.
repeat rewrite swap_floats_commut.
apply testcond_for_float_comparison_correct.
split.
fp *)
simpl.
unfold floatcomp.
destruct c0;
simpl;
auto.
intros.
Simplifs.
apply compare_floats_inv;
auto with asmgen.
-
simpl.
rewrite (
freg_of_eq _ _ EQ).
rewrite (
freg_of_eq _ _ EQ1).
exists (
nextinstr (
compare_floats (
swap_floats c0 (
rs x) (
rs x0)) (
swap_floats c0 (
rs x0) (
rs x))
rs)).
eexists.
destruct (
rs x)
eqn:
VAL;
destruct (
rs x0)
eqn:
VAL';
simpl;
auto.
repeat rewrite swap_floats_commut.
split.
apply exec_straight_one.
destruct c0;
simpl;
rewrite VAL,
VAL';
auto.
auto.
unfold nextinstr.
rewrite Pregmap.gss.
rewrite compare_floats_inv;
auto with asmgen.
split.
apply testcond_for_neg_float_comparison_correct.
split.
fp *)
unfold floatcomp;
destruct c0;
simpl;
auto.
intros.
Simplifs.
apply compare_floats_inv;
auto with asmgen.
-
simpl.
rewrite (
freg_of_eq _ _ EQ).
rewrite (
freg_of_eq _ _ EQ1).
destruct (
rs x)
eqn:
VAL;
destruct (
rs x0)
eqn:
VAL';
simpl;
repeat constructor.
exists (
nextinstr (
compare_floats32 (
swap_floats c0 (
rs x) (
rs x0)) (
swap_floats c0 (
rs x0) (
rs x))
rs)).
eexists.
split.
repeat rewrite swap_floats_commut.
apply exec_straight_one.
destruct c0;
simpl;
auto.
auto.
unfold nextinstr.
rewrite Pregmap.gss.
rewrite compare_floats32_inv;
auto with asmgen.
split.
rewrite VAL,
VAL'.
repeat rewrite swap_floats_commut.
apply testcond_for_float32_comparison_correct.
split.
fp *)
unfold floatcomp32.
destruct c0;
simpl;
auto.
intros.
Simplifs.
apply compare_floats32_inv;
auto with asmgen.
-
simpl.
rewrite (
freg_of_eq _ _ EQ).
rewrite (
freg_of_eq _ _ EQ1).
exists (
nextinstr (
compare_floats32 (
swap_floats c0 (
rs x) (
rs x0)) (
swap_floats c0 (
rs x0) (
rs x))
rs)).
destruct (
rs x)
eqn:
VAL;
destruct (
rs x0)
eqn:
VAL';
simpl;
repeat constructor.
eexists.
split.
apply exec_straight_one.
destruct c0;
simpl;
rewrite VAL,
VAL';
auto.
auto.
unfold nextinstr.
rewrite Pregmap.gss.
rewrite compare_floats32_inv;
auto with asmgen.
split.
repeat rewrite swap_floats_commut.
apply testcond_for_neg_float32_comparison_correct.
split.
fp *)
unfold floatcomp32.
destruct c0;
auto.
intros.
Simplifs.
apply compare_floats32_inv;
auto with asmgen.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
rs x)
eqn:
VAL;
simpl;
repeat constructor.
econstructor.
eexists.
split.
apply exec_straight_one.
simpl;
rewrite VAL.
simpl.
eauto.
eauto.
eauto.
split.
generalize (
compare_ints_spec rs (
Vint (
Int.and i n))
Vzero m).
intros [
A B].
rewrite A.
unfold Val.cmpu;
simpl.
destruct (
Int.eq (
Int.and i n)
Int.zero);
auto.
split.
simpl.
unfold compare_ints_fp.
rewrite VAL.
simpl.
SimplifFPs.
intros.
unfold compare_ints.
Simplifs.
-
simpl.
rewrite (
ireg_of_eq _ _ EQ).
destruct (
rs x)
eqn:
VAL;
simpl;
repeat constructor.
econstructor.
eexists.
split.
apply exec_straight_one.
simpl;
rewrite VAL.
simpl.
eauto.
auto.
auto.
simpl.
unfold compare_ints_fp.
split.
generalize (
compare_ints_spec rs (
Vint (
Int.and i n))
Vzero m).
intros [
A B].
rewrite A.
unfold Val.cmpu;
simpl.
destruct (
Int.eq (
Int.and i n)
Int.zero);
auto.
split.
rewrite VAL.
simpl.
SimplifFPs.
intros.
unfold compare_ints.
Simplifs.
Qed.
Lemma mk_setcc_base_correct:
forall cond rd k rs1 m,
exists rs2,
exec_straight ge fn (
mk_setcc_base cond rd k)
rs1 m empfp k rs2 m
/\
rs2#
rd =
Val.of_optbool(
eval_extcond cond rs1)
/\
forall r,
data_preg r =
true ->
r <>
RAX /\
r <>
RCX ->
r <>
rd ->
rs2#
r =
rs1#
r.
Proof.
Lemma mk_setcc_correct:
forall cond rd k rs1 m,
exists rs2,
exec_straight ge fn (
mk_setcc cond rd k)
rs1 m empfp k rs2 m
/\
rs2#
rd =
Val.of_optbool(
eval_extcond cond rs1)
/\
forall r,
data_preg r =
true ->
r <>
RAX /\
r <>
RCX ->
r <>
rd ->
rs2#
r =
rs1#
r.
Proof.
Translation of arithmetic operations.
Ltac ArgsInv :=
match goal with
| [
H:
Error _ =
OK _ |-
_ ] =>
discriminate
| [
H:
match ?
args with nil =>
_ |
_ ::
_ =>
_ end =
OK _ |-
_ ] =>
destruct args;
ArgsInv
| [
H:
bind _ _ =
OK _ |-
_ ] =>
monadInv H;
ArgsInv
| [
H:
match _ with left _ =>
_ |
right _ =>
assertion_failed end =
OK _ |-
_ ] =>
monadInv H;
ArgsInv
| [
H:
match _ with true =>
_ |
false =>
assertion_failed end =
OK _ |-
_ ] =>
monadInv H;
ArgsInv
| [
H:
ireg_of _ =
OK _ |-
_ ] =>
simpl in *;
rewrite (
ireg_of_eq _ _ H)
in *;
clear H;
ArgsInv
| [
H:
freg_of _ =
OK _ |-
_ ] =>
simpl in *;
rewrite (
freg_of_eq _ _ H)
in *;
clear H;
ArgsInv
|
_ =>
idtac
end.
Ltac TranslOp :=
econstructor;
split;
[
apply exec_straight_one; [
simpl;
eauto |
auto |
auto ]
|
split; [
Simplifs |
intros;
Simplifs ]].
Lemma transl_op_correct:
forall op args res k c (
rs:
regset)
m v fp,
transl_op op args res k =
OK c ->
eval_operation ge (
rs#
RSP)
op (
map rs (
map preg_of args))
m =
Some v ->
eval_operation_fp ge (
rs#
RSP)
op (
map rs (
map preg_of args))
m =
Some fp ->
exists rs',
exec_straight ge fn c rs m fp 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.
Transparent destroyed_by_op.
intros until fp;
intros TR EV EVFP.
assert (
SAME:
(
exists rs',
exec_straight ge fn c rs m fp 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 fn c rs m fp 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;
simpl in TR;
ArgsInv;
simpl in EV,
EVFP;
try (
inv EV);
try (
inv EVFP);
try (
apply SAME;
TranslOp;
fail).
move *)
exploit mk_mov_correct;
eauto.
intros [
rs2 [
A [
B C]]].
apply SAME.
exists rs2.
eauto.
intconst *)
apply SAME.
destruct (
Int.eq_dec n Int.zero).
subst n.
TranslOp.
TranslOp.
longconst *)
apply SAME.
destruct (
Int64.eq_dec n Int64.zero).
subst n.
TranslOp.
TranslOp.
floatconst *)
apply SAME.
destruct (
Float.eq_dec n Float.zero).
subst n.
TranslOp.
TranslOp.
singleconst *)
apply SAME.
destruct (
Float32.eq_dec n Float32.zero).
subst n.
TranslOp.
TranslOp.
cast8signed *)
apply SAME.
eapply mk_intconv_correct;
eauto.
simpl.
match goal with |-
context[
match ?
x with _ =>
_ end] =>
destruct x;
auto end.
cast8unsigned *)
apply SAME.
eapply mk_intconv_correct;
eauto.
simpl.
match goal with |-
context[
match ?
x with _ =>
_ end] =>
destruct x;
auto end.
mulhs *)
apply SAME.
TranslOp.
destruct H1.
Simplifs.
mulhu *)
apply SAME.
TranslOp.
destruct H1.
Simplifs.
div *)
apply SAME.
exploit (
divs_mods_exists (
rs RAX) (
rs RCX)).
left;
congruence.
intros (
nh &
nl &
d &
q &
r &
A &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vint nh))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
simpl.
rewrite A.
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct (
Val.divs);
inv H1;
auto.
auto.
auto.
split.
change (
Vint q =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
divu *)
apply SAME.
exploit (
divu_modu_exists (
rs RAX) (
rs RCX)).
left;
congruence.
intros (
n &
d &
q &
r &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <-
Vzero)).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.divu;
inv H1;
auto.
auto.
auto.
split.
change (
Vint q =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
mod *)
apply SAME.
exploit (
divs_mods_exists (
rs RAX) (
rs RCX)).
right;
congruence.
intros (
nh &
nl &
d &
q &
r &
A &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vint nh))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
simpl.
rewrite A.
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.mods;
inv H1;
auto.
auto.
auto.
split.
change (
Vint r =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
modu *)
apply SAME.
exploit (
divu_modu_exists (
rs RAX) (
rs RCX)).
right;
congruence.
intros (
n &
d &
q &
r &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <-
Vzero)).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.modu;
inv H1;
auto.
auto.
auto.
split.
change (
Vint r =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
shrximm *)
apply SAME.
destruct Val.shrx in H1;
inv H1.
eapply mk_shrximm_correct;
eauto.
lea *)
exploit transl_addressing_mode_32_correct;
eauto.
intros EA.
TranslOp.
simpl.
destruct eval_addressing32 in H1;
inv H1;
auto.
rewrite nextinstr_inv;
auto with asmgen.
rewrite Pregmap.gss.
rewrite normalize_addrmode_32_correct;
auto.
mullhs *)
apply SAME.
TranslOp.
destruct H1.
Simplifs.
mullhu *)
apply SAME.
TranslOp.
destruct H1.
Simplifs.
divl *)
apply SAME.
exploit (
divls_modls_exists (
rs RAX) (
rs RCX)).
left;
congruence.
intros (
nh &
nl &
d &
q &
r &
A &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vlong nh))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
simpl.
rewrite A.
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.divls;
inv H1;
auto.
auto.
auto.
split.
change (
Vlong q =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
divlu *)
apply SAME.
exploit (
divlu_modlu_exists (
rs RAX) (
rs RCX)).
left;
congruence.
intros (
n &
d &
q &
r &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vlong Int64.zero))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.divlu in H1;
inv H1;
auto.
auto.
auto.
split.
change (
Vlong q =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
modl *)
apply SAME.
exploit (
divls_modls_exists (
rs RAX) (
rs RCX)).
right;
congruence.
intros (
nh &
nl &
d &
q &
r &
A &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vlong nh))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
simpl.
rewrite A.
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.modls in H1;
inv H1;
auto.
auto.
auto.
split.
change (
Vlong r =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
modlu *)
apply SAME.
exploit (
divlu_modlu_exists (
rs RAX) (
rs RCX)).
right;
congruence.
intros (
n &
d &
q &
r &
B &
C &
D &
E &
F).
set (
rs1 :=
nextinstr_nf (
rs#
RDX <- (
Vlong Int64.zero))).
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two with (
rs2 :=
rs1).
reflexivity.
auto.
simpl.
change (
rs1 RAX)
with (
rs RAX);
rewrite B.
change (
rs1 RCX)
with (
rs RCX);
rewrite C.
rewrite D.
reflexivity.
destruct Val.modlu in H1;
inv H1;
auto.
auto.
auto.
split.
change (
Vlong r =
v).
congruence.
simpl;
intros.
destruct H3.
unfold rs1;
Simplifs.
shrxlimm *)
apply SAME.
destruct Val.shrxl in H1;
inv H1.
eapply mk_shrxlimm_correct;
eauto.
leal *)
exploit transl_addressing_mode_64_correct;
eauto.
intros EA.
generalize (
normalize_addrmode_64_correct x rs).
destruct (
normalize_addrmode_64 x)
as [
am' [
delta|]];
intros EV.
econstructor;
split.
rewrite <- (
FP.emp_union_fp fp).
eapply exec_straight_two.
simpl.
reflexivity.
auto.
simpl.
reflexivity.
destruct eval_addressing64 in H1;
inv H1;
auto.
auto.
auto.
split.
rewrite nextinstr_nf_inv by auto.
rewrite Pregmap.gss.
rewrite nextinstr_inv by auto with asmgen.
rewrite Pregmap.gss.
rewrite <-
EV;
auto.
intros;
Simplifs.
TranslOp.
destruct eval_addressing64 in H1;
inv H1;
auto.
rewrite nextinstr_inv;
auto with asmgen.
rewrite Pregmap.gss;
auto.
rewrite <-
EV;
auto.
intoffloat *)
apply SAME.
TranslOp.
destruct Val.intoffloat in H1;
inv H1;
auto.
rewrite H0;
auto.
floatofint *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
intofsingle *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
singleofint *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
longoffloat *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
floatoflong *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
longofsingle *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
singleoflong *)
apply SAME.
TranslOp.
SimplifFPs;
inv H1;
auto.
rewrite H0;
auto.
condition *)
pose proof (
transl_cond_correct cond args _ _ rs m EQ0);
eauto.
destruct eval_condition eqn:
EVAL;
try discriminate.
destruct H as [
rs' [
fp' [
P [
Q [
R R']]]]].
simpl in *.
destruct eval_condition_fp eqn:
EVALFP;
try congruence.
inv H1.
inv R.
inv H0.
exploit mk_setcc_correct;
eauto.
intros [
rs3 [
S [
T U]]].
destruct eval_condition in EVAL,
Q; [|
inv EVAL].
inv EVAL.
exists rs3.
split.
rewrite <- (
FP.fp_union_emp fp').
eapply exec_straight_trans.
eexact P.
eexact S.
split.
rewrite T.
rewrite Q.
simpl.
destruct b;
auto.
intros.
transitivity (
rs'
r);
auto.
Qed.
Translation of memory loads.
Lemma transl_load_correct:
forall chunk addr args dest k c (
rs:
regset)
m a v,
transl_load chunk addr args dest k =
OK c ->
eval_addressing ge (
rs#
RSP)
addr (
map rs (
map preg_of args)) =
Some a ->
Mem.loadv chunk m a =
Some v ->
exists rs',
exec_straight ge fn c rs m (
loadv_fp chunk a)
k rs'
m
/\
rs'#(
preg_of dest) =
v
/\
forall r,
data_preg r =
true ->
r <>
preg_of dest ->
rs'#
r =
rs#
r.
Proof.
Lemma transl_store_correct:
forall chunk addr args src k c (
rs:
regset)
m a m',
transl_store chunk addr args src k =
OK c ->
eval_addressing ge (
rs#
RSP)
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 fn c rs m (
storev_fp chunk a)
k rs'
m'
/\
forall r,
data_preg r =
true ->
preg_notin r (
destroyed_by_store chunk addr) ->
rs'#
r =
rs#
r.
Proof.
End CONSTRUCTORS.