aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--aarch64/Asm.v507
-rw-r--r--aarch64/Asmblock.v1554
-rw-r--r--aarch64/Asmblockdeps.v2754
-rw-r--r--aarch64/Asmblockgen.v1258
-rw-r--r--aarch64/Asmblockgenproof.v1158
-rw-r--r--aarch64/Asmblockgenproof0.v983
-rw-r--r--aarch64/Asmblockgenproof1.v (renamed from aarch64/Asmgenproof1.v)3
-rw-r--r--aarch64/Asmblockprops.v358
-rw-r--r--aarch64/Asmexpand.ml102
-rw-r--r--aarch64/Asmgen.v1450
-rw-r--r--aarch64/Asmgenproof.v3183
-rw-r--r--aarch64/Asmgenproof_orig_single_label_in_header.v.stash2245
-rw-r--r--aarch64/InstructionScheduler.ml1263
-rw-r--r--aarch64/InstructionScheduler.mli113
-rw-r--r--aarch64/OpWeightsAsm.ml377
-rw-r--r--aarch64/OrigAsmgen.ml282
-rw-r--r--aarch64/PostpassScheduling.v495
-rw-r--r--aarch64/PostpassSchedulingOracle.ml984
-rw-r--r--aarch64/PostpassSchedulingproof.v690
-rw-r--r--aarch64/TargetPrinter.ml10
-rw-r--r--aarch64/extractionMachdep.v2
-rwxr-xr-xconfigure19
-rw-r--r--extraction/extraction.v4
-rw-r--r--kvx/Asmblockgenproof0.v (renamed from kvx/lib/Asmblockgenproof0.v)0
-rw-r--r--kvx/abstractbb/ImpSimuTest.v114
-rw-r--r--kvx/lib/IterList.v96
-rw-r--r--kvx/lib/OptionMonad.v49
-rw-r--r--kvx/lib/PseudoAsmblock.v267
-rw-r--r--kvx/lib/PseudoAsmblockproof.v1173
-rw-r--r--multiple_labels_crash_test/check.c120
-rw-r--r--multiple_labels_crash_test/driver.c12
-rw-r--r--multiple_labels_crash_test/func.c915
-rw-r--r--multiple_labels_crash_test/func.ref.s5170
-rw-r--r--multiple_labels_crash_test/hash.c3
-rw-r--r--multiple_labels_crash_test/init.c209
-rw-r--r--multiple_labels_crash_test/init.h181
-rw-r--r--test/aarch64/README.md15
-rw-r--r--test/aarch64/c/add_return.c1
-rw-r--r--test/aarch64/c/addresses.c32
-rw-r--r--test/aarch64/c/arith.c16
-rw-r--r--test/aarch64/c/arith_print.c19
-rw-r--r--test/aarch64/c/armstrong.c21
-rw-r--r--test/aarch64/c/array1.c64
-rw-r--r--test/aarch64/c/array2.c74
-rw-r--r--test/aarch64/c/biggest_of_3_int.c10
-rw-r--r--test/aarch64/c/bitwise1.c8
-rw-r--r--test/aarch64/c/cpintarray.c108
-rw-r--r--test/aarch64/c/enum1.c52
-rw-r--r--test/aarch64/c/enum2.c50
-rw-r--r--test/aarch64/c/floop.c8
-rw-r--r--test/aarch64/c/floor.c29
-rw-r--r--test/aarch64/c/funcs.c36
-rw-r--r--test/aarch64/c/hello.c6
-rw-r--r--test/aarch64/c/if.c7
-rw-r--r--test/aarch64/c/msb_pos.c20
-rw-r--r--test/aarch64/c/power2.c42
-rw-r--r--test/aarch64/c/prime.c23
-rw-r--r--test/aarch64/c/random.c50
-rw-r--r--test/aarch64/c/simple_op.c8
-rw-r--r--test/aarch64/c/wloop.c8
-rwxr-xr-xtest/aarch64/gen_tests/asmb_aarch64_gen_test.sh106
-rwxr-xr-xtest/aarch64/postpass_tests/postpass_exec_c_test.sh36
62 files changed, 26547 insertions, 2405 deletions
diff --git a/aarch64/Asm.v b/aarch64/Asm.v
index 38cf8259..8d3d4ff7 100644
--- a/aarch64/Asm.v
+++ b/aarch64/Asm.v
@@ -10,13 +10,20 @@
(* *)
(* *********************************************************************)
-(** Abstract syntax and semantics for AArch64 assembly language *)
+(** Abstract syntax and semantics for AArch64 assembly language
+
+W.r.t Asmblock, this is a "flat" syntax and semantics of "aarch64" assembly:
+ - without the basic block structure
+ - without the hierarchy of instructions.
+
+*)
Require Import Coqlib Zbits Maps.
Require Import AST Integers Floats.
Require Import Values Memory Events Globalenvs Smallstep.
Require Import Locations Conventions.
Require Stacklayout.
+Require Import OptionMonad.
(** * Abstract syntax *)
@@ -43,6 +50,9 @@ Coercion RR1: ireg >-> iregsp.
Lemma ireg_eq: forall (x y: ireg), {x=y} + {x<>y}.
Proof. decide equality. Defined.
+Lemma iregsp_eq: forall (x y: iregsp), {x=y} + {x<>y}.
+Proof. decide equality; apply ireg_eq. Defined.
+
(** In assembly files, [Dn] denotes the low 64-bit of a vector register,
and [Sn] the low 32 bits. *)
@@ -66,21 +76,29 @@ Inductive crbit: Type :=
Lemma crbit_eq: forall (x y: crbit), {x=y} + {x<>y}.
Proof. decide equality. Defined.
+Inductive dreg : Type :=
+ | IR: iregsp -> dreg (**r 64- or 32-bit integer registers *)
+ | FR: freg -> dreg. (**r double- or single-precision float registers *)
+
(** We model the following registers of the ARM architecture. *)
Inductive preg: Type :=
- | IR: ireg -> preg (**r 64- or 32-bit integer registers *)
- | FR: freg -> preg (**r double- or single-precision float registers *)
- | CR: crbit -> preg (**r bits in the condition register *)
- | SP: preg (**r register X31 used as stack pointer *)
- | PC: preg. (**r program counter *)
-
-Coercion IR: ireg >-> preg.
-Coercion FR: freg >-> preg.
+ | DR: dreg -> preg (** see dreg **)
+ | CR: crbit -> preg (**r bits in the condition register *)
+ | PC: preg. (**r program counter *)
+
+(* XXX: ireg no longer coerces to preg *)
+Coercion IR: iregsp >-> dreg.
+Coercion FR: freg >-> dreg.
+Coercion DR: dreg >-> preg.
+Definition SP:preg := XSP.
Coercion CR: crbit >-> preg.
+Lemma dreg_eq: forall (x y: dreg), {x=y} + {x<>y}.
+Proof. decide equality. apply iregsp_eq. apply freg_eq. Defined.
+
Lemma preg_eq: forall (x y: preg), {x=y} + {x<>y}.
-Proof. decide equality. apply ireg_eq. apply freg_eq. apply crbit_eq. Defined.
+Proof. decide equality. apply dreg_eq. apply crbit_eq. Defined.
Module PregEq.
Definition t := preg.
@@ -92,8 +110,6 @@ Module Pregmap := EMap(PregEq).
Definition preg_of_iregsp (r: iregsp) : preg :=
match r with RR1 r => IR r | XSP => SP end.
-Coercion preg_of_iregsp: iregsp >-> preg.
-
(** Conventional name for return address ([RA]) *)
Notation "'RA'" := X30 (only parsing) : asm.
@@ -307,9 +323,30 @@ Definition code := list instruction.
Record function : Type := mkfunction { fn_sig: signature; fn_code: code }.
Definition fundef := AST.fundef function.
Definition program := AST.program fundef unit.
+Definition genv := Genv.t fundef unit.
+
+(** The two functions below axiomatize how the linker processes
+ symbolic references [symbol + offset]. It computes the
+ difference between the address and the PC, and splits it into:
+ - 12 low bits usable as an offset in an addressing mode;
+ - 21 high bits usable as argument to the ADRP instruction.
+
+ In CompCert's model, we cannot really describe PC-relative addressing,
+ but we can claim that the address of [symbol + offset] decomposes
+ as the sum of
+ - a low part, usable as an offset in an addressing mode;
+ - a high part, usable as argument to the ADRP instruction. *)
+
+Parameter symbol_low: genv -> ident -> ptrofs -> val.
+Parameter symbol_high: genv -> ident -> ptrofs -> val.
+
+Axiom symbol_high_low:
+ forall (ge: genv) (id: ident) (ofs: ptrofs),
+ Val.addl (symbol_high ge id ofs) (symbol_low ge id ofs) = Genv.symbol_address ge id ofs.
(** * Operational semantics *)
+
(** The semantics operates over a single mapping from registers
(type [preg]) to values. We maintain (but do not enforce)
the convention that integer registers are mapped to values of
@@ -317,22 +354,19 @@ Definition program := AST.program fundef unit.
and condition bits to either [Vzero] or [Vone]. *)
Definition regset := Pregmap.t val.
-Definition genv := Genv.t fundef unit.
(** The value of an [ireg0] is either the value of the integer register,
or 0. *)
-Definition ir0w (rs: regset) (r: ireg0) : val :=
- match r with RR0 r => rs (IR r) | XZR => Vint Int.zero end.
-Definition ir0x (rs: regset) (r: ireg0) : val :=
- match r with RR0 r => rs (IR r) | XZR => Vlong Int64.zero end.
+Definition ir0 (is:isize) (rs: regset) (r: ireg0) : val :=
+ match r with RR0 r => rs (IR r) | XZR => if is (* is W *) then Vint Int.zero else Vlong Int64.zero end.
(** Concise notations for accessing and updating the values of registers. *)
Notation "a # b" := (a b) (at level 1, only parsing) : asm.
Notation "a # b <- c" := (Pregmap.set b c a) (at level 1, b at next level) : asm.
-Notation "a ## b" := (ir0w a b) (at level 1, only parsing) : asm.
-Notation "a ### b" := (ir0x a b) (at level 1, only parsing) : asm.
+Notation "a ## b" := (ir0 W a b) (at level 1, only parsing) : asm.
+Notation "a ### b" := (ir0 X a b) (at level 1, only parsing) : asm.
Open Scope asm.
@@ -366,84 +400,70 @@ Fixpoint set_res (res: builtin_res preg) (v: val) (rs: regset) : regset :=
| BR_splitlong hi lo => set_res lo (Val.loword v) (set_res hi (Val.hiword v) rs)
end.
-(** The two functions below axiomatize how the linker processes
- symbolic references [symbol + offset]. It computes the
- difference between the address and the PC, and splits it into:
- - 12 low bits usable as an offset in an addressing mode;
- - 21 high bits usable as argument to the ADRP instruction.
-
- In CompCert's model, we cannot really describe PC-relative addressing,
- but we can claim that the address of [symbol + offset] decomposes
- as the sum of
- - a low part, usable as an offset in an addressing mode;
- - a high part, usable as argument to the ADRP instruction. *)
-
-Parameter symbol_low: genv -> ident -> ptrofs -> val.
-Parameter symbol_high: genv -> ident -> ptrofs -> val.
+(** The semantics is purely small-step and defined as a function
+ from the current state (a register set + a memory state)
+ to either [Next rs' m'] where [rs'] and [m'] are the updated register
+ set and memory state after execution of the instruction at [rs#PC],
+ or [Stuck] if the processor is stuck. *)
-Axiom symbol_high_low:
- forall (ge: genv) (id: ident) (ofs: ptrofs),
- Val.addl (symbol_high ge id ofs) (symbol_low ge id ofs) = Genv.symbol_address ge id ofs.
+Record state: Type := State { _rs: regset; _m: mem }.
+Definition outcome := option state.
+Definition Next rs m: outcome := Some (State rs m).
+Definition Stuck: outcome := None.
-Section RELSEM.
-Variable ge: genv.
+(* a few lemma on comparisons of unsigned (e.g. pointers)
-(** Looking up instructions in a code sequence by position. *)
+TODO: these lemma are a copy/paste of kvx/Asmvliw.v (sharing to improve!)
+*)
-Fixpoint find_instr (pos: Z) (c: code) {struct c} : option instruction :=
- match c with
- | nil => None
- | i :: il => if zeq pos 0 then Some i else find_instr (pos - 1) il
- end.
+Definition Val_cmpu_bool cmp v1 v2: option bool :=
+ Val.cmpu_bool (fun _ _ => true) cmp v1 v2.
-(** Position corresponding to a label *)
+Lemma Val_cmpu_bool_correct (m:mem) (cmp: comparison) (v1 v2: val) b:
+ (Val.cmpu_bool (Mem.valid_pointer m) cmp v1 v2) = Some b
+ -> (Val_cmpu_bool cmp v1 v2) = Some b.
+Proof.
+ intros; eapply Val.cmpu_bool_lessdef; (econstructor 1 || eauto).
+Qed.
-Definition is_label (lbl: label) (instr: instruction) : bool :=
- match instr with
- | Plabel lbl' => if peq lbl lbl' then true else false
- | _ => false
- end.
+Definition Val_cmpu cmp v1 v2 := Val.of_optbool (Val_cmpu_bool cmp v1 v2).
-Lemma is_label_correct:
- forall lbl instr,
- if is_label lbl instr then instr = Plabel lbl else instr <> Plabel lbl.
+Lemma Val_cmpu_correct (m:mem) (cmp: comparison) (v1 v2: val):
+ Val.lessdef (Val.cmpu (Mem.valid_pointer m) cmp v1 v2)
+ (Val_cmpu cmp v1 v2).
Proof.
- intros. destruct instr; simpl; try discriminate. destruct (peq lbl lbl0); congruence.
+ unfold Val.cmpu, Val_cmpu.
+ remember (Val.cmpu_bool (Mem.valid_pointer m) cmp v1 v2) as ob.
+ destruct ob; simpl.
+ - erewrite Val_cmpu_bool_correct; eauto.
+ econstructor.
+ - econstructor.
Qed.
-Fixpoint label_pos (lbl: label) (pos: Z) (c: code) {struct c} : option Z :=
- match c with
- | nil => None
- | instr :: c' =>
- if is_label lbl instr then Some (pos + 1) else label_pos lbl (pos + 1) c'
- end.
-
-(** The semantics is purely small-step and defined as a function
- from the current state (a register set + a memory state)
- to either [Next rs' m'] where [rs'] and [m'] are the updated register
- set and memory state after execution of the instruction at [rs#PC],
- or [Stuck] if the processor is stuck. *)
+Definition Val_cmplu_bool (cmp: comparison) (v1 v2: val)
+ := (Val.cmplu_bool (fun _ _ => true) cmp v1 v2).
-Inductive outcome: Type :=
- | Next: regset -> mem -> outcome
- | Stuck: outcome.
+Lemma Val_cmplu_bool_correct (m:mem) (cmp: comparison) (v1 v2: val) b:
+ (Val.cmplu_bool (Mem.valid_pointer m) cmp v1 v2) = Some b
+ -> (Val_cmplu_bool cmp v1 v2) = Some b.
+Proof.
+ intros; eapply Val.cmplu_bool_lessdef; (econstructor 1 || eauto).
+Qed.
-(** Manipulations over the [PC] register: continuing with the next
- instruction ([nextinstr]) or branching to a label ([goto_label]). *)
+Definition Val_cmplu cmp v1 v2 := Val.of_optbool (Val_cmplu_bool cmp v1 v2).
-Definition nextinstr (rs: regset) :=
- rs#PC <- (Val.offset_ptr rs#PC Ptrofs.one).
-
-Definition goto_label (f: function) (lbl: label) (rs: regset) (m: mem) :=
- match label_pos lbl 0 (fn_code f) with
- | None => Stuck
- | Some pos =>
- match rs#PC with
- | Vptr b ofs => Next (rs#PC <- (Vptr b (Ptrofs.repr pos))) m
- | _ => Stuck
- end
- end.
+Lemma Val_cmplu_correct (m:mem) (cmp: comparison) (v1 v2: val):
+ Val.lessdef (Val.maketotal (Val.cmplu (Mem.valid_pointer m) cmp v1 v2))
+ (Val_cmplu cmp v1 v2).
+Proof.
+ unfold Val.cmplu, Val_cmplu.
+ remember (Val.cmplu_bool (Mem.valid_pointer m) cmp v1 v2) as ob.
+ destruct ob as [b|]; simpl.
+ - erewrite Val_cmplu_bool_correct; eauto.
+ simpl. econstructor.
+ - econstructor.
+Qed.
(** Testing a condition *)
@@ -513,10 +533,10 @@ Definition eval_testcond (c: testcond) (rs: regset) : option bool :=
(** Integer "is zero?" test *)
-Definition eval_testzero (sz: isize) (v: val) (m: mem): option bool :=
+Definition eval_testzero (sz: isize) (v: val): option bool :=
match sz with
- | W => Val.cmpu_bool (Mem.valid_pointer m) Ceq v (Vint Int.zero)
- | X => Val.cmplu_bool (Mem.valid_pointer m) Ceq v (Vlong Int64.zero)
+ | W => Val_cmpu_bool Ceq v (Vint Int.zero)
+ | X => Val_cmplu_bool Ceq v (Vlong Int64.zero)
end.
(** Integer "bit is set?" test *)
@@ -527,48 +547,19 @@ Definition eval_testbit (sz: isize) (v: val) (n: int): option bool :=
| X => Val.cmpl_bool Cne (Val.andl v (Vlong (Int64.shl' Int64.one n))) (Vlong Int64.zero)
end.
-(** Evaluating an addressing mode *)
-
-Definition eval_addressing (a: addressing) (rs: regset): val :=
- match a with
- | ADimm base n => Val.addl rs#base (Vlong n)
- | ADreg base r => Val.addl rs#base rs#r
- | ADlsl base r n => Val.addl rs#base (Val.shll rs#r (Vint n))
- | ADsxt base r n => Val.addl rs#base (Val.shll (Val.longofint rs#r) (Vint n))
- | ADuxt base r n => Val.addl rs#base (Val.shll (Val.longofintu rs#r) (Vint n))
- | ADadr base id ofs => Val.addl rs#base (symbol_low ge id ofs)
- | ADpostincr base n => Vundef (* not modeled yet *)
- end.
-
-(** Auxiliaries for memory accesses *)
-
-Definition exec_load (chunk: memory_chunk) (transf: val -> val)
- (a: addressing) (r: preg) (rs: regset) (m: mem) :=
- match Mem.loadv chunk m (eval_addressing a rs) with
- | None => Stuck
- | Some v => Next (nextinstr (rs#r <- (transf v))) m
- end.
-
-Definition exec_store (chunk: memory_chunk)
- (a: addressing) (v: val)
- (rs: regset) (m: mem) :=
- match Mem.storev chunk m (eval_addressing a rs) v with
- | None => Stuck
- | Some m' => Next (nextinstr rs) m'
- end.
(** Comparisons *)
-Definition compare_int (rs: regset) (v1 v2: val) (m: mem) :=
+Definition compare_int (rs: regset) (v1 v2: val) :=
rs#CN <- (Val.negative (Val.sub v1 v2))
- #CZ <- (Val.cmpu (Mem.valid_pointer m) Ceq v1 v2)
- #CC <- (Val.cmpu (Mem.valid_pointer m) Cge v1 v2)
+ #CZ <- (Val_cmpu Ceq v1 v2)
+ #CC <- (Val_cmpu Cge v1 v2)
#CV <- (Val.sub_overflow v1 v2).
-Definition compare_long (rs: regset) (v1 v2: val) (m: mem) :=
+Definition compare_long (rs: regset) (v1 v2: val) :=
rs#CN <- (Val.negativel (Val.subl v1 v2))
- #CZ <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq v1 v2))
- #CC <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Cge v1 v2))
+ #CZ <- (Val_cmplu Ceq v1 v2)
+ #CC <- (Val_cmplu Cge v1 v2)
#CV <- (Val.subl_overflow v1 v2).
(** Semantics of [fcmp] instructions:
@@ -669,18 +660,153 @@ Definition float64_of_bits (v: val): val :=
| _ => Vundef
end.
-(** Execution of a single instruction [i] in initial state
- [rs] and [m]. Return updated state. For instructions
- that correspond to actual AArch64 instructions, the cases are
- straightforward transliterations of the informal descriptions
- given in the ARMv8 reference manuals. For pseudo-instructions,
- refer to the informal descriptions given above.
-
- Note that we set to [Vundef] the registers used as temporaries by
- the expansions of the pseudo-instructions, so that the code we
- generate cannot use those registers to hold values that must
- survive the execution of the pseudo-instruction.
-*)
+
+(** Translation of the LTL/Linear/Mach view of machine registers
+ to the AArch64 view. Note that no LTL register maps to [X16],
+ [X18], nor [X30].
+ [X18] is reserved as the platform register and never used by the
+ code generated by CompCert.
+ [X30] is used for the return address, and can also be used as temporary.
+ [X16] can be used as temporary. *)
+
+Definition dreg_of (r: mreg) : dreg :=
+ match r with
+ | R0 => X0 | R1 => X1 | R2 => X2 | R3 => X3
+ | R4 => X4 | R5 => X5 | R6 => X6 | R7 => X7
+ | R8 => X8 | R9 => X9 | R10 => X10 | R11 => X11
+ | R12 => X12 | R13 => X13 | R14 => X14 | R15 => X15
+ | R17 => X17 | R19 => X19
+ | R20 => X20 | R21 => X21 | R22 => X22 | R23 => X23
+ | R24 => X24 | R25 => X25 | R26 => X26 | R27 => X27
+ | R28 => X28 | R29 => X29
+ | F0 => D0 | F1 => D1 | F2 => D2 | F3 => D3
+ | F4 => D4 | F5 => D5 | F6 => D6 | F7 => D7
+ | F8 => D8 | F9 => D9 | F10 => D10 | F11 => D11
+ | F12 => D12 | F13 => D13 | F14 => D14 | F15 => D15
+ | F16 => D16 | F17 => D17 | F18 => D18 | F19 => D19
+ | F20 => D20 | F21 => D21 | F22 => D22 | F23 => D23
+ | F24 => D24 | F25 => D25 | F26 => D26 | F27 => D27
+ | F28 => D28 | F29 => D29 | F30 => D30 | F31 => D31
+ end.
+
+Definition preg_of (r: mreg) : preg :=
+ dreg_of r.
+
+(** Undefine all registers except SP and callee-save registers *)
+
+Definition undef_caller_save_regs (rs: regset) : regset :=
+ fun r =>
+ if preg_eq r SP
+ || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs))
+ then rs r
+ else Vundef.
+
+(** Extract the values of the arguments of an external call.
+ We exploit the calling conventions from module [Conventions], except that
+ we use AArch64 registers instead of locations. *)
+
+Inductive extcall_arg (rs: regset) (m: mem): loc -> val -> Prop :=
+ | extcall_arg_reg: forall r,
+ extcall_arg rs m (R r) (rs (preg_of r))
+ | extcall_arg_stack: forall ofs ty bofs v,
+ bofs = Stacklayout.fe_ofs_arg + 4 * ofs ->
+ Mem.loadv (chunk_of_type ty) m
+ (Val.offset_ptr rs#SP (Ptrofs.repr bofs)) = Some v ->
+ extcall_arg rs m (Locations.S Outgoing ofs ty) v.
+
+Inductive extcall_arg_pair (rs: regset) (m: mem): rpair loc -> val -> Prop :=
+ | extcall_arg_one: forall l v,
+ extcall_arg rs m l v ->
+ extcall_arg_pair rs m (One l) v
+ | extcall_arg_twolong: forall hi lo vhi vlo,
+ extcall_arg rs m hi vhi ->
+ extcall_arg rs m lo vlo ->
+ extcall_arg_pair rs m (Twolong hi lo) (Val.longofwords vhi vlo).
+
+Definition extcall_arguments
+ (rs: regset) (m: mem) (sg: signature) (args: list val) : Prop :=
+ list_forall2 (extcall_arg_pair rs m) (loc_arguments sg) args.
+
+Definition loc_external_result (sg: signature) : rpair preg :=
+ map_rpair preg_of (loc_result sg).
+
+(** Looking up instructions in a code sequence by position. *)
+
+Fixpoint find_instr (pos: Z) (c: code) {struct c} : option instruction :=
+ match c with
+ | nil => None
+ | i :: il => if zeq pos 0 then Some i else find_instr (pos - 1) il
+ end.
+
+(** Position corresponding to a label *)
+
+Definition is_label (lbl: label) (instr: instruction) : bool :=
+ match instr with
+ | Plabel lbl' => if peq lbl lbl' then true else false
+ | _ => false
+ end.
+
+Lemma is_label_correct:
+ forall lbl instr,
+ if is_label lbl instr then instr = Plabel lbl else instr <> Plabel lbl.
+Proof.
+ intros. destruct instr; simpl; try discriminate. destruct (peq lbl lbl0); congruence.
+Qed.
+
+Fixpoint label_pos (lbl: label) (pos: Z) (c: code) {struct c} : option Z :=
+ match c with
+ | nil => None
+ | instr :: c' =>
+ if is_label lbl instr then Some pos else label_pos lbl (pos + 1) c'
+ end.
+
+Definition nextinstr (rs: regset) :=
+ rs#PC <- (Val.offset_ptr rs#PC Ptrofs.one).
+
+Definition goto_label (f: function) (lbl: label) (rs: regset) (m: mem) :=
+ match label_pos lbl 0 (fn_code f) with
+ | None => Stuck
+ | Some pos =>
+ match rs#PC with
+ | Vptr b ofs => Next (rs#PC <- (Vptr b (Ptrofs.repr pos))) m
+ | _ => Stuck
+ end
+ end.
+
+Section RELSEM.
+
+Variable ge: genv.
+
+(** Evaluating an addressing mode *)
+
+Definition eval_addressing (a: addressing) (rs: regset): val :=
+ match a with
+ | ADimm base n => Val.addl rs#base (Vlong n)
+ | ADreg base r => Val.addl rs#base rs#r
+ | ADlsl base r n => Val.addl rs#base (Val.shll rs#r (Vint n))
+ | ADsxt base r n => Val.addl rs#base (Val.shll (Val.longofint rs#r) (Vint n))
+ | ADuxt base r n => Val.addl rs#base (Val.shll (Val.longofintu rs#r) (Vint n))
+ | ADadr base id ofs => Val.addl rs#base (symbol_low ge id ofs)
+ | ADpostincr base n => Vundef (* not modeled yet *)
+ end.
+
+(** Auxiliaries for memory accesses *)
+
+Definition exec_load (chunk: memory_chunk) (transf: val -> val)
+ (a: addressing) (r: preg) (rs: regset) (m: mem) :=
+ match Mem.loadv chunk m (eval_addressing a rs) with
+ | None => Stuck
+ | Some v => Next (nextinstr (rs#r <- (transf v))) m
+ end.
+
+Definition exec_store (chunk: memory_chunk)
+ (a: addressing) (v: val)
+ (rs: regset) (m: mem) :=
+ match Mem.storev chunk m (eval_addressing a rs) v with
+ | None => Stuck
+ | Some m' => Next (nextinstr rs) m'
+ end.
+
Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : outcome :=
match i with
@@ -704,13 +830,13 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Pret r =>
Next (rs#PC <- (rs#r)) m
| Pcbnz sz r lbl =>
- match eval_testzero sz rs#r m with
+ match eval_testzero sz rs#r with
| Some true => Next (nextinstr rs) m
| Some false => goto_label f lbl rs m
| None => Stuck
end
| Pcbz sz r lbl =>
- match eval_testzero sz rs#r m with
+ match eval_testzero sz rs#r with
| Some true => goto_label f lbl rs m
| Some false => Next (nextinstr rs) m
| None => Stuck
@@ -778,13 +904,13 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Psubimm X rd r1 n =>
Next (nextinstr (rs#rd <- (Val.subl rs#r1 (Vlong (Int64.repr n))))) m
| Pcmpimm W r1 n =>
- Next (nextinstr (compare_int rs rs#r1 (Vint (Int.repr n)) m)) m
+ Next (nextinstr (compare_int rs rs#r1 (Vint (Int.repr n)))) m
| Pcmpimm X r1 n =>
- Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.repr n)) m)) m
+ Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.repr n)))) m
| Pcmnimm W r1 n =>
- Next (nextinstr (compare_int rs rs#r1 (Vint (Int.neg (Int.repr n))) m)) m
+ Next (nextinstr (compare_int rs rs#r1 (Vint (Int.neg (Int.repr n))))) m
| Pcmnimm X r1 n =>
- Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.neg (Int64.repr n))) m)) m
+ Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.neg (Int64.repr n))))) m
(** Move integer register *)
| Pmov rd r1 =>
Next (nextinstr (rs#rd <- (rs#r1))) m
@@ -802,9 +928,9 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Porrimm X rd r1 n =>
Next (nextinstr (rs#rd <- (Val.orl rs###r1 (Vlong (Int64.repr n))))) m
| Ptstimm W r1 n =>
- Next (nextinstr (compare_int rs (Val.and rs#r1 (Vint (Int.repr n))) (Vint Int.zero) m)) m
+ Next (nextinstr (compare_int rs (Val.and rs#r1 (Vint (Int.repr n))) (Vint Int.zero))) m
| Ptstimm X r1 n =>
- Next (nextinstr (compare_long rs (Val.andl rs#r1 (Vlong (Int64.repr n))) (Vlong Int64.zero) m)) m
+ Next (nextinstr (compare_long rs (Val.andl rs#r1 (Vlong (Int64.repr n))) (Vlong Int64.zero))) m
(** Move wide immediate *)
| Pmovz W rd n pos =>
Next (nextinstr (rs#rd <- (Vint (Int.repr (Z.shiftl n pos))))) m
@@ -850,22 +976,22 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Psub X rd r1 r2 s =>
Next (nextinstr (rs#rd <- (Val.subl rs###r1 (eval_shift_op_long rs#r2 s)))) m
| Pcmp W r1 r2 s =>
- Next (nextinstr (compare_int rs rs##r1 (eval_shift_op_int rs#r2 s) m)) m
+ Next (nextinstr (compare_int rs rs##r1 (eval_shift_op_int rs#r2 s))) m
| Pcmp X r1 r2 s =>
- Next (nextinstr (compare_long rs rs###r1 (eval_shift_op_long rs#r2 s) m)) m
+ Next (nextinstr (compare_long rs rs###r1 (eval_shift_op_long rs#r2 s))) m
| Pcmn W r1 r2 s =>
- Next (nextinstr (compare_int rs rs##r1 (Val.neg (eval_shift_op_int rs#r2 s)) m)) m
+ Next (nextinstr (compare_int rs rs##r1 (Val.neg (eval_shift_op_int rs#r2 s)))) m
| Pcmn X r1 r2 s =>
- Next (nextinstr (compare_long rs rs###r1 (Val.negl (eval_shift_op_long rs#r2 s)) m)) m
+ Next (nextinstr (compare_long rs rs###r1 (Val.negl (eval_shift_op_long rs#r2 s)))) m
(** Integer arithmetic, extending register *)
| Paddext rd r1 r2 x =>
Next (nextinstr (rs#rd <- (Val.addl rs#r1 (eval_extend rs#r2 x)))) m
| Psubext rd r1 r2 x =>
Next (nextinstr (rs#rd <- (Val.subl rs#r1 (eval_extend rs#r2 x)))) m
| Pcmpext r1 r2 x =>
- Next (nextinstr (compare_long rs rs#r1 (eval_extend rs#r2 x) m)) m
+ Next (nextinstr (compare_long rs rs#r1 (eval_extend rs#r2 x))) m
| Pcmnext r1 r2 x =>
- Next (nextinstr (compare_long rs rs#r1 (Val.negl (eval_extend rs#r2 x)) m)) m
+ Next (nextinstr (compare_long rs rs#r1 (Val.negl (eval_extend rs#r2 x)))) m
(** Logical, shifted register *)
| Pand W rd r1 r2 s =>
Next (nextinstr (rs#rd <- (Val.and rs##r1 (eval_shift_op_int rs#r2 s)))) m
@@ -892,9 +1018,9 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Porn X rd r1 r2 s =>
Next (nextinstr (rs#rd <- (Val.orl rs###r1 (Val.notl (eval_shift_op_long rs#r2 s))))) m
| Ptst W r1 r2 s =>
- Next (nextinstr (compare_int rs (Val.and rs##r1 (eval_shift_op_int rs#r2 s)) (Vint Int.zero) m)) m
+ Next (nextinstr (compare_int rs (Val.and rs##r1 (eval_shift_op_int rs#r2 s)) (Vint Int.zero))) m
| Ptst X r1 r2 s =>
- Next (nextinstr (compare_long rs (Val.andl rs###r1 (eval_shift_op_long rs#r2 s)) (Vlong Int64.zero) m)) m
+ Next (nextinstr (compare_long rs (Val.andl rs###r1 (eval_shift_op_long rs#r2 s)) (Vlong Int64.zero))) m
(** Variable shifts *)
| Pasrv W rd r1 r2 =>
Next (nextinstr (rs#rd <- (Val.shr rs#r1 rs#r2))) m
@@ -1118,80 +1244,9 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
Stuck
end.
-(** Translation of the LTL/Linear/Mach view of machine registers
- to the AArch64 view. Note that no LTL register maps to [X16],
- [X18], nor [X30].
- [X18] is reserved as the platform register and never used by the
- code generated by CompCert.
- [X30] is used for the return address, and can also be used as temporary.
- [X16] can be used as temporary. *)
-
-Definition preg_of (r: mreg) : preg :=
- match r with
- | R0 => X0 | R1 => X1 | R2 => X2 | R3 => X3
- | R4 => X4 | R5 => X5 | R6 => X6 | R7 => X7
- | R8 => X8 | R9 => X9 | R10 => X10 | R11 => X11
- | R12 => X12 | R13 => X13 | R14 => X14 | R15 => X15
- | R17 => X17 | R19 => X19
- | R20 => X20 | R21 => X21 | R22 => X22 | R23 => X23
- | R24 => X24 | R25 => X25 | R26 => X26 | R27 => X27
- | R28 => X28 | R29 => X29
- | F0 => D0 | F1 => D1 | F2 => D2 | F3 => D3
- | F4 => D4 | F5 => D5 | F6 => D6 | F7 => D7
- | F8 => D8 | F9 => D9 | F10 => D10 | F11 => D11
- | F12 => D12 | F13 => D13 | F14 => D14 | F15 => D15
- | F16 => D16 | F17 => D17 | F18 => D18 | F19 => D19
- | F20 => D20 | F21 => D21 | F22 => D22 | F23 => D23
- | F24 => D24 | F25 => D25 | F26 => D26 | F27 => D27
- | F28 => D28 | F29 => D29 | F30 => D30 | F31 => D31
- end.
-
-(** Undefine all registers except SP and callee-save registers *)
-
-Definition undef_caller_save_regs (rs: regset) : regset :=
- fun r =>
- if preg_eq r SP
- || In_dec preg_eq r (List.map preg_of (List.filter is_callee_save all_mregs))
- then rs r
- else Vundef.
-
-(** Extract the values of the arguments of an external call.
- We exploit the calling conventions from module [Conventions], except that
- we use AArch64 registers instead of locations. *)
-
-Inductive extcall_arg (rs: regset) (m: mem): loc -> val -> Prop :=
- | extcall_arg_reg: forall r,
- extcall_arg rs m (R r) (rs (preg_of r))
- | extcall_arg_stack: forall ofs ty bofs v,
- bofs = Stacklayout.fe_ofs_arg + 4 * ofs ->
- Mem.loadv (chunk_of_type ty) m
- (Val.offset_ptr rs#SP (Ptrofs.repr bofs)) = Some v ->
- extcall_arg rs m (Locations.S Outgoing ofs ty) v.
-
-Inductive extcall_arg_pair (rs: regset) (m: mem): rpair loc -> val -> Prop :=
- | extcall_arg_one: forall l v,
- extcall_arg rs m l v ->
- extcall_arg_pair rs m (One l) v
- | extcall_arg_twolong: forall hi lo vhi vlo,
- extcall_arg rs m hi vhi ->
- extcall_arg rs m lo vlo ->
- extcall_arg_pair rs m (Twolong hi lo) (Val.longofwords vhi vlo).
-
-Definition extcall_arguments
- (rs: regset) (m: mem) (sg: signature) (args: list val) : Prop :=
- list_forall2 (extcall_arg_pair rs m) (loc_arguments sg) args.
-
-Definition loc_external_result (sg: signature) : rpair preg :=
- map_rpair preg_of (loc_result sg).
-
-(** Execution of the instruction at [rs#PC]. *)
-
-Inductive state: Type :=
- | State: regset -> mem -> state.
-
Inductive step: state -> trace -> state -> Prop :=
| exec_step_internal:
- forall b ofs f i rs m rs' m',
+ forall b ofs (f:function) i rs m rs' m',
rs PC = Vptr b ofs ->
Genv.find_funct_ptr ge b = Some (Internal f) ->
find_instr (Ptrofs.unsigned ofs) f.(fn_code) = Some i ->
@@ -1302,11 +1357,11 @@ Qed.
Definition data_preg (r: preg) : bool :=
match r with
- | IR X16 => false
- | IR X30 => false
- | IR _ => true
- | FR _ => true
+ | DR (IR X16) => false
+ | DR (IR X30) => false
+ | DR (IR _) => true
+ | DR (FR _) => true
| CR _ => false
- | SP => true
+ (* | SP => true; subsumed by IR (iregsp) *)
| PC => false
end.
diff --git a/aarch64/Asmblock.v b/aarch64/Asmblock.v
new file mode 100644
index 00000000..5da7e20a
--- /dev/null
+++ b/aarch64/Asmblock.v
@@ -0,0 +1,1554 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Justus Fasse UGA, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+
+(* Asmblock language for aarch64
+
+WORK IN PROGRESS: we want to define an Asmblock syntax, with an Asmblock semantics
+(e.g. we don't need the parallel semantics of Asmvliw)
+
+
+NOTE: this file is inspired from
+ - aarch64/Asm.v
+ - kvx/Asmvliw.v (only the Asmblock syntax)
+ - kvx/Asmblock.v
+*)
+
+
+(** Abstract syntax and semantics for AArch64 assembly language *)
+
+Require Import Coqlib Zbits Maps.
+Require Import AST Integers Floats.
+Require Import Values Memory Events Globalenvs Smallstep.
+Require Import Locations Conventions.
+Require Stacklayout.
+Require Import OptionMonad Asm.
+Require Export Asm.
+
+Local Open Scope option_monad_scope.
+
+(** * Abstract syntax *)
+
+(* First task: splitting the big [instruction] type below into CFI and basic instructions.
+ Actually a finer splitting in order to regroup "similar" instructions could be much better for automation of the scheduler proof!
+ e.g. "similar" means identical "interface" w.r.t. pseudo-registers when translated to AbstractBB,
+ or with a "similar" semantics.
+
+ see example of loads below.
+*)
+
+(** Control Flow instructions
+
+*)
+Inductive cf_instruction : Type :=
+ | Pb (lbl: label) (**r branch *)
+ | Pbc (c: testcond) (lbl: label) (**r conditional branch *)
+ | Pbl (id: ident) (sg: signature) (**r jump to function and link *)
+ | Pbs (id: ident) (sg: signature) (**r jump to function *)
+ | Pblr (r: ireg) (sg: signature) (**r indirect jump and link *)
+ | Pbr (r: ireg) (sg: signature) (**r indirect jump *)
+ | Pret (r: ireg) (**r return *)
+ | Pcbnz (sz: isize) (r: ireg) (lbl: label) (**r branch if not zero *)
+ | Pcbz (sz: isize) (r: ireg) (lbl: label) (**r branch if zero *)
+ | Ptbnz (sz: isize) (r: ireg) (n: int) (lbl: label) (**r branch if bit n is not zero *)
+ | Ptbz (sz: isize) (r: ireg) (n: int) (lbl: label) (**r branch if bit n is zero *)
+ (** Pseudo-instructions *)
+ | Pbtbl (r1: ireg) (tbl: list label) (**r N-way branch through a jump table *)
+ .
+
+(*
+A builtin is considered as a control-flow instruction, because it could emit a trace (cf. Machblock semantics).
+Here, we do not need to have builtins alone in basic-blocks (on the contrary to KVX bundles).
+*)
+
+Inductive control: Type :=
+ | PCtlFlow (i: cf_instruction)
+ (** Pseudo-instructions *)
+ | Pbuiltin (ef: external_function)
+ (args: list (builtin_arg dreg)) (res: builtin_res dreg) (**r built-in function (pseudo) *)
+ .
+
+Coercion PCtlFlow: cf_instruction >-> control.
+
+(** Basic instructions *)
+
+(* Loads waiting for (rd: dreg) (a: addressing)
+ * XXX Use dreg because exec_load is defined in terms of it, thus allowing us to
+ * treat integer and floating point loads the same. *)
+Inductive load_rd_a: Type :=
+ (* Integer load *)
+ | Pldrw (**r load int32 *)
+ | Pldrw_a (**r load int32 as any32 *)
+ | Pldrx (**r load int64 *)
+ | Pldrx_a (**r load int64 as any64 *)
+ | Pldrb (sz: isize) (**r load int8, zero-extend *)
+ | Pldrsb (sz: isize) (**r load int8, sign-extend *)
+ | Pldrh (sz: isize) (**r load int16, zero-extend *)
+ | Pldrsh (sz: isize) (**r load int16, sign-extend *)
+ | Pldrzw (**r load int32, zero-extend to int64 *)
+ | Pldrsw (**r load int32, sign-extend to int64 *)
+ (* Floating-point load *)
+ | Pldrs (**r load float32 (single precision) *)
+ | Pldrd (**r load float64 (double precision) *)
+ | Pldrd_a (**r load float64 as any64 *)
+ .
+
+(* Actually, Pldp is not used in the aarch64/Asm semantics!
+
+Thus we skip this particular case:
+
+Inductive ld_instruction: Type :=
+ | PLd_rd_a (ld: load_rd_a) (rd: ireg) (a: addressing)
+ | Pldp (rd1 rd2: ireg) (a: addressing) (**r load two int64 *)
+ .
+
+Coercion PLoad: ld_instruction >-> basic.
+
+*)
+
+Inductive store_rs_a : Type :=
+ (* Integer store *)
+ | Pstrw (**r store int32 *)
+ | Pstrw_a (**r store int32 as any32 *)
+ | Pstrx (**r store int64 *)
+ | Pstrx_a (**r store int64 as any64 *)
+ | Pstrb (**r store int8 *)
+ | Pstrh (**r store int16 *)
+ (* Floating-point store *)
+ | Pstrs (**r store float32 *)
+ | Pstrd (**r store float64 *)
+ | Pstrd_a (**r store float64 as any64 *)
+ .
+(* Actually, Pstp is not used in the aarch64/Asm semantics!
+ * Thus we skip this particular case:
+ * Inductive st_instruction : Type :=
+ * | PSt_rs_a (st : store_rs_a) (rs : ireg) (a : addressing)
+ * | Pstp (rs1 rs2: ireg) (a: addressing) (**r store two int64 *)
+ * .
+ * Coercion PStore : st_instruction >-> basic.
+ *)
+
+Inductive arith_p : Type :=
+ (** PC-relative addressing *)
+ | Padrp (id: ident) (ofs: ptrofs) (**r set [rd] to high address of [id + ofs] *)
+ (** Move wide immediate *)
+ | Pmovz (sz: isize) (n: Z) (pos: Z) (**r move [n << pos] to [rd] *)
+ | Pmovn (sz: isize) (n: Z) (pos: Z) (**r move [NOT(n << pos)] to [rd] *)
+ (** Floating-point move *)
+ | Pfmovimms (f: float32) (**r load float32 constant *)
+ | Pfmovimmd (f: float) (**r load float64 constant *)
+.
+
+Inductive arith_comparison_p : Type :=
+ (** Floating-point comparison *)
+ | Pfcmp0 (sz: fsize) (**r compare [r1] and [+0.0] *)
+ (** Integer arithmetic, immediate *)
+ | Pcmpimm (sz: isize) (n: Z) (**r compare *)
+ | Pcmnimm (sz: isize) (n: Z) (**r compare negative *)
+ (** Logical, immediate *)
+ | Ptstimm (sz: isize) (n: Z) (**r and, then set flags *)
+.
+
+Inductive arith_pp : Type :=
+ (** Move integer register *)
+ | Pmov
+ (** Move wide immediate *)
+ (* XXX: has to have the same register supplied both times *)
+ | Pmovk (sz: isize) (n: Z) (pos: Z) (**r insert 16 bits of [n] at [pos] in rd *)
+ (** PC-relative addressing *)
+ | Paddadr (id: ident) (ofs: ptrofs) (**r add the low address of [id + ofs] *)
+ (** Bit-field operations *)
+ | Psbfiz (sz: isize) (r: int) (s: Z) (**r sign extend and shift left *)
+ | Psbfx (sz: isize) (r: int) (s: Z) (**r shift right and sign extend *)
+ | Pubfiz (sz: isize) (r: int) (s: Z) (**r zero extend and shift left *)
+ | Pubfx (sz: isize) (r: int) (s: Z) (**r shift right and zero extend *)
+(* Bit operations are not used in the aarch64/asm semantics
+ (** Bit operations *)
+ | Pcls (sz: isize) (**r count leading sign bits *)
+ | Pclz (sz: isize) (**r count leading zero bits *)
+ | Prev (sz: isize) (**r reverse bytes *)
+ | Prev16 (sz: isize) (**r reverse bytes in each 16-bit word *)
+*)
+ (** Floating-point move *)
+ | Pfmov
+ (** Floating-point conversions *)
+ | Pfcvtds (**r convert float32 to float64 *)
+ | Pfcvtsd (**r convert float64 to float32 *)
+ (** Floating-point arithmetic *)
+ | Pfabs (sz: fsize) (**r absolute value *)
+ | Pfneg (sz: fsize) (**r negation *)
+ (* Pfsqrt is not used in the semantics of aarch64/asm
+ | Pfsqrt (sz: fsize) (**r square root *) *)
+ (** Floating-point conversions *)
+ | Pscvtf (fsz: fsize) (isz: isize) (**r convert signed int to float *)
+ | Pucvtf (fsz: fsize) (isz: isize) (**r convert unsigned int to float *)
+ | Pfcvtzs (isz: isize) (fsz: fsize) (**r convert float to signed int *)
+ | Pfcvtzu (isz: isize) (fsz: fsize) (**r convert float to unsigned int *)
+ (** Integer arithmetic, immediate *)
+ | Paddimm (sz: isize) (n: Z) (**r addition *)
+ | Psubimm (sz: isize) (n: Z) (**r subtraction *)
+.
+
+Inductive arith_comparison_r0r : Type :=
+ (** Integer arithmetic, shifted register *)
+ | Pcmp (is:isize) (s: shift_op) (**r compare *)
+ | Pcmn (is:isize) (s: shift_op) (**r compare negative *)
+ (** Logical, shifted register *)
+ | Ptst (is:isize) (s: shift_op) (**r and, then set flags *)
+.
+
+Inductive arith_comparison_pp : Type :=
+ (** Integer arithmetic, extending register *)
+ | Pcmpext (x: extend_op) (**r int64-int32 cmp *)
+ | Pcmnext (x: extend_op) (**r int64-int32 cmn *)
+ (** Floating-point comparison *)
+ | Pfcmp (sz: fsize) (**r compare [r1] and [r2] *)
+.
+
+Inductive arith_ppp : Type :=
+ (** Variable shifts *)
+ | Pasrv (sz: isize) (**r arithmetic right shift *)
+ | Plslv (sz: isize) (**r left shift *)
+ | Plsrv (sz: isize) (**r logical right shift *)
+ | Prorv (sz: isize) (**r rotate right *)
+ (** Integer multiply/divide *)
+ | Psmulh (**r signed multiply high *)
+ | Pumulh (**r unsigned multiply high *)
+ | Psdiv (sz: isize) (**r signed division *)
+ | Pudiv (sz: isize) (**r unsigned division *)
+ (** Integer arithmetic, extending register *)
+ | Paddext (x: extend_op) (**r int64-int32 add *)
+ | Psubext (x: extend_op) (**r int64-int32 sub *)
+ (** Floating-point arithmetic *)
+ | Pfadd (sz: fsize) (**r addition *)
+ | Pfdiv (sz: fsize) (**r division *)
+ | Pfmul (sz: fsize) (**r multiplication *)
+ | Pfsub (sz: fsize) (**r subtraction *)
+.
+
+Inductive arith_rr0r : Type :=
+ (** Integer arithmetic, shifted register *)
+ | Padd (sz:isize) (s: shift_op) (**r addition *)
+ | Psub (sz:isize) (s: shift_op) (**r subtraction *)
+ (** Logical, shifted register *)
+ | Pand (sz:isize) (s: shift_op) (**r and *)
+ | Pbic (sz:isize) (s: shift_op) (**r and-not *)
+ | Peon (sz:isize) (s: shift_op) (**r xor-not *)
+ | Peor (sz:isize) (s: shift_op) (**r xor *)
+ | Porr (sz:isize) (s: shift_op) (**r or *)
+ | Porn (sz:isize) (s: shift_op) (**r or-not *)
+.
+
+
+Inductive arith_rr0 : Type :=
+ (** Logical, immediate *)
+ | Pandimm (sz: isize) (n: Z) (**r and *)
+ | Peorimm (sz: isize) (n: Z) (**r xor *)
+ | Porrimm (sz: isize) (n: Z) (**r or *)
+.
+
+Inductive arith_arrrr0 : Type :=
+ (** Integer multiply/divide *)
+ | Pmadd (sz: isize) (**r multiply-add *)
+ | Pmsub (sz: isize) (**r multiply-sub *)
+.
+
+(* Currently not used by the semantics of aarch64/Asm
+ * Inductive arith_apppp : Type :=
+ * (** Floating-point arithmetic *)
+ * | Pfmadd (sz: fsize) (**r [rd = r3 + r1 * r2] *)
+ * | Pfmsub (sz: fsize) (**r [rd = r3 - r1 * r2] *)
+ * .
+
+ * Inductive arith_aapppp : Type :=
+ * (** Floating-point arithmetic *)
+ * | Pfnmadd (sz: fsize) (**r [rd = - r3 - r1 * r2] *)
+ * | Pfnmsub (sz: fsize) (**r [rd = - r3 + r1 * r2] *)
+ * . *)
+
+(* Notes on the naming scheme used here:
+ * R: ireg
+ * R0: ireg0
+ * Rsp: iregsp
+ * F: freg
+ * W/X: Occur in conjunction with R0, says whether an ireg0 should be evaluated
+ * as W regsiter (32 bit) or X register (64 bit)
+ * S/D: Used for completeness sake. Only used for copying an integer register
+ * to a floating point register. Could be removed.
+ * A: These instructions perform an additional arithmetic operation
+ XXX Does this interpretation match the use in kvx/Asmvliw?
+ * Comparison: For these instructions the first register is not the target.
+ * Instead, the condition register is mutated.
+ *)
+Inductive ar_instruction : Type :=
+ | PArithP (i : arith_p) (rd : dreg)
+ | PArithPP (i : arith_pp) (rd rs : dreg)
+ | PArithPPP (i : arith_ppp) (rd r1 r2 : dreg)
+ | PArithRR0R (i : arith_rr0r) (rd : ireg) (r1 : ireg0) (r2 : ireg)
+ | PArithRR0 (i : arith_rr0) (rd : ireg) (r1 : ireg0)
+ | PArithARRRR0 (i : arith_arrrr0) (rd r1 r2 : ireg) (r3 : ireg0)
+ (* Pfmadd and Pfmsub are currently not used by the semantics of aarch64/Asm
+ | PArithAPPPP (i : arith_apppp) (rd r1 r2 r3 : preg) *)
+ (* Pfnmadd and Pfnmsub are currently not used by the semantics of aarch64/Asm
+ | PArithAAPPPP (i : arith_aapppp) (rd r1 r2 r3 : preg) *)
+ | PArithComparisonPP (i : arith_comparison_pp) (r1 r2 : dreg)
+ | PArithComparisonR0R (i : arith_comparison_r0r) (r1 : ireg0) (r2 : ireg)
+ | PArithComparisonP (i : arith_comparison_p) (r1 : dreg)
+ (* Instructions without indirection sine they would be the only ones *)
+ (* PArithCP: Pcsetm is commented out by aarch64/Asm, so Pcset is alone *)
+ | Pcset (rd : ireg) (c : testcond) (**r set to 1/0 if cond is true/false *)
+ (* PArithFR0 *)
+ | Pfmovi (fsz : fsize) (rd : freg) (r1 : ireg0) (**r copy int reg to FP reg *)
+ (* PArithCPPP *)
+ | Pcsel (rd r1 r2 : dreg) (c : testcond) (**r int/float conditional move *)
+ (* PArithAFFF *)
+ | Pfnmul (fsz : fsize) (rd r1 r2 : freg) (**r multiply-negate *)
+.
+
+Inductive basic : Type :=
+ | PArith (i: ar_instruction) (**r TODO *)
+ | PLoad (ld: load_rd_a) (rd: dreg) (a: addressing) (**r TODO *)
+ | PStore (st: store_rs_a) (r: dreg) (a: addressing) (**r TODO *)
+ | Pallocframe (sz: Z) (linkofs: ptrofs) (**r allocate new stack frame *)
+ | Pfreeframe (sz: Z) (linkofs: ptrofs) (**r deallocate stack frame and restore previous frame *)
+ | Ploadsymbol (rd: ireg) (id: ident) (**r load the address of [id] *)
+ | Pcvtsw2x (rd: ireg) (r1: ireg) (**r sign-extend 32-bit int to 64-bit *)
+ | Pcvtuw2x (rd: ireg) (r1: ireg) (**r zero-extend 32-bit int to 64-bit *)
+ | Pcvtx2w (rd: ireg) (**r retype a 64-bit int as a 32-bit int *)
+(* NOT USED IN THE SEMANTICS !
+ | Pnop (**r no operation *)
+ | Pcfi_adjust (ofs: int) (**r .cfi_adjust debug directive *)
+ | Pcfi_rel_offset (ofs: int) (**r .cfi_rel_offset debug directive *)
+*)
+.
+
+Inductive instruction : Type :=
+ | PBasic (i: basic)
+ | PControl (i: control).
+
+Coercion PBasic: basic >-> instruction.
+Coercion PControl: control >-> instruction.
+
+(** * Definition of a bblock
+
+A bblock must contain at least one instruction.
+
+This choice simplifies the definition of [find_bblock] below:
+indeed, each address of a code block identifies at most one bblock.
+*)
+
+Definition non_empty_body (body: list basic): bool :=
+ match body with
+ | nil => false
+ | _ => true
+ end.
+
+Definition non_empty_exit (exit: option control): bool :=
+ match exit with
+ | None => false
+ | _ => true
+ end.
+
+Definition non_empty_bblockb (body: list basic) (exit: option control): bool := non_empty_body body || non_empty_exit exit.
+
+(** A bblock is well-formed if he contains at least one instruction. *)
+
+Record bblock := mk_bblock {
+ header: list label;
+ body: list basic;
+ exit: option control;
+ correct: Is_true (non_empty_bblockb body exit)
+}.
+
+(* FIXME? redundant with definition in Machblock *)
+Definition length_opt {A} (o: option A) : nat :=
+ match o with
+ | Some o => 1
+ | None => 0
+ end.
+
+Program Definition no_header (bb : bblock) := {| header := nil; body := body bb; exit := exit bb |}.
+Next Obligation.
+ destruct bb; cbn. assumption.
+Defined.
+
+Program Definition stick_header (h : list label) (bb : bblock) := {| header := h; body := body bb; exit := exit bb |}.
+Next Obligation.
+ destruct bb; cbn. assumption.
+Defined.
+
+(* This notion of size induces the notion of "valid" code address given by [find_bblock]
+
+ The result is in Z to be compatible with operations on PC.
+*)
+Definition size (b:bblock): Z := Z.of_nat (length (header b) + length (body b) + length_opt (exit b)).
+
+Definition bblocks := list bblock.
+
+Fixpoint size_blocks (l: bblocks): Z :=
+ match l with
+ | nil => 0
+ | b :: l =>
+ (size b) + (size_blocks l)
+ end
+ .
+
+Record function : Type := mkfunction { fn_sig: signature; fn_blocks: bblocks }.
+Definition fundef := AST.fundef function.
+Definition program := AST.program fundef unit.
+
+(* TODO: ORIGINAL ABSTRACT SYNTAX OF INSTRUCTIONS THAT NEEDS TO BE ADAPTED !
+
+Inductive instruction: Type :=
+ (** Branches *)
+ | Pb (lbl: label) (**r branch *)
+ | Pbc (c: testcond) (lbl: label) (**r conditional branch *)
+ | Pbl (id: ident) (sg: signature) (**r jump to function and link *)
+ | Pbs (id: ident) (sg: signature) (**r jump to function *)
+ | Pblr (r: ireg) (sg: signature) (**r indirect jump and link *)
+ | Pbr (r: ireg) (sg: signature) (**r indirect jump *)
+ | Pret (r: ireg) (**r return *)
+ | Pcbnz (sz: isize) (r: ireg) (lbl: label) (**r branch if not zero *)
+ | Pcbz (sz: isize) (r: ireg) (lbl: label) (**r branch if zero *)
+ | Ptbnz (sz: isize) (r: ireg) (n: int) (lbl: label) (**r branch if bit n is not zero *)
+ | Ptbz (sz: isize) (r: ireg) (n: int) (lbl: label) (**r branch if bit n is zero *)
+ (** Memory loads and stores *)
+ | Pldrw (rd: ireg) (a: addressing) (**r load int32 *)
+ | Pldrw_a (rd: ireg) (a: addressing) (**r load int32 as any32 *)
+ | Pldrx (rd: ireg) (a: addressing) (**r load int64 *)
+ | Pldrx_a (rd: ireg) (a: addressing) (**r load int64 as any64 *)
+ | Pldrb (sz: isize) (rd: ireg) (a: addressing) (**r load int8, zero-extend *)
+ | Pldrsb (sz: isize) (rd: ireg) (a: addressing) (**r load int8, sign-extend *)
+ | Pldrh (sz: isize) (rd: ireg) (a: addressing) (**r load int16, zero-extend *)
+ | Pldrsh (sz: isize) (rd: ireg) (a: addressing) (**r load int16, sign-extend *)
+ | Pldrzw (rd: ireg) (a: addressing) (**r load int32, zero-extend to int64 *)
+ | Pldrsw (rd: ireg) (a: addressing) (**r load int32, sign-extend to int64 *)
+ | Pldp (rd1 rd2: ireg) (a: addressing) (**r load two int64 *)
+ | Pstrw (rs: ireg) (a: addressing) (**r store int32 *)
+ | Pstrw_a (rs: ireg) (a: addressing) (**r store int32 as any32 *)
+ | Pstrx (rs: ireg) (a: addressing) (**r store int64 *)
+ | Pstrx_a (rs: ireg) (a: addressing) (**r store int64 as any64 *)
+ | Pstrb (rs: ireg) (a: addressing) (**r store int8 *)
+ | Pstrh (rs: ireg) (a: addressing) (**r store int16 *)
+ | Pstp (rs1 rs2: ireg) (a: addressing) (**r store two int64 *)
+ (** Integer arithmetic, immediate *)
+ | Paddimm (sz: isize) (rd: iregsp) (r1: iregsp) (n: Z) (**r addition *)
+ | Psubimm (sz: isize) (rd: iregsp) (r1: iregsp) (n: Z) (**r subtraction *)
+ | Pcmpimm (sz: isize) (r1: ireg) (n: Z) (**r compare *)
+ | Pcmnimm (sz: isize) (r1: ireg) (n: Z) (**r compare negative *)
+ (** Move integer register *)
+ | Pmov (rd: iregsp) (r1: iregsp)
+ (** Logical, immediate *)
+ | Pandimm (sz: isize) (rd: ireg) (r1: ireg0) (n: Z) (**r and *)
+ | Peorimm (sz: isize) (rd: ireg) (r1: ireg0) (n: Z) (**r xor *)
+ | Porrimm (sz: isize) (rd: ireg) (r1: ireg0) (n: Z) (**r or *)
+ | Ptstimm (sz: isize) (r1: ireg) (n: Z) (**r and, then set flags *)
+ (** Move wide immediate *)
+ | Pmovz (sz: isize) (rd: ireg) (n: Z) (pos: Z) (**r move [n << pos] to [rd] *)
+ | Pmovn (sz: isize) (rd: ireg) (n: Z) (pos: Z) (**r move [NOT(n << pos)] to [rd] *)
+ | Pmovk (sz: isize) (rd: ireg) (n: Z) (pos: Z) (**r insert 16 bits of [n] at [pos] in rd *)
+ (** PC-relative addressing *)
+ | Padrp (rd: ireg) (id: ident) (ofs: ptrofs) (**r set [rd] to high address of [id + ofs] *)
+ | Paddadr (rd: ireg) (r1: ireg) (id: ident) (ofs: ptrofs) (**r add the low address of [id + ofs] *)
+ (** Bit-field operations *)
+ | Psbfiz (sz: isize) (rd: ireg) (r1: ireg) (r: int) (s: Z) (**r sign extend and shift left *)
+ | Psbfx (sz: isize) (rd: ireg) (r1: ireg) (r: int) (s: Z) (**r shift right and sign extend *)
+ | Pubfiz (sz: isize) (rd: ireg) (r1: ireg) (r: int) (s: Z) (**r zero extend and shift left *)
+ | Pubfx (sz: isize) (rd: ireg) (r1: ireg) (r: int) (s: Z) (**r shift right and zero extend *)
+ (** Integer arithmetic, shifted register *)
+ | Padd (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r addition *)
+ | Psub (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r subtraction *)
+ | Pcmp (sz: isize) (r1: ireg0) (r2: ireg) (s: shift_op) (**r compare *)
+ | Pcmn (sz: isize) (r1: ireg0) (r2: ireg) (s: shift_op) (**r compare negative *)
+ (** Integer arithmetic, extending register *)
+ | Paddext (rd: iregsp) (r1: iregsp) (r2: ireg) (x: extend_op) (**r int64-int32 add *)
+ | Psubext (rd: iregsp) (r1: iregsp) (r2: ireg) (x: extend_op) (**r int64-int32 sub *)
+ | Pcmpext (r1: ireg) (r2: ireg) (x: extend_op) (**r int64-int32 cmp *)
+ | Pcmnext (r1: ireg) (r2: ireg) (x: extend_op) (**r int64-int32 cmn *)
+ (** Logical, shifted register *)
+ | Pand (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r and *)
+ | Pbic (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r and-not *)
+ | Peon (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r xor-not *)
+ | Peor (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r xor *)
+ | Porr (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r or *)
+ | Porn (sz: isize) (rd: ireg) (r1: ireg0) (r2: ireg) (s: shift_op) (**r or-not *)
+ | Ptst (sz: isize) (r1: ireg0) (r2: ireg) (s: shift_op) (**r and, then set flags *)
+ (** Variable shifts *)
+ | Pasrv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r arithmetic right shift *)
+ | Plslv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r left shift *)
+ | Plsrv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r logical right shift *)
+ | Prorv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r rotate right *)
+ (** Bit operations *)
+ | Pcls (sz: isize) (rd r1: ireg) (**r count leading sign bits *)
+ | Pclz (sz: isize) (rd r1: ireg) (**r count leading zero bits *)
+ | Prev (sz: isize) (rd r1: ireg) (**r reverse bytes *)
+ | Prev16 (sz: isize) (rd r1: ireg) (**r reverse bytes in each 16-bit word *)
+ (** Conditional data processing *)
+ | Pcsel (rd: ireg) (r1 r2: ireg) (c: testcond) (**r int conditional move *)
+ | Pcset (rd: ireg) (c: testcond) (**r set to 1/0 if cond is true/false *)
+(*
+ | Pcsetm (rd: ireg) (c: testcond) (**r set to -1/0 if cond is true/false *)
+*)
+ (** Integer multiply/divide *)
+ | Pmadd (sz: isize) (rd: ireg) (r1 r2: ireg) (r3: ireg0) (**r multiply-add *)
+ | Pmsub (sz: isize) (rd: ireg) (r1 r2: ireg) (r3: ireg0) (**r multiply-sub *)
+ | Psmulh (rd: ireg) (r1 r2: ireg) (**r signed multiply high *)
+ | Pumulh (rd: ireg) (r1 r2: ireg) (**r unsigned multiply high *)
+ | Psdiv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r signed division *)
+ | Pudiv (sz: isize) (rd: ireg) (r1 r2: ireg) (**r unsigned division *)
+ (** Floating-point loads and stores *)
+ | Pldrs (rd: freg) (a: addressing) (**r load float32 (single precision) *)
+ | Pldrd (rd: freg) (a: addressing) (**r load float64 (double precision) *)
+ | Pldrd_a (rd: freg) (a: addressing) (**r load float64 as any64 *)
+ | Pstrs (rs: freg) (a: addressing) (**r store float32 *)
+ | Pstrd (rs: freg) (a: addressing) (**r store float64 *)
+ | Pstrd_a (rs: freg) (a: addressing) (**r store float64 as any64 *)
+ (** Floating-point move *)
+ | Pfmov (rd r1: freg)
+ | Pfmovimms (rd: freg) (f: float32) (**r load float32 constant *)
+ | Pfmovimmd (rd: freg) (f: float) (**r load float64 constant *)
+ | Pfmovi (fsz: fsize) (rd: freg) (r1: ireg0) (**r copy int reg to FP reg *)
+ (** Floating-point conversions *)
+ | Pfcvtds (rd r1: freg) (**r convert float32 to float64 *)
+ | Pfcvtsd (rd r1: freg) (**r convert float64 to float32 *)
+ | Pfcvtzs (isz: isize) (fsz: fsize) (rd: ireg) (r1: freg) (**r convert float to signed int *)
+ | Pfcvtzu (isz: isize) (fsz: fsize) (rd: ireg) (r1: freg) (**r convert float to unsigned int *)
+ | Pscvtf (fsz: fsize) (isz: isize) (rd: freg) (r1: ireg) (**r convert signed int to float *)
+ | Pucvtf (fsz: fsize) (isz: isize) (rd: freg) (r1: ireg) (**r convert unsigned int to float *)
+ (** Floating-point arithmetic *)
+ | Pfabs (sz: fsize) (rd r1: freg) (**r absolute value *)
+ | Pfneg (sz: fsize) (rd r1: freg) (**r negation *)
+ | Pfsqrt (sz: fsize) (rd r1: freg) (**r square root *)
+ | Pfadd (sz: fsize) (rd r1 r2: freg) (**r addition *)
+ | Pfdiv (sz: fsize) (rd r1 r2: freg) (**r division *)
+ | Pfmul (sz: fsize) (rd r1 r2: freg) (**r multiplication *)
+ | Pfnmul (sz: fsize) (rd r1 r2: freg) (**r multiply-negate *)
+ | Pfsub (sz: fsize) (rd r1 r2: freg) (**r subtraction *)
+ | Pfmadd (sz: fsize) (rd r1 r2 r3: freg) (**r [rd = r3 + r1 * r2] *)
+ | Pfmsub (sz: fsize) (rd r1 r2 r3: freg) (**r [rd = r3 - r1 * r2] *)
+ | Pfnmadd (sz: fsize) (rd r1 r2 r3: freg) (**r [rd = - r3 - r1 * r2] *)
+ | Pfnmsub (sz: fsize) (rd r1 r2 r3: freg) (**r [rd = - r3 + r1 * r2] *)
+ (** Floating-point comparison *)
+ | Pfcmp (sz: fsize) (r1 r2: freg) (**r compare [r1] and [r2] *)
+ | Pfcmp0 (sz: fsize) (r1: freg) (**r compare [r1] and [+0.0] *)
+ (** Floating-point conditional select *)
+ | Pfsel (rd r1 r2: freg) (cond: testcond)
+ (** Pseudo-instructions *)
+ | Pallocframe (sz: Z) (linkofs: ptrofs) (**r allocate new stack frame *)
+ | Pfreeframe (sz: Z) (linkofs: ptrofs) (**r deallocate stack frame and restore previous frame *)
+ | Plabel (lbl: label) (**r define a code label *)
+ | Ploadsymbol (rd: ireg) (id: ident) (**r load the address of [id] *)
+ | Pcvtsw2x (rd: ireg) (r1: ireg) (**r sign-extend 32-bit int to 64-bit *)
+ | Pcvtuw2x (rd: ireg) (r1: ireg) (**r zero-extend 32-bit int to 64-bit *)
+ | Pcvtx2w (rd: ireg) (**r retype a 64-bit int as a 32-bit int *)
+ | Pbtbl (r1: ireg) (tbl: list label) (**r N-way branch through a jump table *)
+ | Pbuiltin (ef: external_function)
+ (args: list (builtin_arg preg)) (res: builtin_res preg) (**r built-in function (pseudo) *)
+ | Pnop (**r no operation *)
+ | Pcfi_adjust (ofs: int) (**r .cfi_adjust debug directive *)
+ | Pcfi_rel_offset (ofs: int) (**r .cfi_rel_offset debug directive *)
+.
+*)
+
+
+(** * Operational semantics *)
+
+(** See "Parameters" of the same names in Asm.v *)
+Record aarch64_linker: Type := {
+ symbol_low: ident -> ptrofs -> val;
+ symbol_high: ident -> ptrofs -> val
+}.
+
+Definition genv := Genv.t fundef unit.
+
+Section RELSEM.
+
+Variable lk: aarch64_linker.
+Variable ge: genv.
+
+(** Evaluating an addressing mode *)
+
+Definition eval_addressing (a: addressing) (rs: regset): val :=
+ match a with
+ | ADimm base n => Val.addl rs#base (Vlong n)
+ | ADreg base r => Val.addl rs#base rs#r
+ | ADlsl base r n => Val.addl rs#base (Val.shll rs#r (Vint n))
+ | ADsxt base r n => Val.addl rs#base (Val.shll (Val.longofint rs#r) (Vint n))
+ | ADuxt base r n => Val.addl rs#base (Val.shll (Val.longofintu rs#r) (Vint n))
+ | ADadr base id ofs => Val.addl rs#base (symbol_low lk id ofs)
+ | ADpostincr base n => Vundef (* not modeled yet *)
+ end.
+
+(** Auxiliaries for memory accesses *)
+
+Definition exec_load (chunk: memory_chunk) (transf: val -> val)
+ (a: addressing) (r: dreg) (rs: regset) (m: mem) :=
+ SOME v <- Mem.loadv chunk m (eval_addressing a rs) IN
+ Next (rs#r <- (transf v)) m.
+
+Definition exec_store (chunk: memory_chunk)
+ (a: addressing) (v: val)
+ (rs: regset) (m: mem) :=
+ SOME m' <- Mem.storev chunk m (eval_addressing a rs) v IN
+ Next rs m'.
+
+
+(** execution of loads
+*)
+
+Definition chunk_load_rd_a (ld: load_rd_a): memory_chunk :=
+ match ld with
+ | Pldrw => Mint32
+ | Pldrw_a => Many32
+ | Pldrx => Mint64
+ | Pldrx_a => Many64
+ | Pldrb _ => Mint8unsigned
+ | Pldrsb _ => Mint8signed
+ | Pldrh _ => Mint16unsigned
+ | Pldrsh _ => Mint16signed
+ | Pldrzw => Mint32
+ | Pldrsw => Mint32
+ | Pldrs => Mfloat32
+ | Pldrd => Mfloat64
+ | Pldrd_a => Many64
+ end.
+
+Definition chunk_store_rs_a (st: store_rs_a) : memory_chunk :=
+ match st with
+ | Pstrw => Mint32
+ | Pstrw_a => Many32
+ | Pstrx => Mint64
+ | Pstrx_a => Many64
+ | Pstrb => Mint8unsigned
+ | Pstrh => Mint16unsigned
+ | Pstrs => Mfloat32
+ | Pstrd => Mfloat64
+ | Pstrd_a => Many64
+ end.
+
+Definition interp_load_rd_a (ld: load_rd_a): val -> val :=
+ match ld with
+ | Pldrb X => Val.longofintu
+ | Pldrsb X => Val.longofint
+ | Pldrh X => Val.longofintu
+ | Pldrsh X => Val.longofint
+ | Pldrzw => Val.longofintu
+ | Pldrsw => Val.longofint
+ (* Changed to exhaustive list because I tend to forgot all the places I need
+ * to check when changing things. *)
+ | Pldrb W | Pldrsb W | Pldrh W | Pldrsh W
+ | Pldrw | Pldrw_a | Pldrx | Pldrx_a
+ | Pldrs | Pldrd | Pldrd_a => fun v => v
+ end.
+
+(** TODO: redundant w.r.t Machblock ?? *)
+Lemma in_dec (lbl: label) (l: list label): { List.In lbl l } + { ~(List.In lbl l) }.
+Proof.
+ apply List.in_dec.
+ apply Pos.eq_dec.
+Qed.
+
+(** Note: copy-paste from Machblock *)
+Definition is_label (lbl: label) (bb: bblock) : bool :=
+ if in_dec lbl (header bb) then true else false.
+
+Lemma is_label_correct_true lbl bb:
+ List.In lbl (header bb) <-> is_label lbl bb = true.
+Proof.
+ unfold is_label; destruct (in_dec lbl (header bb)); simpl; intuition.
+Qed.
+
+Lemma is_label_correct_false lbl bb:
+ ~(List.In lbl (header bb)) <-> is_label lbl bb = false.
+Proof.
+ unfold is_label; destruct (in_dec lbl (header bb)); simpl; intuition.
+Qed.
+
+(** convert a label into a position in the code *)
+Fixpoint label_pos (lbl: label) (pos: Z) (lb: bblocks) {struct lb} : option Z :=
+ match lb with
+ | nil => None
+ | b :: lb' => if is_label lbl b then Some pos else label_pos lbl (pos + (size b)) lb'
+ end.
+
+Definition goto_label (f: function) (lbl: label) (rs: regset) (m: mem) :=
+ SOME pos <- label_pos lbl 0 (fn_blocks f) IN
+ match rs#PC with
+ | Vptr b ofs => Next (rs#PC <- (Vptr b (Ptrofs.repr pos))) m
+ | _ => Stuck
+ end.
+
+(** Evaluating a branch
+
+Warning: PC is assumed to be already pointing on the next instruction !
+
+*)
+
+Definition eval_branch (f: function) (lbl: label) (rs: regset) (m: mem) (ores: option bool) :=
+ SOME res <- ores IN
+ if res then goto_label f lbl rs m else Next rs m.
+
+Definition eval_neg_branch (f: function) (lbl: label) (rs: regset) (m: mem) (ores: option bool) :=
+ SOME res <- ores IN
+ if res then Next rs m else goto_label f lbl rs m.
+
+Definition exec_cfi (f: function) (cfi: cf_instruction) (rs: regset) (m: mem) : outcome :=
+ match cfi with
+ (** Branches *)
+ | Pb lbl =>
+ goto_label f lbl rs m
+ | Pbc cond lbl =>
+ eval_branch f lbl rs m (eval_testcond cond rs)
+ | Pbl id sg =>
+ Next (rs#RA <- (rs#PC) #PC <- (Genv.symbol_address ge id Ptrofs.zero)) m
+ | Pbs id sg =>
+ Next (rs#PC <- (Genv.symbol_address ge id Ptrofs.zero)) m
+ | Pblr r sg =>
+ Next (rs#RA <- (rs#PC) #PC <- (rs#r)) m
+ | Pbr r sg =>
+ Next (rs#PC <- (rs#r)) m
+ | Pret r =>
+ Next (rs#PC <- (rs#r)) m
+ | Pcbnz sz r lbl =>
+ eval_neg_branch f lbl rs m (eval_testzero sz rs#r)
+ | Pcbz sz r lbl =>
+ eval_branch f lbl rs m (eval_testzero sz rs#r)
+ | Ptbnz sz r n lbl =>
+ eval_branch f lbl rs m (eval_testbit sz rs#r n)
+ | Ptbz sz r n lbl =>
+ eval_neg_branch f lbl rs m (eval_testbit sz rs#r n)
+ (** Pseudo-instructions *)
+ | Pbtbl r tbl =>
+ match (rs#X16 <- Vundef)#r with
+ | Vint n =>
+ SOME lbl <- list_nth_z tbl (Int.unsigned n) IN
+ goto_label f lbl (rs#X16 <- Vundef #X17 <- Vundef) m
+ | _ => Stuck
+ end
+ end.
+
+Definition arith_eval_p (i : arith_p) : val :=
+ match i with
+ | Padrp id ofs => symbol_high lk id ofs
+ (** Move wide immediate *)
+ | Pmovz W n pos => Vint (Int.repr (Z.shiftl n pos))
+ | Pmovz X n pos => Vlong (Int64.repr (Z.shiftl n pos))
+ | Pmovn W n pos => Vint (Int.repr (Z.lnot (Z.shiftl n pos)))
+ | Pmovn X n pos => Vlong (Int64.repr (Z.lnot (Z.shiftl n pos)))
+ (** Floating-point move *)
+ | Pfmovimms f => Vsingle f
+ | Pfmovimmd f => Vfloat f
+ end.
+
+Definition if_opt_bool_val (c: option bool) v1 v2: val :=
+ match c with
+ | Some true => v1
+ | Some false => v2
+ | None => Vundef
+ end.
+
+Definition arith_eval_pp i v :=
+ match i with
+ | Pmov => v
+ | Pmovk W n pos => insert_in_int v n pos 16
+ | Pmovk X n pos => insert_in_long v n pos 16
+ | Paddadr id ofs => Val.addl v (symbol_low lk id ofs)
+ | Psbfiz W r s => Val.shl (Val.sign_ext s v) (Vint r)
+ | Psbfiz X r s => Val.shll (Val.sign_ext_l s v) (Vint r)
+ | Psbfx W r s => Val.sign_ext s (Val.shr v (Vint r))
+ | Psbfx X r s => Val.sign_ext_l s (Val.shrl v (Vint r))
+ | Pubfiz W r s => Val.shl (Val.zero_ext s v) (Vint r)
+ | Pubfiz X r s => Val.shll (Val.zero_ext_l s v) (Vint r)
+ | Pubfx W r s => Val.zero_ext s (Val.shru v (Vint r))
+ | Pubfx X r s => Val.zero_ext_l s (Val.shrlu v (Vint r))
+ | Pfmov => v
+ | Pfcvtds => Val.floatofsingle v
+ | Pfcvtsd => Val.singleoffloat v
+ | Pfabs S => Val.absfs v
+ | Pfabs D => Val.absf v
+ | Pfneg S => Val.negfs v
+ | Pfneg D => Val.negf v
+ | Pfcvtzs W S => Val.maketotal (Val.intofsingle v)
+ | Pfcvtzs W D => Val.maketotal (Val.intoffloat v)
+ | Pfcvtzs X S => Val.maketotal (Val.longofsingle v)
+ | Pfcvtzs X D => Val.maketotal (Val.longoffloat v)
+ | Pfcvtzu W S => Val.maketotal (Val.intuofsingle v)
+ | Pfcvtzu W D => Val.maketotal (Val.intuoffloat v)
+ | Pfcvtzu X S => Val.maketotal (Val.longuofsingle v)
+ | Pfcvtzu X D => Val.maketotal (Val.longuoffloat v)
+ | Paddimm W n => Val.add v (Vint (Int.repr n))
+ | Paddimm X n => Val.addl v (Vlong (Int64.repr n))
+ | Psubimm W n => Val.sub v (Vint (Int.repr n))
+ | Psubimm X n => Val.subl v (Vlong (Int64.repr n))
+ | Pscvtf S W => Val.maketotal (Val.singleofint v)
+ | Pscvtf D W => Val.maketotal (Val.floatofint v)
+ | Pscvtf S X => Val.maketotal (Val.singleoflong v)
+ | Pscvtf D X => Val.maketotal (Val.floatoflong v)
+ | Pucvtf S W => Val.maketotal (Val.singleofintu v)
+ | Pucvtf D W => Val.maketotal (Val.floatofintu v)
+ | Pucvtf S X => Val.maketotal (Val.singleoflongu v)
+ | Pucvtf D X => Val.maketotal (Val.floatoflongu v)
+ end.
+
+Definition arith_eval_ppp i v1 v2 :=
+ match i with
+ | Pasrv W => Val.shr v1 v2
+ | Pasrv X => Val.shrl v1 v2
+ | Plslv W => Val.shl v1 v2
+ | Plslv X => Val.shll v1 v2
+ | Plsrv W => Val.shru v1 v2
+ | Plsrv X => Val.shrlu v1 v2
+ | Prorv W => Val.ror v1 v2
+ | Prorv X => Val.rorl v1 v2
+ | Psmulh => Val.mullhs v1 v2
+ | Pumulh => Val.mullhu v1 v2
+ | Psdiv W => Val.maketotal (Val.divs v1 v2)
+ | Psdiv X => Val.maketotal (Val.divls v1 v2)
+ | Pudiv W => Val.maketotal (Val.divu v1 v2)
+ | Pudiv X => Val.maketotal (Val.divlu v1 v2)
+ | Paddext x => Val.addl v1 (eval_extend v2 x)
+ | Psubext x => Val.subl v1 (eval_extend v2 x)
+ | Pfadd S => Val.addfs v1 v2
+ | Pfadd D => Val.addf v1 v2
+ | Pfdiv S => Val.divfs v1 v2
+ | Pfdiv D => Val.divf v1 v2
+ | Pfmul S => Val.mulfs v1 v2
+ | Pfmul D => Val.mulf v1 v2
+ | Pfsub S => Val.subfs v1 v2
+ | Pfsub D => Val.subf v1 v2
+ end.
+
+Definition arith_rr0r_isize (i: arith_rr0r) :=
+ match i with
+ | Padd is _ => is
+ | Psub is _ => is
+ | Pand is _ => is
+ | Pbic is _ => is
+ | Peon is _ => is
+ | Peor is _ => is
+ | Porr is _ => is
+ | Porn is _ => is
+ end.
+
+(* obtain v1 by [ir0 (arith_rr0r_isize i) rs s1] *)
+Definition arith_eval_rr0r i v1 v2 :=
+ match i with
+ | Padd W s => Val.add v1 (eval_shift_op_int v2 s)
+ | Padd X s => Val.addl v1 (eval_shift_op_long v2 s)
+ | Psub W s => Val.sub v1 (eval_shift_op_int v2 s)
+ | Psub X s => Val.subl v1 (eval_shift_op_long v2 s)
+ | Pand W s => Val.and v1 (eval_shift_op_int v2 s)
+ | Pand X s => Val.andl v1 (eval_shift_op_long v2 s)
+ | Pbic W s => Val.and v1 (Val.notint (eval_shift_op_int v2 s))
+ | Pbic X s => Val.andl v1 (Val.notl (eval_shift_op_long v2 s))
+ | Peon W s => Val.xor v1 (Val.notint (eval_shift_op_int v2 s))
+ | Peon X s => Val.xorl v1 (Val.notl (eval_shift_op_long v2 s))
+ | Peor W s => Val.xor v1 (eval_shift_op_int v2 s)
+ | Peor X s => Val.xorl v1 (eval_shift_op_long v2 s)
+ | Porr W s => Val.or v1 (eval_shift_op_int v2 s)
+ | Porr X s => Val.orl v1 (eval_shift_op_long v2 s)
+ | Porn W s => Val.or v1 (Val.notint (eval_shift_op_int v2 s))
+ | Porn X s => Val.orl v1 (Val.notl (eval_shift_op_long v2 s))
+ end.
+
+Definition arith_rr0_isize (i : arith_rr0) :=
+ match i with
+ | Pandimm is _ | Peorimm is _ | Porrimm is _ => is
+ end.
+
+(* obtain v by [ir0 (arith_rr0_isize i) rs s] *)
+Definition arith_eval_rr0 i v :=
+ match i with
+ | Pandimm W n => Val.and v (Vint (Int.repr n))
+ | Pandimm X n => Val.andl v (Vlong (Int64.repr n))
+ | Peorimm W n => Val.xor v (Vint (Int.repr n))
+ | Peorimm X n => Val.xorl v (Vlong (Int64.repr n))
+ | Porrimm W n => Val.or v (Vint (Int.repr n))
+ | Porrimm X n => Val.orl v (Vlong (Int64.repr n))
+ end.
+
+Definition arith_arrrr0_isize (i : arith_arrrr0) :=
+ match i with
+ | Pmadd is | Pmsub is => is
+ end.
+
+(* obtain v3 by [ir0 (arith_arrrr0_isize i) rs s3] *)
+Definition arith_eval_arrrr0 i v1 v2 v3 :=
+ match i with
+ | Pmadd W => Val.add v3 (Val.mul v1 v2)
+ | Pmadd X => Val.addl v3 (Val.mull v1 v2)
+ | Pmsub W => Val.sub v3 (Val.mul v1 v2)
+ | Pmsub X => Val.subl v3 (Val.mull v1 v2)
+ end.
+
+Definition arith_prepare_comparison_pp i (v1 v2 : val) :=
+ match i with
+ | Pcmpext x => (v1, (eval_extend v2 x))
+ | Pcmnext x => (v1, (Val.negl (eval_extend v2 x)))
+ | Pfcmp _ => (v1, v2)
+ end.
+
+Definition arith_comparison_r0r_isize i :=
+ match i with
+ | Pcmp is _ => is
+ | Pcmn is _ => is
+ | Ptst is _ => is
+ end.
+
+Definition arith_prepare_comparison_r0r i v1 v2 :=
+ match i with
+ | Pcmp W s => (v1, (eval_shift_op_int v2 s))
+ | Pcmp X s => (v1, (eval_shift_op_long v2 s))
+ | Pcmn W s => (v1, (Val.neg (eval_shift_op_int v2 s)))
+ | Pcmn X s => (v1, (Val.negl (eval_shift_op_long v2 s)))
+ | Ptst W s => ((Val.and v1 (eval_shift_op_int v2 s)), (Vint Int.zero))
+ | Ptst X s => ((Val.andl v1 (eval_shift_op_long v2 s)), (Vlong Int64.zero))
+ end.
+
+Definition arith_prepare_comparison_p i v :=
+ match i with
+ | Pcmpimm W n => (v, (Vint (Int.repr n)))
+ | Pcmpimm X n => (v, (Vlong (Int64.repr n)))
+ | Pcmnimm W n => (v, (Vint (Int.neg (Int.repr n))))
+ | Pcmnimm X n => (v, (Vlong (Int64.neg (Int64.repr n))))
+ | Ptstimm W n => ((Val.and v (Vint (Int.repr n))), (Vint Int.zero))
+ | Ptstimm X n => ((Val.andl v (Vlong (Int64.repr n))), (Vlong Int64.zero))
+ | Pfcmp0 S => (v, (Vsingle Float32.zero))
+ | Pfcmp0 D => (v, (Vfloat Float.zero))
+ end.
+
+Definition arith_comparison_pp_compare i :=
+ match i with
+ | Pcmpext _ | Pcmnext _ => compare_long
+ | Pfcmp S => compare_single
+ | Pfcmp D => compare_float
+ end.
+
+Definition arith_comparison_p_compare i :=
+ match i with
+ | Pcmpimm W _ | Pcmnimm W _ | Ptstimm W _ => compare_int
+ | Pcmpimm X _ | Pcmnimm X _ | Ptstimm X _ => compare_long
+ | Pfcmp0 S => compare_single
+ | Pfcmp0 D => compare_float
+ end.
+
+Definition exec_arith_instr (ai: ar_instruction) (rs: regset): regset :=
+ match ai with
+ | PArithP i d => rs#d <- (arith_eval_p i)
+ | PArithPP i d s => rs#d <- (arith_eval_pp i rs#s)
+ | PArithPPP i d s1 s2 => rs#d <- (arith_eval_ppp i rs#s1 rs#s2)
+
+ | PArithRR0R i d s1 s2 => rs#d <- (arith_eval_rr0r i (ir0 (arith_rr0r_isize i) rs s1) rs#s2)
+
+ | PArithRR0 i d s => rs#d <- (arith_eval_rr0 i (ir0 (arith_rr0_isize i) rs s))
+
+ | PArithARRRR0 i d s1 s2 s3 =>
+ rs#d <- (arith_eval_arrrr0 i rs#s1 rs#s2 (ir0 (arith_arrrr0_isize i) rs s3))
+
+ | PArithComparisonPP i s1 s2 =>
+ let (v1, v2) := arith_prepare_comparison_pp i rs#s1 rs#s2 in
+ arith_comparison_pp_compare i rs v1 v2
+ | PArithComparisonR0R i s1 s2 =>
+ let is := arith_comparison_r0r_isize i in
+ let (v1, v2) := arith_prepare_comparison_r0r i (ir0 is rs s1) rs#s2 in
+ (if is (* is W *) then compare_int else compare_long) rs v1 v2
+ | PArithComparisonP i s =>
+ let (v1, v2) := arith_prepare_comparison_p i rs#s in
+ arith_comparison_p_compare i rs v1 v2
+ | Pcset d c => rs#d <- (if_opt_bool_val (eval_testcond c rs) (Vint Int.one) (Vint Int.zero))
+ | Pfmovi S d s => rs#d <- (float32_of_bits rs##s)
+ | Pfmovi D d s => rs#d <- (float64_of_bits rs###s)
+ | Pcsel d s1 s2 c => rs#d <- (if_opt_bool_val (eval_testcond c rs) (rs#s1) (rs#s2))
+ | Pfnmul S d s1 s2 => rs#d <- (Val.negfs (Val.mulfs rs#s1 rs#s2))
+ | Pfnmul D d s1 s2 => rs#d <- (Val.negf (Val.mulf rs#s1 rs#s2))
+ end.
+
+(* basic exec *)
+Definition exec_basic (b: basic) (rs: regset) (m: mem): outcome :=
+ match b with
+ | PArith ai => Next (exec_arith_instr ai rs) m
+ | PLoad ld rd a => exec_load (chunk_load_rd_a ld) (interp_load_rd_a ld) a rd rs m
+ | PStore st r a => exec_store (chunk_store_rs_a st) a rs#r rs m
+ | Pallocframe sz pos =>
+ let (m1, stk) := Mem.alloc m 0 sz in
+ let sp := (Vptr stk Ptrofs.zero) in
+ SOME m2 <- Mem.storev Mint64 m1 (Val.offset_ptr sp pos) rs#SP IN
+ Next (rs #X29 <- (rs#SP) #SP <- sp #X16 <- Vundef) m2
+ | Pfreeframe sz pos =>
+ SOME v <- Mem.loadv Mint64 m (Val.offset_ptr rs#SP pos) IN
+ match rs#SP with
+ | Vptr stk ofs =>
+ SOME m' <- Mem.free m stk 0 sz IN
+ Next (rs#SP <- v #X16 <- Vundef) m'
+ | _ => Stuck
+ end
+ | Ploadsymbol rd id =>
+ Next (rs#rd <- (Genv.symbol_address ge id Ptrofs.zero)) m
+ | Pcvtsw2x rd r1 =>
+ Next (rs#rd <- (Val.longofint rs#r1)) m
+ | Pcvtuw2x rd r1 =>
+ Next (rs#rd <- (Val.longofintu rs#r1)) m
+ | Pcvtx2w rd =>
+ Next (rs#rd <- (Val.loword rs#rd)) m
+ end.
+
+(* TODO: ORIGINAL EXECUTION OF INSTRUCTIONS THAT NEEDS TO BE ADAPTED !
+
+(** Execution of a single instruction [i] in initial state
+ [rs] and [m]. Return updated state. For instructions
+ that correspond to actual AArch64 instructions, the cases are
+ straightforward transliterations of the informal descriptions
+ given in the ARMv8 reference manuals. For pseudo-instructions,
+ refer to the informal descriptions given above.
+
+ Note that we set to [Vundef] the registers used as temporaries by
+ the expansions of the pseudo-instructions, so that the code we
+ generate cannot use those registers to hold values that must
+ survive the execution of the pseudo-instruction.
+*)
+
+Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : outcome :=
+ match i with
+ (** Branches *)
+ | Pb lbl =>
+ goto_label f lbl rs m
+ | Pbc cond lbl =>
+ match eval_testcond cond rs with
+ | Some true => goto_label f lbl rs m
+ | Some false => Next (nextinstr rs) m
+ | None => Stuck
+ end
+ | Pbl id sg =>
+ Next (rs#RA <- (Val.offset_ptr rs#PC Ptrofs.one) #PC <- (Genv.symbol_address ge id Ptrofs.zero)) m
+ | Pbs id sg =>
+ Next (rs#PC <- (Genv.symbol_address ge id Ptrofs.zero)) m
+ | Pblr r sg =>
+ Next (rs#RA <- (Val.offset_ptr rs#PC Ptrofs.one) #PC <- (rs#r)) m
+ | Pbr r sg =>
+ Next (rs#PC <- (rs#r)) m
+ | Pret r =>
+ Next (rs#PC <- (rs#r)) m
+ | Pcbnz sz r lbl =>
+ match eval_testzero sz rs#r m with
+ | Some true => Next (nextinstr rs) m
+ | Some false => goto_label f lbl rs m
+ | None => Stuck
+ end
+ | Pcbz sz r lbl =>
+ match eval_testzero sz rs#r m with
+ | Some true => goto_label f lbl rs m
+ | Some false => Next (nextinstr rs) m
+ | None => Stuck
+ end
+ | Ptbnz sz r n lbl =>
+ match eval_testbit sz rs#r n with
+ | Some true => goto_label f lbl rs m
+ | Some false => Next (nextinstr rs) m
+ | None => Stuck
+ end
+ | Ptbz sz r n lbl =>
+ match eval_testbit sz rs#r n with
+ | Some true => Next (nextinstr rs) m
+ | Some false => goto_label f lbl rs m
+ | None => Stuck
+ end
+ (** Memory loads and stores *)
+ | Pldrw rd a =>
+ exec_load Mint32 (fun v => v) a rd rs m
+ | Pldrw_a rd a =>
+ exec_load Many32 (fun v => v) a rd rs m
+ | Pldrx rd a =>
+ exec_load Mint64 (fun v => v) a rd rs m
+ | Pldrx_a rd a =>
+ exec_load Many64 (fun v => v) a rd rs m
+ | Pldrb W rd a =>
+ exec_load Mint8unsigned (fun v => v) a rd rs m
+ | Pldrb X rd a =>
+ exec_load Mint8unsigned Val.longofintu a rd rs m
+ | Pldrsb W rd a =>
+ exec_load Mint8signed (fun v => v) a rd rs m
+ | Pldrsb X rd a =>
+ exec_load Mint8signed Val.longofint a rd rs m
+ | Pldrh W rd a =>
+ exec_load Mint16unsigned (fun v => v) a rd rs m
+ | Pldrh X rd a =>
+ exec_load Mint16unsigned Val.longofintu a rd rs m
+ | Pldrsh W rd a =>
+ exec_load Mint16signed (fun v => v) a rd rs m
+ | Pldrsh X rd a =>
+ exec_load Mint16signed Val.longofint a rd rs m
+ | Pldrzw rd a =>
+ exec_load Mint32 Val.longofintu a rd rs m
+ | Pldrsw rd a =>
+ exec_load Mint32 Val.longofint a rd rs m
+ | Pstrw r a =>
+ exec_store Mint32 a rs#r rs m
+ | Pstrw_a r a =>
+ exec_store Many32 a rs#r rs m
+ | Pstrx r a =>
+ exec_store Mint64 a rs#r rs m
+ | Pstrx_a r a =>
+ exec_store Many64 a rs#r rs m
+ | Pstrb r a =>
+ exec_store Mint8unsigned a rs#r rs m
+ | Pstrh r a =>
+ exec_store Mint16unsigned a rs#r rs m
+ (** Integer arithmetic, immediate *)
+ | Paddimm W rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.add rs#r1 (Vint (Int.repr n))))) m
+ | Paddimm X rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.addl rs#r1 (Vlong (Int64.repr n))))) m
+ | Psubimm W rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.sub rs#r1 (Vint (Int.repr n))))) m
+ | Psubimm X rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.subl rs#r1 (Vlong (Int64.repr n))))) m
+ | Pcmpimm W r1 n =>
+ Next (nextinstr (compare_int rs rs#r1 (Vint (Int.repr n)) m)) m
+ | Pcmpimm X r1 n =>
+ Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.repr n)) m)) m
+ | Pcmnimm W r1 n =>
+ Next (nextinstr (compare_int rs rs#r1 (Vint (Int.neg (Int.repr n))) m)) m
+ | Pcmnimm X r1 n =>
+ Next (nextinstr (compare_long rs rs#r1 (Vlong (Int64.neg (Int64.repr n))) m)) m
+ (** Move integer register *)
+ | Pmov rd r1 =>
+ Next (nextinstr (rs#rd <- (rs#r1))) m
+ (** Logical, immediate *)
+ | Pandimm W rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.and rs##r1 (Vint (Int.repr n))))) m
+ | Pandimm X rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.andl rs###r1 (Vlong (Int64.repr n))))) m
+ | Peorimm W rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.xor rs##r1 (Vint (Int.repr n))))) m
+ | Peorimm X rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.xorl rs###r1 (Vlong (Int64.repr n))))) m
+ | Porrimm W rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.or rs##r1 (Vint (Int.repr n))))) m
+ | Porrimm X rd r1 n =>
+ Next (nextinstr (rs#rd <- (Val.orl rs###r1 (Vlong (Int64.repr n))))) m
+ | Ptstimm W r1 n =>
+ Next (nextinstr (compare_int rs (Val.and rs#r1 (Vint (Int.repr n))) (Vint Int.zero) m)) m
+ | Ptstimm X r1 n =>
+ Next (nextinstr (compare_long rs (Val.andl rs#r1 (Vlong (Int64.repr n))) (Vlong Int64.zero) m)) m
+ (** Move wide immediate *)
+ | Pmovz W rd n pos =>
+ Next (nextinstr (rs#rd <- (Vint (Int.repr (Z.shiftl n pos))))) m
+ | Pmovz X rd n pos =>
+ Next (nextinstr (rs#rd <- (Vlong (Int64.repr (Z.shiftl n pos))))) m
+ | Pmovn W rd n pos =>
+ Next (nextinstr (rs#rd <- (Vint (Int.repr (Z.lnot (Z.shiftl n pos)))))) m
+ | Pmovn X rd n pos =>
+ Next (nextinstr (rs#rd <- (Vlong (Int64.repr (Z.lnot (Z.shiftl n pos)))))) m
+ | Pmovk W rd n pos =>
+ Next (nextinstr (rs#rd <- (insert_in_int rs#rd n pos 16))) m
+ | Pmovk X rd n pos =>
+ Next (nextinstr (rs#rd <- (insert_in_long rs#rd n pos 16))) m
+ (** PC-relative addressing *)
+ | Padrp rd id ofs =>
+ Next (nextinstr (rs#rd <- (symbol_high ge id ofs))) m
+ | Paddadr rd r1 id ofs =>
+ Next (nextinstr (rs#rd <- (Val.addl rs#r1 (symbol_low ge id ofs)))) m
+ (** Bit-field operations *)
+ | Psbfiz W rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.shl (Val.sign_ext s rs#r1) (Vint r)))) m
+ | Psbfiz X rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.shll (Val.sign_ext_l s rs#r1) (Vint r)))) m
+ | Psbfx W rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.sign_ext s (Val.shr rs#r1 (Vint r))))) m
+ | Psbfx X rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.sign_ext_l s (Val.shrl rs#r1 (Vint r))))) m
+ | Pubfiz W rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.shl (Val.zero_ext s rs#r1) (Vint r)))) m
+ | Pubfiz X rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.shll (Val.zero_ext_l s rs#r1) (Vint r)))) m
+ | Pubfx W rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.zero_ext s (Val.shru rs#r1 (Vint r))))) m
+ | Pubfx X rd r1 r s =>
+ Next (nextinstr (rs#rd <- (Val.zero_ext_l s (Val.shrlu rs#r1 (Vint r))))) m
+ (** Integer arithmetic, shifted register *)
+ | Padd W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.add rs##r1 (eval_shift_op_int rs#r2 s)))) m
+ | Padd X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.addl rs###r1 (eval_shift_op_long rs#r2 s)))) m
+ | Psub W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.sub rs##r1 (eval_shift_op_int rs#r2 s)))) m
+ | Psub X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.subl rs###r1 (eval_shift_op_long rs#r2 s)))) m
+ | Pcmp W r1 r2 s =>
+ Next (nextinstr (compare_int rs rs##r1 (eval_shift_op_int rs#r2 s) m)) m
+ | Pcmp X r1 r2 s =>
+ Next (nextinstr (compare_long rs rs###r1 (eval_shift_op_long rs#r2 s) m)) m
+ | Pcmn W r1 r2 s =>
+ Next (nextinstr (compare_int rs rs##r1 (Val.neg (eval_shift_op_int rs#r2 s)) m)) m
+ | Pcmn X r1 r2 s =>
+ Next (nextinstr (compare_long rs rs###r1 (Val.negl (eval_shift_op_long rs#r2 s)) m)) m
+ (** Integer arithmetic, extending register *)
+ | Paddext rd r1 r2 x =>
+ Next (nextinstr (rs#rd <- (Val.addl rs#r1 (eval_extend rs#r2 x)))) m
+ | Psubext rd r1 r2 x =>
+ Next (nextinstr (rs#rd <- (Val.subl rs#r1 (eval_extend rs#r2 x)))) m
+ | Pcmpext r1 r2 x =>
+ Next (nextinstr (compare_long rs rs#r1 (eval_extend rs#r2 x) m)) m
+ | Pcmnext r1 r2 x =>
+ Next (nextinstr (compare_long rs rs#r1 (Val.negl (eval_extend rs#r2 x)) m)) m
+ (** Logical, shifted register *)
+ | Pand W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.and rs##r1 (eval_shift_op_int rs#r2 s)))) m
+ | Pand X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.andl rs###r1 (eval_shift_op_long rs#r2 s)))) m
+ | Pbic W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.and rs##r1 (Val.notint (eval_shift_op_int rs#r2 s))))) m
+ | Pbic X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.andl rs###r1 (Val.notl (eval_shift_op_long rs#r2 s))))) m
+ | Peon W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.xor rs##r1 (Val.notint (eval_shift_op_int rs#r2 s))))) m
+ | Peon X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.xorl rs###r1 (Val.notl (eval_shift_op_long rs#r2 s))))) m
+ | Peor W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.xor rs##r1 (eval_shift_op_int rs#r2 s)))) m
+ | Peor X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.xorl rs###r1 (eval_shift_op_long rs#r2 s)))) m
+ | Porr W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.or rs##r1 (eval_shift_op_int rs#r2 s)))) m
+ | Porr X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.orl rs###r1 (eval_shift_op_long rs#r2 s)))) m
+ | Porn W rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.or rs##r1 (Val.notint (eval_shift_op_int rs#r2 s))))) m
+ | Porn X rd r1 r2 s =>
+ Next (nextinstr (rs#rd <- (Val.orl rs###r1 (Val.notl (eval_shift_op_long rs#r2 s))))) m
+ | Ptst W r1 r2 s =>
+ Next (nextinstr (compare_int rs (Val.and rs##r1 (eval_shift_op_int rs#r2 s)) (Vint Int.zero) m)) m
+ | Ptst X r1 r2 s =>
+ Next (nextinstr (compare_long rs (Val.andl rs###r1 (eval_shift_op_long rs#r2 s)) (Vlong Int64.zero) m)) m
+ (** Variable shifts *)
+ | Pasrv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shr rs#r1 rs#r2))) m
+ | Pasrv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shrl rs#r1 rs#r2))) m
+ | Plslv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shl rs#r1 rs#r2))) m
+ | Plslv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shll rs#r1 rs#r2))) m
+ | Plsrv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shru rs#r1 rs#r2))) m
+ | Plsrv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.shrlu rs#r1 rs#r2))) m
+ | Prorv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.ror rs#r1 rs#r2))) m
+ | Prorv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.rorl rs#r1 rs#r2))) m
+ (** Conditional data processing *)
+ | Pcsel rd r1 r2 cond =>
+ let v :=
+ match eval_testcond cond rs with
+ | Some true => rs#r1
+ | Some false => rs#r2
+ | None => Vundef
+ end in
+ Next (nextinstr (rs#rd <- v)) m
+ | Pcset rd cond =>
+ let v :=
+ match cond rs with
+ | Some true => Vint Int.one
+ | Some false => Vint Int.zero
+ | None => Vundef
+ end in
+ Next (nextinstr (rs#rd <- v)) m
+ (** Integer multiply/divide *)
+ | Pmadd W rd r1 r2 r3 =>
+ Next (nextinstr (rs#rd <- (Val.add rs##r3 (Val.mul rs#r1 rs#r2)))) m
+ | Pmadd X rd r1 r2 r3 =>
+ Next (nextinstr (rs#rd <- (Val.addl rs###r3 (Val.mull rs#r1 rs#r2)))) m
+ | Pmsub W rd r1 r2 r3 =>
+ Next (nextinstr (rs#rd <- (Val.sub rs##r3 (Val.mul rs#r1 rs#r2)))) m
+ | Pmsub X rd r1 r2 r3 =>
+ Next (nextinstr (rs#rd <- (Val.subl rs###r3 (Val.mull rs#r1 rs#r2)))) m
+ | Psmulh rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.mullhs rs#r1 rs#r2))) m
+ | Pumulh rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.mullhu rs#r1 rs#r2))) m
+ | Psdiv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.divs rs#r1 rs#r2)))) m
+ | Psdiv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.divls rs#r1 rs#r2)))) m
+ | Pudiv W rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.divu rs#r1 rs#r2)))) m
+ | Pudiv X rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.divlu rs#r1 rs#r2)))) m
+ (** Floating-point loads and stores *)
+ | Pldrs rd a =>
+ exec_load Mfloat32 (fun v => v) a rd rs m
+ | Pldrd rd a =>
+ exec_load Mfloat64 (fun v => v) a rd rs m
+ | Pldrd_a rd a =>
+ exec_load Many64 (fun v => v) a rd rs m
+ | Pstrs r a =>
+ exec_store Mfloat32 a rs#r rs m
+ | Pstrd r a =>
+ exec_store Mfloat64 a rs#r rs m
+ | Pstrd_a r a =>
+ exec_store Many64 a rs#r rs m
+ (** Floating-point move *)
+ | Pfmov rd r1 =>
+ Next (nextinstr (rs#rd <- (rs#r1))) m
+ | Pfmovimms rd f =>
+ Next (nextinstr (rs#rd <- (Vsingle f))) m
+ | Pfmovimmd rd f =>
+ Next (nextinstr (rs#rd <- (Vfloat f))) m
+ | Pfmovi S rd r1 =>
+ Next (nextinstr (rs#rd <- (float32_of_bits rs##r1))) m
+ | Pfmovi D rd r1 =>
+ Next (nextinstr (rs#rd <- (float64_of_bits rs###r1))) m
+ (** Floating-point conversions *)
+ | Pfcvtds rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.floatofsingle rs#r1))) m
+ | Pfcvtsd rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.singleoffloat rs#r1))) m
+ | Pfcvtzs W S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.intofsingle rs#r1)))) m
+ | Pfcvtzs W D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.intoffloat rs#r1)))) m
+ | Pfcvtzs X S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.longofsingle rs#r1)))) m
+ | Pfcvtzs X D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.longoffloat rs#r1)))) m
+ | Pfcvtzu W S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.intuofsingle rs#r1)))) m
+ | Pfcvtzu W D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.intuoffloat rs#r1)))) m
+ | Pfcvtzu X S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.longuofsingle rs#r1)))) m
+ | Pfcvtzu X D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.longuoffloat rs#r1)))) m
+ | Pscvtf S W rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.singleofint rs#r1)))) m
+ | Pscvtf D W rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.floatofint rs#r1)))) m
+ | Pscvtf S X rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.singleoflong rs#r1)))) m
+ | Pscvtf D X rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.floatoflong rs#r1)))) m
+ | Pucvtf S W rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.singleofintu rs#r1)))) m
+ | Pucvtf D W rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.floatofintu rs#r1)))) m
+ | Pucvtf S X rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.singleoflongu rs#r1)))) m
+ | Pucvtf D X rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.maketotal (Val.floatoflongu rs#r1)))) m
+ (** Floating-point arithmetic *)
+ | Pfabs S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.absfs rs#r1))) m
+ | Pfabs D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.absf rs#r1))) m
+ | Pfneg S rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.negfs rs#r1))) m
+ | Pfneg D rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.negf rs#r1))) m
+ | Pfadd S rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.addfs rs#r1 rs#r2))) m
+ | Pfadd D rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.addf rs#r1 rs#r2))) m
+ | Pfdiv S rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.divfs rs#r1 rs#r2))) m
+ | Pfdiv D rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.divf rs#r1 rs#r2))) m
+ | Pfmul S rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.mulfs rs#r1 rs#r2))) m
+ | Pfmul D rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.mulf rs#r1 rs#r2))) m
+ | Pfnmul S rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.negfs (Val.mulfs rs#r1 rs#r2)))) m
+ | Pfnmul D rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.negf (Val.mulf rs#r1 rs#r2)))) m
+ | Pfsub S rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.subfs rs#r1 rs#r2))) m
+ | Pfsub D rd r1 r2 =>
+ Next (nextinstr (rs#rd <- (Val.subf rs#r1 rs#r2))) m
+ (** Floating-point comparison *)
+ | Pfcmp S r1 r2 =>
+ Next (nextinstr (compare_single rs rs#r1 rs#r2)) m
+ | Pfcmp D r1 r2 =>
+ Next (nextinstr (compare_float rs rs#r1 rs#r2)) m
+ | Pfcmp0 S r1 =>
+ Next (nextinstr (compare_single rs rs#r1 (Vsingle Float32.zero))) m
+ | Pfcmp0 D r1 =>
+ Next (nextinstr (compare_float rs rs#r1 (Vfloat Float.zero))) m
+ (** Floating-point conditional select *)
+ | Pfsel rd r1 r2 cond =>
+ let v :=
+ match eval_testcond cond rs with
+ | Some true => rs#r1
+ | Some false => rs#r2
+ | None => Vundef
+ end in
+ Next (nextinstr (rs#rd <- v)) m
+ (** Pseudo-instructions *)
+ | Pallocframe sz pos =>
+ let (m1, stk) := Mem.alloc m 0 sz in
+ let sp := (Vptr stk Ptrofs.zero) in
+ match Mem.storev Mint64 m1 (Val.offset_ptr sp pos) rs#SP with
+ | None => Stuck
+ | Some m2 => Next (nextinstr (rs #X29 <- (rs#SP) #SP <- sp #X16 <- Vundef)) m2
+ end
+ | Pfreeframe sz pos =>
+ match Mem.loadv Mint64 m (Val.offset_ptr rs#SP pos) with
+ | None => Stuck
+ | Some v =>
+ match rs#SP with
+ | Vptr stk ofs =>
+ match Mem.free m stk 0 sz with
+ | None => Stuck
+ | Some m' => Next (nextinstr (rs#SP <- v #X16 <- Vundef)) m'
+ end
+ | _ => Stuck
+ end
+ end
+ | Plabel lbl =>
+ Next (nextinstr rs) m
+ | Ploadsymbol rd id =>
+ Next (nextinstr (rs#rd <- (Genv.symbol_address ge id Ptrofs.zero))) m
+ | Pcvtsw2x rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.longofint rs#r1))) m
+ | Pcvtuw2x rd r1 =>
+ Next (nextinstr (rs#rd <- (Val.longofintu rs#r1))) m
+ | Pcvtx2w rd =>
+ Next (nextinstr (rs#rd <- (Val.loword rs#rd))) m
+ | Pbtbl r tbl =>
+ match (rs#X16 <- Vundef)#r with
+ | Vint n =>
+ match list_nth_z tbl (Int.unsigned n) with
+ | None => Stuck
+ | Some lbl => goto_label f lbl (rs#X16 <- Vundef #X17 <- Vundef) m
+ end
+ | _ => Stuck
+ end
+ | Pbuiltin ef args res => Stuck (**r treated specially below *)
+ (** The following instructions and directives are not generated directly
+ by Asmgen, so we do not model them. *)
+ | Pldp _ _ _
+ | Pstp _ _ _
+ | Pcls _ _ _
+ | Pclz _ _ _
+ | Prev _ _ _
+ | Prev16 _ _ _
+ | Pfsqrt _ _ _
+ | Pfmadd _ _ _ _ _
+ | Pfmsub _ _ _ _ _
+ | Pfnmadd _ _ _ _ _
+ | Pfnmsub _ _ _ _ _
+ | Pnop
+ | Pcfi_adjust _
+ | Pcfi_rel_offset _ =>
+ Stuck
+ end.
+*)
+
+(** execution of the body of a bblock *)
+Fixpoint exec_body (body: list basic) (rs: regset) (m: mem): outcome :=
+ match body with
+ | nil => Next rs m
+ | bi::body' =>
+ SOME o <- exec_basic bi rs m IN
+ exec_body body' (_rs o) (_m o)
+ end.
+
+Definition incrPC size_b (rs: regset) :=
+ rs#PC <- (Val.offset_ptr rs#PC size_b).
+
+Definition estep (f: function) cfi size_b (rs: regset) (m: mem) :=
+ exec_cfi f cfi (incrPC size_b rs) m.
+
+(** execution of the exit instruction of a bblock *)
+Inductive exec_exit (f: function) size_b (rs: regset) (m: mem): (option control) -> trace -> regset -> mem -> Prop :=
+ | none_step:
+ exec_exit f size_b rs m None E0 (incrPC size_b rs) m
+ | cfi_step (cfi: cf_instruction) rs' m':
+ exec_cfi f cfi (incrPC size_b rs) m = Next rs' m' ->
+ exec_exit f size_b rs m (Some (PCtlFlow cfi)) E0 rs' m'
+ | builtin_step ef args res vargs t vres rs' m':
+ eval_builtin_args ge (fun (r: dreg) => rs r) rs#SP m args vargs ->
+ external_call ef ge vargs m t vres m' ->
+ rs' = incrPC size_b
+ (set_res (map_builtin_res DR res) vres
+ (undef_regs (map preg_of (destroyed_by_builtin ef)) rs)) ->
+ exec_exit f size_b rs m (Some (Pbuiltin ef args res)) t rs' m'
+ .
+
+Definition bbstep f cfi size_b bdy rs m :=
+ match exec_body bdy rs m with
+ | Some (State rs' m') => estep f cfi size_b rs' m'
+ | Stuck => Stuck
+ end.
+
+Definition exec_bblock (f: function) (b: bblock) (rs: regset) (m: mem) (t:trace) (rs':regset) (m':mem): Prop
+ := exists rs1 m1, exec_body (body b) rs m = Next rs1 m1 /\ exec_exit f (Ptrofs.repr (size b)) rs1 m1 (exit b) t rs' m'.
+
+Fixpoint find_bblock (pos: Z) (lb: bblocks) {struct lb} : option bblock :=
+ match lb with
+ | nil => None
+ | b :: il =>
+ if zlt pos 0 then None (* NOTE: It is impossible to branch inside a block *)
+ else if zeq pos 0 then Some b
+ else find_bblock (pos - (size b)) il
+ end.
+
+(** Execution of the instruction at [rs PC]. *)
+
+Inductive step: state -> trace -> state -> Prop :=
+ | exec_step_internal:
+ forall b ofs f bi rs m t rs' m',
+ rs PC = Vptr b ofs ->
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bi ->
+ exec_bblock f bi rs m t rs' m' ->
+ step (State rs m) t (State rs' m')
+ | exec_step_external:
+ forall b ef args res rs m t rs' m',
+ rs PC = Vptr b Ptrofs.zero ->
+ Genv.find_funct_ptr ge b = Some (External ef) ->
+ external_call ef ge args m t res m' ->
+ extcall_arguments rs m (ef_sig ef) args ->
+ rs' = (set_pair (loc_external_result (ef_sig ef) ) res (undef_caller_save_regs rs))#PC <- (rs RA) ->
+ step (State rs m) t (State rs' m')
+ .
+
+
+End RELSEM.
+
+
+(** Execution of whole programs. *)
+
+Inductive initial_state (p: program): state -> Prop :=
+ | initial_state_intro: forall m0,
+ Genv.init_mem p = Some m0 ->
+ let ge := Genv.globalenv p in
+ let rs0 :=
+ (Pregmap.init Vundef)
+ # PC <- (Genv.symbol_address ge p.(prog_main) Ptrofs.zero)
+ # RA <- Vnullptr
+ # SP <- Vnullptr in
+ initial_state p (State rs0 m0).
+
+Inductive final_state: state -> int -> Prop :=
+ | final_state_intro: forall rs m r,
+ rs#PC = Vnullptr ->
+ rs#X0 = Vint r ->
+ final_state (State rs m) r.
+
+Definition semantics (lk: aarch64_linker) (p: program) :=
+ Semantics (step lk) (initial_state p) final_state (Genv.globalenv p).
diff --git a/aarch64/Asmblockdeps.v b/aarch64/Asmblockdeps.v
new file mode 100644
index 00000000..bd460209
--- /dev/null
+++ b/aarch64/Asmblockdeps.v
@@ -0,0 +1,2754 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(** * Translation from [Asmvliw] to [AbstractBB] *)
+
+(** We define a specific instance [L] of [AbstractBB] and translate [bblocks] from [Asmvliw] into [L].
+ [AbstractBB] will then define two semantics for [L]: a sequential and a parallel one.
+ We prove a bisimulation between the parallel semantics of [L] and [AsmVLIW].
+ We also prove a bisimulation between the sequential semantics of [L] and [Asmblock].
+ Then, the checkers on [Asmblock] and [Asmvliw] are deduced from those of [L].
+ *)
+
+Require Import AST.
+Require Import Asm Asmblock.
+Require Import Asmblockgenproof0 Asmblockprops.
+Require Import Values.
+Require Import Globalenvs.
+Require Import Memory.
+Require Import Errors.
+Require Import Integers.
+Require Import Floats.
+Require Import ZArith.
+Require Import Coqlib.
+Require Import ImpSimuTest.
+Require Import Axioms.
+Require Import Permutation.
+Require Import Events.
+
+Require Import Lia.
+
+Open Scope impure.
+
+(** auxiliary treatments of builtins *)
+
+Definition has_builtin(bb: bblock): bool :=
+ match exit bb with
+ | Some (Pbuiltin _ _ _) => true
+ | _ => false
+ end.
+
+Remark builtin_arg_eq_dreg: forall (a b: builtin_arg dreg), {a=b} + {a<>b}.
+Proof.
+ intros.
+ apply (builtin_arg_eq dreg_eq).
+Qed.
+
+Remark builtin_res_eq_dreg: forall (a b: builtin_res dreg), {a=b} + {a<>b}.
+Proof.
+ intros.
+ apply (builtin_res_eq dreg_eq).
+Qed.
+
+Definition assert_same_builtin (bb1 bb2: bblock): ?? unit :=
+ match exit bb1 with
+ | Some (Pbuiltin ef1 lbar1 brr1) =>
+ match exit bb2 with
+ | Some (Pbuiltin ef2 lbar2 brr2) =>
+ if (external_function_eq ef1 ef2) then
+ if (list_eq_dec builtin_arg_eq_dreg lbar1 lbar2) then
+ if (builtin_res_eq_dreg brr1 brr2) then RET tt
+ else FAILWITH "Different brr in Pbuiltin"
+ else FAILWITH "Different lbar in Pbuiltin"
+ else FAILWITH "Different ef in Pbuiltin"
+ | _ => FAILWITH "Expected a builtin: found something else" (* XXX: on peut raffiner le message d'erreur si nécessaire *)
+ end
+ | _ => RET tt (* ok *)
+ end.
+
+Lemma assert_same_builtin_correct (bb1 bb2: bblock):
+ WHEN assert_same_builtin bb1 bb2 ~> _ THEN
+ has_builtin bb1 = true -> exit bb1 = exit bb2.
+Proof.
+ unfold assert_same_builtin, has_builtin.
+ destruct (exit bb1) as [[]|]; simpl; try (wlp_simplify; congruence).
+ destruct (exit bb2) as [[]|]; wlp_simplify.
+Qed.
+Global Opaque assert_same_builtin.
+Local Hint Resolve assert_same_builtin_correct: wlp.
+
+(** Definition of [L] *)
+
+Module P<: ImpParam.
+Module R := Pos.
+
+Section IMPPARAM.
+
+Definition env := Genv.t fundef unit.
+
+Record genv_wrap := { _genv: env; _fn: function; _lk: aarch64_linker }.
+Definition genv := genv_wrap.
+
+Variable Ge: genv.
+
+Inductive value_wrap :=
+ | Val (v: val)
+ | Memstate (m: mem)
+ | Bool (b: bool)
+.
+
+Definition value := value_wrap.
+
+Record CRflags := { _CN: val; _CZ:val; _CC: val; _CV: val }.
+
+Inductive control_op :=
+ (*| Oj_l (l: label)*)
+ | Ob (l: label)
+ | Obc (c: testcond) (l: label)
+ | Obl (id: ident)
+ | Obs (id: ident)
+ | Ocbnz (sz: isize) (l: label)
+ | Ocbz (sz: isize) (l: label)
+ | Otbnz (sz: isize) (n: int) (l: label)
+ | Otbz (sz: isize) (n: int) (l: label)
+ | Obtbl (l: list label)
+ | OError
+ | OIncremPC (sz: Z)
+.
+
+Inductive arith_op :=
+ | OArithP (n: arith_p)
+ | OArithPP (n: arith_pp)
+ | OArithPPP (n: arith_ppp)
+ | OArithRR0R (n: arith_rr0r)
+ | OArithRR0R_XZR (n: arith_rr0r) (vz: val)
+ | OArithRR0 (n: arith_rr0)
+ | OArithRR0_XZR (n: arith_rr0) (vz: val)
+ | OArithARRRR0 (n: arith_arrrr0)
+ | OArithARRRR0_XZR (n: arith_arrrr0) (vz: val)
+ | OArithComparisonPP_CN (n: arith_comparison_pp)
+ | OArithComparisonPP_CZ (n: arith_comparison_pp)
+ | OArithComparisonPP_CC (n: arith_comparison_pp)
+ | OArithComparisonPP_CV (n: arith_comparison_pp)
+ | OArithComparisonR0R_CN (n: arith_comparison_r0r) (is: isize)
+ | OArithComparisonR0R_CZ (n: arith_comparison_r0r) (is: isize)
+ | OArithComparisonR0R_CC (n: arith_comparison_r0r) (is: isize)
+ | OArithComparisonR0R_CV (n: arith_comparison_r0r) (is: isize)
+ | OArithComparisonR0R_CN_XZR (n: arith_comparison_r0r) (is: isize) (vz: val)
+ | OArithComparisonR0R_CZ_XZR (n: arith_comparison_r0r) (is: isize) (vz: val)
+ | OArithComparisonR0R_CC_XZR (n: arith_comparison_r0r) (is: isize) (vz: val)
+ | OArithComparisonR0R_CV_XZR (n: arith_comparison_r0r) (is: isize) (vz: val)
+ | OArithComparisonP_CN (n: arith_comparison_p)
+ | OArithComparisonP_CZ (n: arith_comparison_p)
+ | OArithComparisonP_CC (n: arith_comparison_p)
+ | OArithComparisonP_CV (n: arith_comparison_p)
+ | Ocset (c: testcond)
+ | Ofmovi (fsz: fsize)
+ | Ofmovi_XZR (fsz: fsize)
+ | Ocsel (c: testcond)
+ | Ofnmul (fsz: fsize)
+.
+
+Inductive store_op :=
+ | Ostore1 (st: store_rs_a) (a: addressing)
+ | Ostore2 (st: store_rs_a) (a: addressing)
+ | OstoreU (st: store_rs_a) (a: addressing)
+.
+
+Inductive load_op :=
+ | Oload1 (ld: load_rd_a) (a: addressing)
+ | Oload2 (ld: load_rd_a) (a: addressing)
+ | OloadU (ld: load_rd_a) (a: addressing)
+.
+
+Inductive allocf_op :=
+ | OAllocf_SP (sz: Z) (linkofs: ptrofs)
+ | OAllocf_Mem (sz: Z) (linkofs: ptrofs)
+.
+
+Inductive freef_op :=
+ | OFreef_SP (sz: Z) (linkofs: ptrofs)
+ | OFreef_Mem (sz: Z) (linkofs: ptrofs)
+.
+
+Inductive op_wrap :=
+ (* arithmetic operation *)
+ | Arith (op: arith_op)
+ | Load (ld: load_op)
+ | Store (st: store_op)
+ | Allocframe (al: allocf_op)
+ | Freeframe (fr: freef_op)
+ | Loadsymbol (id: ident)
+ | Cvtsw2x
+ | Cvtuw2x
+ | Cvtx2w
+ | Control (co: control_op)
+ | Constant (v: val)
+.
+
+Definition op:=op_wrap.
+
+Coercion Arith: arith_op >-> op_wrap.
+
+Definition v_compare_int (v1 v2: val) : CRflags :=
+ {| _CN := (Val.negative (Val.sub v1 v2));
+ _CZ := (Val_cmpu Ceq v1 v2);
+ _CC := (Val_cmpu Cge v1 v2);
+ _CV := (Val.sub_overflow v1 v2) |}.
+
+Definition v_compare_long (v1 v2: val) : CRflags :=
+ {| _CN := (Val.negativel (Val.subl v1 v2));
+ _CZ := (Val_cmplu Ceq v1 v2);
+ _CC := (Val_cmplu Cge v1 v2);
+ _CV := (Val.subl_overflow v1 v2) |}.
+
+Definition v_compare_float (v1 v2: val) : CRflags :=
+ match v1, v2 with
+ | Vfloat f1, Vfloat f2 =>
+ {| _CN := (Val.of_bool (Float.cmp Clt f1 f2));
+ _CZ := (Val.of_bool (Float.cmp Ceq f1 f2));
+ _CC := (Val.of_bool (negb (Float.cmp Clt f1 f2)));
+ _CV := (Val.of_bool (negb (Float.ordered f1 f2))) |}
+ | _, _ =>
+ {| _CN := Vundef;
+ _CZ := Vundef;
+ _CC := Vundef;
+ _CV := Vundef |}
+ end.
+
+Definition v_compare_single (v1 v2: val) : CRflags :=
+ match v1, v2 with
+ | Vsingle f1, Vsingle f2 =>
+ {| _CN := (Val.of_bool (Float32.cmp Clt f1 f2));
+ _CZ := (Val.of_bool (Float32.cmp Ceq f1 f2));
+ _CC := (Val.of_bool (negb (Float32.cmp Clt f1 f2)));
+ _CV := (Val.of_bool (negb (Float32.ordered f1 f2))) |}
+ | _, _ =>
+ {| _CN := Vundef;
+ _CZ := Vundef;
+ _CC := Vundef;
+ _CV := Vundef |}
+ end.
+
+Definition arith_eval_comparison_pp (n: arith_comparison_pp) (v1 v2: val) :=
+ let (v1',v2') := arith_prepare_comparison_pp n v1 v2 in
+ match n with
+ | Pcmpext _ | Pcmnext _ => v_compare_long v1' v2'
+ | Pfcmp S => v_compare_single v1' v2'
+ | Pfcmp D => v_compare_float v1' v2'
+ end.
+
+Definition arith_eval_comparison_p (n: arith_comparison_p) (v: val) :=
+ let (v1',v2') := arith_prepare_comparison_p n v in
+ match n with
+ | Pcmpimm W _ | Pcmnimm W _ | Ptstimm W _ => v_compare_int v1' v2'
+ | Pcmpimm X _ | Pcmnimm X _ | Ptstimm X _ => v_compare_long v1' v2'
+ | Pfcmp0 S => v_compare_single v1' v2'
+ | Pfcmp0 D => v_compare_float v1' v2'
+ end.
+
+Definition arith_eval_comparison_r0r (n: arith_comparison_r0r) (v1 v2: val) (is: isize) :=
+ let (v1',v2') := arith_prepare_comparison_r0r n v1 v2 in
+ if is then v_compare_int v1' v2' else v_compare_long v1' v2'.
+
+Definition flags_testcond_value (c: testcond) (vCN vCZ vCC vCV: val) :=
+ match c with
+ | TCeq => (**r equal *)
+ match vCZ with
+ | Vint n => Some (Int.eq n Int.one)
+ | _ => None
+ end
+ | TCne => (**r not equal *)
+ match vCZ with
+ | Vint n => Some (Int.eq n Int.zero)
+ | _ => None
+ end
+ | TClo => (**r unsigned less than *)
+ match vCC with
+ | Vint n => Some (Int.eq n Int.zero)
+ | _ => None
+ end
+ | TCls => (**r unsigned less or equal *)
+ match vCC, vCZ with
+ | Vint c, Vint z => Some (Int.eq c Int.zero || Int.eq z Int.one)
+ | _, _ => None
+ end
+ | TChs => (**r unsigned greater or equal *)
+ match vCC with
+ | Vint n => Some (Int.eq n Int.one)
+ | _ => None
+ end
+ | TChi => (**r unsigned greater *)
+ match vCC, vCZ with
+ | Vint c, Vint z => Some (Int.eq c Int.one && Int.eq z Int.zero)
+ | _, _ => None
+ end
+ | TClt => (**r signed less than *)
+ match vCV, vCN with
+ | Vint o, Vint s => Some (Int.eq (Int.xor o s) Int.one)
+ | _, _ => None
+ end
+ | TCle => (**r signed less or equal *)
+ match vCV, vCN, vCZ with
+ | Vint o, Vint s, Vint z => Some (Int.eq (Int.xor o s) Int.one || Int.eq z Int.one)
+ | _, _, _ => None
+ end
+ | TCge => (**r signed greater or equal *)
+ match vCV, vCN with
+ | Vint o, Vint s => Some (Int.eq (Int.xor o s) Int.zero)
+ | _, _ => None
+ end
+ | TCgt => (**r signed greater *)
+ match vCV, vCN, vCZ with
+ | Vint o, Vint s, Vint z => Some (Int.eq (Int.xor o s) Int.zero && Int.eq z Int.zero)
+ | _, _, _ => None
+ end
+ | TCpl => (**r positive *)
+ match vCN with
+ | Vint n => Some (Int.eq n Int.zero)
+ | _ => None
+ end
+ | TCmi => (**r negative *)
+ match vCN with
+ | Vint n => Some (Int.eq n Int.one)
+ | _ => None
+ end
+ end.
+
+Definition cond_eval_is (c: testcond) (v1 v2 vCN vCZ vCC vCV: val) (is: Z) :=
+ let res := flags_testcond_value c vCN vCZ vCC vCV in
+ match is, res with
+ | 0, res => Some (Val (if_opt_bool_val res (Vint Int.one) (Vint Int.zero)))
+ | 1, res => Some (Val (if_opt_bool_val res v1 v2))
+ | 2, Some b => Some (Bool (b))
+ | _, _ => None
+ end.
+
+Definition fmovi_eval (fsz: fsize) (v: val) :=
+ match fsz with
+ | S => float32_of_bits v
+ | D => float64_of_bits v
+ end.
+
+Definition fmovi_eval_xzr (fsz: fsize) :=
+ match fsz with
+ | S => float32_of_bits (Vint Int.zero)
+ | D => float64_of_bits (Vlong Int64.zero)
+ end.
+
+Definition fnmul_eval (fsz: fsize) (v1 v2: val) :=
+ match fsz with
+ | S => Val.negfs (Val.mulfs v1 v2)
+ | D => Val.negf (Val.mulf v1 v2)
+ end.
+
+Definition cflags_eval (c: testcond) (l: list value) (v1 v2: val) (is: Z) :=
+
+ match c, l with
+ | TCeq, [Val vCZ] => cond_eval_is TCeq v1 v2 Vundef vCZ Vundef Vundef is
+ | TCne, [Val vCZ] => cond_eval_is TCne v1 v2 Vundef vCZ Vundef Vundef is
+ | TChs, [Val vCC] => cond_eval_is TChs v1 v2 Vundef Vundef vCC Vundef is
+ | TClo, [Val vCC] => cond_eval_is TClo v1 v2 Vundef Vundef vCC Vundef is
+ | TCmi, [Val vCN] => cond_eval_is TCmi v1 v2 vCN Vundef Vundef Vundef is
+ | TCpl, [Val vCN] => cond_eval_is TCpl v1 v2 vCN Vundef Vundef Vundef is
+ | TChi, [Val vCZ; Val vCC] => cond_eval_is TChi v1 v2 Vundef vCZ vCC Vundef is
+ | TCls, [Val vCZ; Val vCC] => cond_eval_is TCls v1 v2 Vundef vCZ vCC Vundef is
+ | TCge, [Val vCN; Val vCV] => cond_eval_is TCge v1 v2 vCN Vundef Vundef vCV is
+ | TClt, [Val vCN; Val vCV] => cond_eval_is TClt v1 v2 vCN Vundef Vundef vCV is
+ | TCgt, [Val vCN; Val vCZ; Val vCV] => cond_eval_is TCgt v1 v2 vCN vCZ Vundef vCV is
+ | TCle, [Val vCN; Val vCZ; Val vCV] => cond_eval_is TCle v1 v2 vCN vCZ Vundef vCV is
+ | _, _ => None
+ end.
+
+Definition arith_op_eval (op: arith_op) (l: list value) :=
+ match op, l with
+ | OArithP n, [] => Some (Val (arith_eval_p Ge.(_lk) n))
+ | OArithPP n, [Val v] => Some (Val (arith_eval_pp Ge.(_lk) n v))
+ | OArithPPP n, [Val v1; Val v2] => Some (Val (arith_eval_ppp n v1 v2))
+ | OArithRR0R n, [Val v1; Val v2] => Some (Val (arith_eval_rr0r n v1 v2))
+ | OArithRR0R_XZR n vz, [Val v] => Some (Val (arith_eval_rr0r n vz v))
+ | OArithRR0 n, [Val v] => Some (Val (arith_eval_rr0 n v))
+ | OArithRR0_XZR n vz, [] => Some (Val (arith_eval_rr0 n vz))
+ | OArithARRRR0 n, [Val v1; Val v2; Val v3] => Some (Val (arith_eval_arrrr0 n v1 v2 v3))
+ | OArithARRRR0_XZR n vz, [Val v1; Val v2] => Some (Val (arith_eval_arrrr0 n v1 v2 vz))
+ | OArithComparisonPP_CN n, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_pp n v1 v2).(_CN)))
+ | OArithComparisonPP_CZ n, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_pp n v1 v2).(_CZ)))
+ | OArithComparisonPP_CC n, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_pp n v1 v2).(_CC)))
+ | OArithComparisonPP_CV n, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_pp n v1 v2).(_CV)))
+ | OArithComparisonR0R_CN n is, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_r0r n v1 v2 is).(_CN)))
+ | OArithComparisonR0R_CZ n is, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_r0r n v1 v2 is).(_CZ)))
+ | OArithComparisonR0R_CC n is, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_r0r n v1 v2 is).(_CC)))
+ | OArithComparisonR0R_CV n is, [Val v1; Val v2] => Some (Val ((arith_eval_comparison_r0r n v1 v2 is).(_CV)))
+ | OArithComparisonR0R_CN_XZR n is vz, [Val v2] => Some (Val ((arith_eval_comparison_r0r n vz v2 is).(_CN)))
+ | OArithComparisonR0R_CZ_XZR n is vz, [Val v2] => Some (Val ((arith_eval_comparison_r0r n vz v2 is).(_CZ)))
+ | OArithComparisonR0R_CC_XZR n is vz, [Val v2] => Some (Val ((arith_eval_comparison_r0r n vz v2 is).(_CC)))
+ | OArithComparisonR0R_CV_XZR n is vz, [Val v2] => Some (Val ((arith_eval_comparison_r0r n vz v2 is).(_CV)))
+ | OArithComparisonP_CN n, [Val v] => Some (Val ((arith_eval_comparison_p n v).(_CN)))
+ | OArithComparisonP_CZ n, [Val v] => Some (Val ((arith_eval_comparison_p n v).(_CZ)))
+ | OArithComparisonP_CC n, [Val v] => Some (Val ((arith_eval_comparison_p n v).(_CC)))
+ | OArithComparisonP_CV n, [Val v] => Some (Val ((arith_eval_comparison_p n v).(_CV)))
+ | Ocset c, l => cflags_eval c l Vundef Vundef 0
+ | Ofmovi fsz, [Val v] => Some (Val (fmovi_eval fsz v))
+ | Ofmovi_XZR fsz, [] => Some (Val (fmovi_eval_xzr fsz))
+ | Ocsel c, Val v1 :: Val v2 :: l' => cflags_eval c l' v1 v2 1
+ | Ofnmul fsz, [Val v1; Val v2] => Some (Val (fnmul_eval fsz v1 v2))
+ | _, _ => None
+ end.
+
+Definition call_ll_storev (c: memory_chunk) (m: mem) (v: option val) (vs: val) :=
+ match v with
+ | Some va => match Mem.storev c m va vs with
+ | Some m' => Some (Memstate m')
+ | None => None
+ end
+ | None => None (* should never occurs *)
+ end.
+
+Definition exec_store1 (n: store_rs_a) (m: mem) (a: addressing) (vr vs: val) :=
+ let v :=
+ match a with
+ | ADimm _ n => Some (Val.addl vs (Vlong n))
+ | ADadr _ id ofs => Some (Val.addl vs (symbol_low Ge.(_lk) id ofs))
+ | _ => None
+ end in
+ call_ll_storev (chunk_store_rs_a n) m v vr.
+
+Definition exec_store2 (n: store_rs_a) (m: mem) (a: addressing) (vr vs1 vs2: val) :=
+ let v :=
+ match a with
+ | ADreg _ _ => Some (Val.addl vs1 vs2)
+ | ADlsl _ _ n => Some (Val.addl vs1 (Val.shll vs2 (Vint n)))
+ | ADsxt _ _ n => Some (Val.addl vs1 (Val.shll (Val.longofint vs2) (Vint n)))
+ | ADuxt _ _ n => Some (Val.addl vs1 (Val.shll (Val.longofintu vs2) (Vint n)))
+ | _ => None
+ end in
+ call_ll_storev (chunk_store_rs_a n) m v vr.
+
+Definition exec_storeU (n: store_rs_a) (m: mem) (a: addressing) (vr: val) :=
+ call_ll_storev (chunk_store_rs_a n) m None vr.
+
+Definition goto_label_deps (f: function) (lbl: label) (vpc: val) :=
+ match label_pos lbl 0 (fn_blocks f) with
+ | None => None
+ | Some pos =>
+ match vpc with
+ | Vptr b ofs => Some (Val (Vptr b (Ptrofs.repr pos)))
+ | _ => None
+ end
+ end.
+
+Definition control_eval (o: control_op) (l: list value) :=
+ let (ge, fn, lk) := Ge in
+ match o, l with
+ | Ob lbl, [Val vpc] => goto_label_deps fn lbl vpc
+ | Obc c lbl, Val vpc :: l' => match cflags_eval c l' Vundef Vundef 2 with
+ | Some (Bool true) => goto_label_deps fn lbl vpc
+ | Some (Bool false) => Some (Val vpc)
+ | _ => None
+ end
+ | Obl id, [] => Some (Val (Genv.symbol_address Ge.(_genv) id Ptrofs.zero))
+ | Obs id, [] => Some (Val (Genv.symbol_address Ge.(_genv) id Ptrofs.zero))
+ | Ocbnz sz lbl, [Val v; Val vpc] => match eval_testzero sz v with
+ | Some (true) => Some (Val vpc)
+ | Some (false) => goto_label_deps fn lbl vpc
+ | None => None
+ end
+ | Ocbz sz lbl, [Val v; Val vpc] => match eval_testzero sz v with
+ | Some (true) => goto_label_deps fn lbl vpc
+ | Some (false) => Some (Val vpc)
+ | None => None
+ end
+ | Otbnz sz n lbl, [Val v; Val vpc] => match eval_testbit sz v n with
+ | Some (true) => goto_label_deps fn lbl vpc
+ | Some (false) => Some (Val vpc)
+ | None => None
+ end
+ | Otbz sz n lbl, [Val v; Val vpc] => match eval_testbit sz v n with
+ | Some (true) => Some (Val vpc)
+ | Some (false) => goto_label_deps fn lbl vpc
+ | None => None
+ end
+ | Obtbl tbl, [Val index; Val vpc] => match index with
+ | Vint n =>
+ match list_nth_z tbl (Int.unsigned n) with
+ | None => None
+ | Some lbl => goto_label_deps fn lbl vpc
+ end
+ | _ => None
+ end
+ | OIncremPC sz, [Val vpc] => Some (Val (Val.offset_ptr vpc (Ptrofs.repr sz)))
+ | OError, _ => None
+ | _, _ => None
+ end.
+
+Definition store_eval (o: store_op) (l: list value) :=
+ match o, l with
+ | Ostore1 st a, [Val vr; Val vs; Memstate m] => exec_store1 st m a vr vs
+ | Ostore2 st a, [Val vr; Val vs1; Val vs2; Memstate m] => exec_store2 st m a vr vs1 vs2
+ | OstoreU st a, [Val vr; Memstate m] => exec_storeU st m a vr
+ | _, _ => None
+ end.
+
+Definition call_ll_loadv (c: memory_chunk) (transf: val -> val) (m: mem) (v: option val) :=
+ match v with
+ | Some va => match Mem.loadv c m va with
+ | Some v' => Some (Val (transf v'))
+ | None => None
+ end
+ | None => None (* should never occurs *)
+ end.
+
+Definition exec_load1 (n: load_rd_a) (m: mem) (a: addressing) (vl: val) :=
+ let v :=
+ match a with
+ | ADimm _ n => Some (Val.addl vl (Vlong n))
+ | ADadr _ id ofs => Some (Val.addl vl (symbol_low Ge.(_lk) id ofs))
+ | _ => None
+ end in
+ call_ll_loadv (chunk_load_rd_a n) (interp_load_rd_a n) m v.
+
+Definition exec_load2 (n: load_rd_a) (m: mem) (a: addressing) (vl1 vl2: val) :=
+ let v :=
+ match a with
+ | ADreg _ _ => Some (Val.addl vl1 vl2)
+ | ADlsl _ _ n => Some (Val.addl vl1 (Val.shll vl2 (Vint n)))
+ | ADsxt _ _ n => Some (Val.addl vl1 (Val.shll (Val.longofint vl2) (Vint n)))
+ | ADuxt _ _ n => Some (Val.addl vl1 (Val.shll (Val.longofintu vl2) (Vint n)))
+ | _ => None
+ end in
+ call_ll_loadv (chunk_load_rd_a n) (interp_load_rd_a n) m v.
+
+Definition exec_loadU (n: load_rd_a) (m: mem) (a: addressing) :=
+ call_ll_loadv (chunk_load_rd_a n) (interp_load_rd_a n) m None.
+
+Definition load_eval (o: load_op) (l: list value) :=
+ match o, l with
+ | Oload1 st a, [Val vs; Memstate m] => exec_load1 st m a vs
+ | Oload2 st a, [Val vs1; Val vs2; Memstate m] => exec_load2 st m a vs1 vs2
+ | OloadU st a, [Memstate m] => exec_loadU st m a
+ | _, _ => None
+ end.
+
+Definition eval_allocf (o: allocf_op) (l: list value) :=
+ match o, l with
+ | OAllocf_Mem sz linkofs, [Val spv; Memstate m] =>
+ let (m1, stk) := Mem.alloc m 0 sz in
+ let sp := (Vptr stk Ptrofs.zero) in
+ call_ll_storev Mint64 m1 (Some (Val.offset_ptr sp linkofs)) spv
+ | OAllocf_SP sz linkofs, [Val spv; Memstate m] =>
+ let (m1, stk) := Mem.alloc m 0 sz in
+ let sp := (Vptr stk Ptrofs.zero) in
+ match call_ll_storev Mint64 m1 (Some (Val.offset_ptr sp linkofs)) spv with
+ | None => None
+ | Some ms => Some (Val sp)
+ end
+ | _, _ => None
+ end.
+
+Definition eval_freef (o: freef_op) (l: list value) :=
+ match o, l with
+ | OFreef_Mem sz linkofs, [Val spv; Memstate m] =>
+ match call_ll_loadv Mint64 (fun v => v) m (Some (Val.offset_ptr spv linkofs)) with
+ | None => None
+ | Some v =>
+ match spv with
+ | Vptr stk ofs =>
+ match Mem.free m stk 0 sz with
+ | None => None
+ | Some m' => Some (Memstate m')
+ end
+ | _ => None
+ end
+ end
+ | OFreef_SP sz linkofs, [Val spv; Memstate m] =>
+ match call_ll_loadv Mint64 (fun v => v) m (Some (Val.offset_ptr spv linkofs)) with
+ | None => None
+ | Some v =>
+ match spv with
+ | Vptr stk ofs =>
+ match Mem.free m stk 0 sz with
+ | None => None
+ | Some m' => Some (v)
+ end
+ | _ => None
+ end
+ end
+ | _, _ => None
+ end.
+
+Definition op_eval (op: op) (l:list value) :=
+ match op, l with
+ | Arith op, l => arith_op_eval op l
+ | Load o, l => load_eval o l
+ | Store o, l => store_eval o l
+ | Allocframe o, l => eval_allocf o l
+ | Freeframe o, l => eval_freef o l
+ | Loadsymbol id, [] => Some (Val (Genv.symbol_address Ge.(_genv) id Ptrofs.zero))
+ | Cvtsw2x, [Val v] => Some (Val (Val.longofint v))
+ | Cvtuw2x, [Val v] => Some (Val (Val.longofintu v))
+ | Cvtx2w, [Val v] => Some (Val (Val.loword v))
+ | Control o, l => control_eval o l
+ | Constant v, [] => Some (Val v)
+ | _, _ => None
+ end.
+
+Definition vz_eq (vz1 vz2: val) : ?? bool :=
+ RET (match vz1 with
+ | Vint i1 => match vz2 with
+ | Vint i2 => Int.eq i1 i2
+ | _ => false
+ end
+ | Vlong l1 => match vz2 with
+ | Vlong l2 => Int64.eq l1 l2
+ | _ => false
+ end
+ | _ => false
+ end).
+
+Lemma vz_eq_correct vz1 vz2:
+ WHEN vz_eq vz1 vz2 ~> b THEN b = true -> vz1 = vz2.
+Proof.
+ wlp_simplify.
+ destruct vz1; destruct vz2; trivial; try discriminate.
+ - eapply f_equal; apply Int.same_if_eq; auto.
+ - eapply f_equal. apply Int64.same_if_eq; auto.
+Qed.
+Hint Resolve vz_eq_correct: wlp.
+
+Definition is_eq (is1 is2: isize) : ?? bool :=
+ RET (match is1 with
+ | W => match is2 with
+ | W => true
+ | _ => false
+ end
+ | X => match is2 with
+ | X => true
+ | _ => false
+ end
+ end).
+
+Lemma is_eq_correct is1 is2:
+ WHEN is_eq is1 is2 ~> b THEN b = true -> is1 = is2.
+Proof.
+ wlp_simplify; destruct is1; destruct is2; trivial; try discriminate.
+Qed.
+Hint Resolve is_eq_correct: wlp.
+
+(*Definition testcond_eq (c1 c2: testcond) : ?? bool :=*)
+ (*RET (match c1 with*)
+ (*| TCeq => match c2 with*)
+ (*| TCeq => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCne => match c2 with*)
+ (*| TCne => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TChs => match c2 with*)
+ (*| TChs => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TClo => match c2 with*)
+ (*| TClo => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCmi => match c2 with*)
+ (*| TCmi => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCpl => match c2 with*)
+ (*| TCpl => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TChi => match c2 with*)
+ (*| TChi => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCls => match c2 with*)
+ (*| TCls => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCge => match c2 with*)
+ (*| TCge => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TClt => match c2 with*)
+ (*| TClt => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCgt => match c2 with*)
+ (*| TCgt => true*)
+ (*| _ => false*)
+ (*end*)
+ (*| TCle => match c2 with*)
+ (*| TCle => true*)
+ (*| _ => false*)
+ (*end*)
+ (*end).*)
+
+(*Lemma testcond_eq_correct c1 c2:*)
+ (*WHEN testcond_eq c1 c2 ~> b THEN b = true -> c1 = c2.*)
+(*Proof.*)
+ (*wlp_simplify; destruct c1; destruct c2; trivial; try discriminate.*)
+(*Qed.*)
+(*Hint Resolve testcond_eq_correct: wlp.*)
+
+Definition arith_op_eq (o1 o2: arith_op): ?? bool :=
+ match o1 with
+ | OArithP n1 =>
+ match o2 with OArithP n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithPP n1 =>
+ match o2 with OArithPP n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithPPP n1 =>
+ match o2 with OArithPPP n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithRR0R n1 =>
+ match o2 with OArithRR0R n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithRR0R_XZR n1 vz1 =>
+ match o2 with OArithRR0R_XZR n2 vz2 => iandb (phys_eq n1 n2) (vz_eq vz1 vz2) | _ => RET false end
+ | OArithRR0 n1 =>
+ match o2 with OArithRR0 n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithRR0_XZR n1 vz1 =>
+ match o2 with OArithRR0_XZR n2 vz2 => iandb (phys_eq n1 n2) (vz_eq vz1 vz2) | _ => RET false end
+ | OArithARRRR0 n1 =>
+ match o2 with OArithARRRR0 n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithARRRR0_XZR n1 vz1 =>
+ match o2 with OArithARRRR0_XZR n2 vz2 => iandb (phys_eq n1 n2) (vz_eq vz1 vz2) | _ => RET false end
+ | OArithComparisonPP_CN n1 =>
+ match o2 with OArithComparisonPP_CN n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonPP_CZ n1 =>
+ match o2 with OArithComparisonPP_CZ n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonPP_CC n1 =>
+ match o2 with OArithComparisonPP_CC n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonPP_CV n1 =>
+ match o2 with OArithComparisonPP_CV n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonR0R_CN n1 is1 =>
+ match o2 with OArithComparisonR0R_CN n2 is2 => iandb (phys_eq n1 n2) (is_eq is1 is2) | _ => RET false end
+ | OArithComparisonR0R_CZ n1 is1 =>
+ match o2 with OArithComparisonR0R_CZ n2 is2 => iandb (phys_eq n1 n2) (is_eq is1 is2) | _ => RET false end
+ | OArithComparisonR0R_CC n1 is1 =>
+ match o2 with OArithComparisonR0R_CC n2 is2 => iandb (phys_eq n1 n2) (is_eq is1 is2) | _ => RET false end
+ | OArithComparisonR0R_CV n1 is1 =>
+ match o2 with OArithComparisonR0R_CV n2 is2 => iandb (phys_eq n1 n2) (is_eq is1 is2) | _ => RET false end
+ | OArithComparisonR0R_CN_XZR n1 is1 vz1 =>
+ match o2 with OArithComparisonR0R_CN_XZR n2 is2 vz2 => iandb (vz_eq vz1 vz2) (iandb (phys_eq n1 n2) (is_eq is1 is2)) | _ => RET false end
+ | OArithComparisonR0R_CZ_XZR n1 is1 vz1 =>
+ match o2 with OArithComparisonR0R_CZ_XZR n2 is2 vz2 => iandb (vz_eq vz1 vz2) (iandb (phys_eq n1 n2) (is_eq is1 is2)) | _ => RET false end
+ | OArithComparisonR0R_CC_XZR n1 is1 vz1 =>
+ match o2 with OArithComparisonR0R_CC_XZR n2 is2 vz2 => iandb (vz_eq vz1 vz2) (iandb (phys_eq n1 n2) (is_eq is1 is2)) | _ => RET false end
+ | OArithComparisonR0R_CV_XZR n1 is1 vz1 =>
+ match o2 with OArithComparisonR0R_CV_XZR n2 is2 vz2 => iandb (vz_eq vz1 vz2) (iandb (phys_eq n1 n2) (is_eq is1 is2)) | _ => RET false end
+ | OArithComparisonP_CN n1 =>
+ match o2 with OArithComparisonP_CN n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonP_CZ n1 =>
+ match o2 with OArithComparisonP_CZ n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonP_CC n1 =>
+ match o2 with OArithComparisonP_CC n2 => phys_eq n1 n2 | _ => RET false end
+ | OArithComparisonP_CV n1 =>
+ match o2 with OArithComparisonP_CV n2 => phys_eq n1 n2 | _ => RET false end
+ | Ocset c1 =>
+ match o2 with Ocset c2 => struct_eq c1 c2 | _ => RET false end
+ | Ofmovi fsz1 =>
+ match o2 with Ofmovi fsz2 => phys_eq fsz1 fsz2 | _ => RET false end
+ | Ofmovi_XZR fsz1 =>
+ match o2 with Ofmovi_XZR fsz2 => phys_eq fsz1 fsz2 | _ => RET false end
+ | Ocsel c1 =>
+ match o2 with Ocsel c2 => struct_eq c1 c2 | _ => RET false end
+ | Ofnmul fsz1 =>
+ match o2 with Ofnmul fsz2 => phys_eq fsz1 fsz2 | _ => RET false end
+ end.
+
+Ltac my_wlp_simplify := wlp_xsimplify ltac:(intros; subst; simpl in * |- *; congruence || intuition eauto with wlp).
+
+Lemma arith_op_eq_correct o1 o2:
+ WHEN arith_op_eq o1 o2 ~> b THEN b = true -> o1 = o2.
+Proof.
+ destruct o1, o2; my_wlp_simplify; try congruence;
+ try (destruct vz; destruct vz0); try (destruct is; destruct is0);
+ repeat apply f_equal; try congruence;
+ try apply Int.same_if_eq; try apply Int64.same_if_eq; try auto.
+Qed.
+Hint Resolve arith_op_eq_correct: wlp.
+Opaque arith_op_eq_correct.
+
+Definition control_op_eq (c1 c2: control_op): ?? bool :=
+ match c1 with
+ | Ob lbl1 =>
+ match c2 with Ob lbl2 => phys_eq lbl1 lbl2 | _ => RET false end
+ | Obc c1 lbl1 =>
+ match c2 with Obc c2 lbl2 => iandb (struct_eq c1 c2) (phys_eq lbl1 lbl2) | _ => RET false end
+ | Obl id1 =>
+ match c2 with Obl id2 => phys_eq id1 id2 | _ => RET false end
+ | Obs id1 =>
+ match c2 with Obs id2 => phys_eq id1 id2 | _ => RET false end
+ | Ocbnz sz1 lbl1 =>
+ match c2 with Ocbnz sz2 lbl2 => iandb (phys_eq sz1 sz2) (phys_eq lbl1 lbl2) | _ => RET false end
+ | Ocbz sz1 lbl1 =>
+ match c2 with Ocbz sz2 lbl2 => iandb (phys_eq sz1 sz2) (phys_eq lbl1 lbl2) | _ => RET false end
+ | Otbnz sz1 n1 lbl1 =>
+ match c2 with Otbnz sz2 n2 lbl2 => iandb (RET (Int.eq n1 n2)) (iandb (phys_eq sz1 sz2) (phys_eq lbl1 lbl2)) | _ => RET false end
+ | Otbz sz1 n1 lbl1 =>
+ match c2 with Otbz sz2 n2 lbl2 => iandb (RET (Int.eq n1 n2)) (iandb (phys_eq sz1 sz2) (phys_eq lbl1 lbl2)) | _ => RET false end
+ | Obtbl tbl1 =>
+ match c2 with Obtbl tbl2 => (phys_eq tbl1 tbl2) | _ => RET false end
+ (*| Ocbu bt1 l1 =>*)
+ (*match c2 with Ocbu bt2 l2 => iandb (phys_eq bt1 bt2) (phys_eq l1 l2) | _ => RET false end*)
+ (*| Ojumptable tbl1 =>*)
+ (*match c2 with Ojumptable tbl2 => phys_eq tbl1 tbl2 | _ => RET false end*)
+ (*| Odiv =>*)
+ (*match c2 with Odiv => RET true | _ => RET false end*)
+ (*| Odivu =>*)
+ (*match c2 with Odivu => RET true | _ => RET false end*)
+ | OIncremPC sz1 =>
+ match c2 with OIncremPC sz2 => RET (Z.eqb sz1 sz2) | _ => RET false end
+ | OError =>
+ match c2 with OError => RET true | _ => RET false end
+ end.
+
+Lemma control_op_eq_correct c1 c2:
+ WHEN control_op_eq c1 c2 ~> b THEN b = true -> c1 = c2.
+Proof.
+ destruct c1, c2; wlp_simplify; try rewrite Z.eqb_eq in * |-; try congruence;
+ try apply Int.same_if_eq in H; try congruence.
+Qed.
+Hint Resolve control_op_eq_correct: wlp.
+Opaque control_op_eq_correct.
+
+Definition store_op_eq (s1 s2: store_op): ?? bool :=
+ match s1 with
+ | Ostore1 st1 a1 =>
+ match s2 with Ostore1 st2 a2 => iandb (phys_eq st1 st2) (struct_eq a1 a2) | _ => RET false end
+ | Ostore2 st1 a1 =>
+ match s2 with Ostore2 st2 a2 => iandb (phys_eq st1 st2) (struct_eq a1 a2) | _ => RET false end
+ | OstoreU st1 a1 =>
+ match s2 with OstoreU st2 a2 => iandb (phys_eq st1 st2) (struct_eq a1 a2) | _ => RET false end
+ end.
+
+Lemma store_op_eq_correct s1 s2:
+ WHEN store_op_eq s1 s2 ~> b THEN b = true -> s1 = s2.
+Proof.
+ destruct s1, s2; wlp_simplify; try congruence.
+ all: rewrite H0 in H; rewrite H; reflexivity.
+Qed.
+Hint Resolve store_op_eq_correct: wlp.
+Opaque store_op_eq_correct.
+
+Definition load_op_eq (l1 l2: load_op): ?? bool :=
+ match l1 with
+ | Oload1 ld1 a1 =>
+ match l2 with Oload1 ld2 a2 => iandb (phys_eq ld1 ld2) (struct_eq a1 a2) | _ => RET false end
+ | Oload2 ld1 a1 =>
+ match l2 with Oload2 ld2 a2 => iandb (phys_eq ld1 ld2) (struct_eq a1 a2) | _ => RET false end
+ | OloadU ld1 a1 =>
+ match l2 with OloadU ld2 a2 => iandb (phys_eq ld1 ld2) (struct_eq a1 a2) | _ => RET false end
+ end.
+
+Lemma load_op_eq_correct l1 l2:
+ WHEN load_op_eq l1 l2 ~> b THEN b = true -> l1 = l2.
+Proof.
+ destruct l1, l2; wlp_simplify; try congruence.
+ all: rewrite H0 in H; rewrite H; reflexivity.
+Qed.
+Hint Resolve load_op_eq_correct: wlp.
+Opaque load_op_eq_correct.
+
+Definition allocf_op_eq (al1 al2: allocf_op): ?? bool :=
+ match al1 with
+ | OAllocf_SP sz1 linkofs1 =>
+ match al2 with OAllocf_SP sz2 linkofs2 => iandb (RET (Z.eqb sz1 sz2)) (phys_eq linkofs1 linkofs2) | _ => RET false end
+ | OAllocf_Mem sz1 linkofs1 =>
+ match al2 with OAllocf_Mem sz2 linkofs2 => iandb (RET (Z.eqb sz1 sz2)) (phys_eq linkofs1 linkofs2) | _ => RET false end
+ end.
+
+Lemma allocf_op_eq_correct al1 al2:
+ WHEN allocf_op_eq al1 al2 ~> b THEN b = true -> al1 = al2.
+Proof.
+ destruct al1, al2; wlp_simplify; try congruence.
+ all: rewrite H2; rewrite Z.eqb_eq in H; rewrite H; reflexivity.
+Qed.
+Hint Resolve allocf_op_eq_correct: wlp.
+Opaque allocf_op_eq_correct.
+
+Definition freef_op_eq (fr1 fr2: freef_op): ?? bool :=
+ match fr1 with
+ | OFreef_SP sz1 linkofs1 =>
+ match fr2 with OFreef_SP sz2 linkofs2 => iandb (RET (Z.eqb sz1 sz2)) (phys_eq linkofs1 linkofs2) | _ => RET false end
+ | OFreef_Mem sz1 linkofs1 =>
+ match fr2 with OFreef_Mem sz2 linkofs2 => iandb (RET (Z.eqb sz1 sz2)) (phys_eq linkofs1 linkofs2) | _ => RET false end
+ end.
+
+Lemma freef_op_eq_correct fr1 fr2:
+ WHEN freef_op_eq fr1 fr2 ~> b THEN b = true -> fr1 = fr2.
+Proof.
+ destruct fr1, fr2; wlp_simplify; try congruence.
+ all: rewrite H2; rewrite Z.eqb_eq in H; rewrite H; reflexivity.
+Qed.
+Hint Resolve freef_op_eq_correct: wlp.
+Opaque freef_op_eq_correct.
+
+Definition op_eq (o1 o2: op): ?? bool :=
+ match o1 with
+ | Arith i1 =>
+ match o2 with Arith i2 => arith_op_eq i1 i2 | _ => RET false end
+ | Control i1 =>
+ match o2 with Control i2 => control_op_eq i1 i2 | _ => RET false end
+ | Load i1 =>
+ match o2 with Load i2 => load_op_eq i1 i2 | _ => RET false end
+ | Store i1 =>
+ match o2 with Store i2 => store_op_eq i1 i2 | _ => RET false end
+ | Allocframe i1 =>
+ match o2 with Allocframe i2 => allocf_op_eq i1 i2 | _ => RET false end
+ | Freeframe i1 =>
+ match o2 with Freeframe i2 => freef_op_eq i1 i2 | _ => RET false end
+ | Loadsymbol id1 =>
+ match o2 with Loadsymbol id2 => phys_eq id1 id2 | _ => RET false end
+ | Cvtsw2x =>
+ match o2 with Cvtsw2x => RET true | _ => RET false end
+ | Cvtuw2x =>
+ match o2 with Cvtuw2x => RET true | _ => RET false end
+ | Cvtx2w =>
+ match o2 with Cvtx2w => RET true | _ => RET false end
+ | Constant c1 =>
+ match o2 with Constant c2 => phys_eq c1 c2 | _ => RET false end
+ (*| _ => RET false*)
+ end.
+
+Lemma op_eq_correct o1 o2:
+ WHEN op_eq o1 o2 ~> b THEN b=true -> o1 = o2.
+Proof.
+ destruct o1, o2; wlp_simplify; congruence.
+Qed.
+
+End IMPPARAM.
+
+End P.
+
+Module L <: ISeqLanguage with Module LP:=P.
+
+Module LP:=P.
+
+Include MkSeqLanguage P.
+
+End L.
+
+Module IST := ImpSimu L ImpPosDict.
+
+Import L.
+Import P.
+
+(** Compilation from [Asmvliw] to [L] *)
+
+Local Open Scope positive_scope.
+
+Definition pmem : R.t := 1.
+
+Definition ireg_to_pos (ir: ireg) : R.t :=
+ match ir with
+ | X0 => 8 | X1 => 9 | X2 => 10 | X3 => 11 | X4 => 12 | X5 => 13 | X6 => 14 | X7 => 15
+ | X8 => 16 | X9 => 17 | X10 => 18 | X11 => 19 | X12 => 20 | X13 => 21 | X14 => 22 | X15 => 23
+ | X16 => 24 | X17 => 25 | X18 => 26 | X19 => 27 | X20 => 28 | X21 => 29 | X22 => 30 | X23 => 31
+ | X24 => 32 | X25 => 33 | X26 => 34 | X27 => 35 | X28 => 36 | X29 => 37 | X30 => 38
+ end
+.
+
+Definition freg_to_pos (fr: freg) : R.t :=
+ match fr with
+ | D0 => 39 | D1 => 40 | D2 => 41 | D3 => 42 | D4 => 43 | D5 => 44 | D6 => 45 | D7 => 46
+ | D8 => 47 | D9 => 48 | D10 => 49 | D11 => 50 | D12 => 51 | D13 => 52 | D14 => 53 | D15 => 54
+ | D16 => 55 | D17 => 56 | D18 => 57 | D19 => 58 | D20 => 59 | D21 => 60 | D22 => 61 | D23 => 62
+ | D24 => 63 | D25 => 64 | D26 => 65 | D27 => 66 | D28 => 67 | D29 => 68 | D30 => 69 | D31 => 70
+ end
+.
+
+Lemma ireg_to_pos_discr: forall r r', r <> r' -> ireg_to_pos r <> ireg_to_pos r'.
+Proof.
+ destruct r; destruct r'; try contradiction; discriminate.
+Qed.
+
+Lemma freg_to_pos_discr: forall r r', r <> r' -> freg_to_pos r <> freg_to_pos r'.
+Proof.
+ destruct r; destruct r'; try contradiction; discriminate.
+Qed.
+
+(*Lemma creg_to_pos_discr: forall r r', r <> r' -> freg_to_pos r <> freg_to_pos r'.*)
+(*Proof.*)
+ (*destruct r; destruct r'; try contradiction; discriminate.*)
+(*Qed.*)
+
+Definition ppos (r: preg) : R.t :=
+ match r with
+ | CR c => match c with
+ | CN => 2
+ | CZ => 3
+ | CC => 4
+ | CV => 5
+ end
+ | PC => 6
+ | DR d => match d with
+ | IR i => match i with
+ | XSP => 7
+ | RR1 ir => ireg_to_pos ir
+ end
+ | FR fr => freg_to_pos fr
+ end
+ end
+.
+
+(*Definition ppos_ireg0 (r: ireg0) : R.t :=*)
+ (*match r with*)
+ (*| RR0 p => ppos p*)
+ (*| XZR => 71*)
+ (*end*)
+(*.*)
+
+Notation "# r" := (ppos r) (at level 100, right associativity).
+
+Lemma not_eq_add:
+ forall k n n', n <> n' -> k + n <> k + n'.
+Proof.
+ intros k n n' H1 H2. apply H1; clear H1. eapply Pos.add_reg_l; eauto.
+Qed.
+
+Lemma ppos_equal: forall r r', r = r' <-> ppos r = ppos r'.
+Proof.
+ destruct r as [dr|cr|]; destruct r' as [dr'|cr'|];
+ try destruct dr as [ir|fr]; try destruct dr' as [ir'|fr'];
+ try destruct ir as [irr|]; try destruct ir' as [irr'|].
+ all: split; intros; try rewrite H; try discriminate; try contradiction; simpl; eauto;
+ try destruct irr; try destruct irr';
+ try destruct fr; try destruct fr';
+ try destruct cr; try destruct cr';
+ simpl; try discriminate; try reflexivity.
+Qed.
+
+Lemma ppos_discr: forall r r', r <> r' -> ppos r <> ppos r'.
+Proof.
+ destruct r as [dr|cr|]; destruct r' as [dr'|cr'|];
+ try destruct dr as [ir|fr]; try destruct dr' as [ir'|fr'];
+ try destruct ir as [irr|]; try destruct ir' as [irr'|].
+ all: try discriminate; try contradiction.
+ 1: intros; unfold ppos; apply ireg_to_pos_discr; congruence.
+ 1,2,11,18: intros; unfold ppos; try destruct irr; try destruct irr'; discriminate.
+ 1,3: intros; unfold ppos; try destruct irr; try destruct fr; try destruct irr'; try destruct fr'; discriminate.
+ 1,2,7,13: intros; unfold ppos; try destruct fr; try destruct fr'; discriminate.
+ 1: intros; unfold ppos; apply freg_to_pos_discr; congruence.
+ 1,4: intros; unfold ppos; try destruct irr; try destruct irr'; try destruct cr; try destruct cr'; discriminate.
+ 2,4: intros; unfold ppos; try destruct fr; try destruct fr'; try destruct cr; try destruct cr'; discriminate.
+ 1,2,4,5: intros; unfold ppos; try destruct cr; try destruct cr'; discriminate.
+ 1: intros; unfold ppos; try destruct cr; try destruct cr'; congruence.
+Qed.
+
+Lemma ppos_pmem_discr: forall r, pmem <> ppos r.
+Proof.
+ intros. destruct r as [dr|cr|].
+ - destruct dr as [ir|fr]; try destruct ir as [irr|]; try destruct irr; try destruct fr;
+ unfold ppos; unfold pmem; discriminate.
+ - unfold ppos; unfold pmem; destruct cr; discriminate.
+ - unfold ppos; unfold pmem; discriminate.
+Qed.
+
+(** Inversion functions, used for debug traces *)
+
+Definition pos_to_ireg (p: R.t) : option ireg :=
+ match p with
+ | 8 => Some (X0) | 9 => Some (X1) | 10 => Some (X2) | 11 => Some (X3) | 12 => Some (X4) | 13 => Some (X5) | 14 => Some (X6) | 15 => Some (X7)
+ | 16 => Some (X8) | 17 => Some (X9) | 18 => Some (X10) | 19 => Some (X11) | 20 => Some (X12) | 21 => Some (X13) | 22 => Some (X14) | 23 => Some (X15)
+ | 24 => Some (X16) | 25 => Some (X17) | 26 => Some (X18) | 27 => Some (X19) | 28 => Some (X20) | 29 => Some (X21) | 30 => Some (X22) | 31 => Some (X23)
+ | 32 => Some (X24) | 33 => Some (X25) | 34 => Some (X26) | 35 => Some (X27) | 36 => Some (X28) | 37 => Some (X29) | 38 => Some (X30) | _ => None
+ end.
+
+Definition pos_to_freg (p: R.t) : option freg :=
+ match p with
+ | 39 => Some(D0) | 40 => Some(D1) | 41 => Some(D2) | 42 => Some(D3) | 43 => Some(D4) | 44 => Some(D5) | 45 => Some(D6) | 46 => Some(D7)
+ | 47 => Some(D8) | 48 => Some(D9) | 49 => Some(D10) | 50 => Some(D11) | 51 => Some(D12) | 52 => Some(D13) | 53 => Some(D14) | 54 => Some(D15)
+ | 55 => Some(D16) | 56 => Some(D17) | 57 => Some(D18) | 58 => Some(D19) | 59 => Some(D20) | 60 => Some(D21) | 61 => Some(D22) | 62 => Some(D23)
+ | 63 => Some(D24) | 64 => Some(D25) | 65 => Some(D26) | 66 => Some(D27) | 67 => Some(D28) | 68 => Some(D29) | 69 => Some(D30) | 70 => Some(D31) | _ => None
+ end.
+
+Definition inv_ppos (p: R.t) : option preg :=
+ match p with
+ | 1 => None
+ | 2 => Some (CR CN)
+ | 3 => Some (CR CZ)
+ | 4 => Some (CR CC)
+ | 5 => Some (CR CV)
+ | 6 => Some (PC)
+ | 7 => Some (DR (IR XSP))
+ | n => match pos_to_ireg n with
+ | None => match pos_to_freg n with
+ | None => None
+ | Some fr => Some (DR (FR fr))
+ end
+ | Some ir => Some (DR (IR ir))
+ end
+ end.
+
+Notation "a @ b" := (Econs a b) (at level 102, right associativity).
+
+(** Translations of instructions *)
+
+Definition get_testcond_rlocs (c: testcond) :=
+ match c with
+ | TCeq => (PReg(#CZ) @ Enil)
+ | TCne => (PReg(#CZ) @ Enil)
+ | TChs => (PReg(#CC) @ Enil)
+ | TClo => (PReg(#CC) @ Enil)
+ | TCmi => (PReg(#CN) @ Enil)
+ | TCpl => (PReg(#CN) @ Enil)
+ | TChi => (PReg(#CZ) @ PReg(#CC) @ Enil)
+ | TCls => (PReg(#CZ) @ PReg(#CC) @ Enil)
+ | TCge => (PReg(#CN) @ PReg(#CV) @ Enil)
+ | TClt => (PReg(#CN) @ PReg(#CV) @ Enil)
+ | TCgt => (PReg(#CN) @ PReg(#CZ) @ PReg(#CV) @ Enil)
+ | TCle => (PReg(#CN) @ PReg(#CZ) @ PReg(#CV) @ Enil)
+ end.
+
+Definition trans_control (ctl: control) : inst :=
+ match ctl with
+ | Pb lbl => [(#PC, Op (Control (Ob lbl)) (PReg(#PC) @ Enil))]
+ | Pbc c lbl =>
+ let lr := get_testcond_rlocs c in
+ [(#PC, Op (Control (Obc c lbl)) (PReg(#PC) @ lr))]
+ | Pbl id sg => [(#RA, PReg(#PC));
+ (#PC, Op (Control (Obl id)) Enil)]
+ | Pbs id sg => [(#PC, Op (Control (Obs id)) Enil)]
+ | Pblr r sg => [(#RA, PReg(#PC));
+ (#PC, Old (PReg(#r)))]
+ | Pbr r sg => [(#PC, PReg(#r))]
+ | Pret r => [(#PC, PReg(#r))]
+ | Pcbnz sz r lbl => [(#PC, Op (Control (Ocbnz sz lbl)) (PReg(#r) @ PReg(#PC) @ Enil))]
+ | Pcbz sz r lbl => [(#PC, Op (Control (Ocbz sz lbl)) (PReg(#r) @ PReg(#PC) @ Enil))]
+ | Ptbnz sz r n lbl => [(#PC, Op (Control (Otbnz sz n lbl)) (PReg(#r) @ PReg(#PC) @ Enil))]
+ | Ptbz sz r n lbl => [(#PC, Op (Control (Otbz sz n lbl)) (PReg(#r) @ PReg(#PC) @ Enil))]
+ | Pbtbl r tbl => [(#X16, Op (Constant Vundef) Enil);
+ (#PC, Op (Control (Obtbl tbl)) (PReg(#r) @ PReg(#PC) @ Enil));
+ (#X16, Op (Constant Vundef) Enil);
+ (#X17, Op (Constant Vundef) Enil)]
+ | Pbuiltin ef args res => []
+ end.
+
+Definition trans_exit (ex: option control) : L.inst :=
+ match ex with
+ | None => []
+ | Some ctl => trans_control ctl
+ end
+.
+
+Definition trans_arith (ai: ar_instruction) : inst :=
+ match ai with
+ | PArithP n rd => [(#rd, Op(Arith (OArithP n)) Enil)]
+ | PArithPP n rd r1 => [(#rd, Op(Arith (OArithPP n)) (PReg(#r1) @ Enil))]
+ | PArithPPP n rd r1 r2 => [(#rd, Op(Arith (OArithPPP n)) (PReg(#r1) @ PReg(#r2) @ Enil))]
+ | PArithRR0R n rd r1 r2 =>
+ let lr := match r1 with
+ | RR0 r1' => Op(Arith (OArithRR0R n)) (PReg(#r1') @ PReg(#r2) @ Enil)
+ | XZR => let vz := if arith_rr0r_isize n then Vint Int.zero else Vlong Int64.zero in
+ Op(Arith (OArithRR0R_XZR n vz)) (PReg(#r2) @ Enil)
+ end in
+ [(#rd, lr)]
+ | PArithRR0 n rd r1 =>
+ let lr := match r1 with
+ | RR0 r1' => Op(Arith (OArithRR0 n)) (PReg(#r1') @ Enil)
+ | XZR => let vz := if arith_rr0_isize n then Vint Int.zero else Vlong Int64.zero in
+ Op(Arith (OArithRR0_XZR n vz)) (Enil)
+ end in
+ [(#rd, lr)]
+ | PArithARRRR0 n rd r1 r2 r3 =>
+ let lr := match r3 with
+ | RR0 r3' => Op(Arith (OArithARRRR0 n)) (PReg(#r1) @ PReg (#r2) @ PReg(#r3') @ Enil)
+ | XZR => let vz := if arith_arrrr0_isize n then Vint Int.zero else Vlong Int64.zero in
+ Op(Arith (OArithARRRR0_XZR n vz)) (PReg(#r1) @ PReg(#r2) @ Enil)
+ end in
+ [(#rd, lr)]
+ | PArithComparisonPP n r1 r2 =>
+ [(#CN, Op(Arith (OArithComparisonPP_CN n)) (PReg(#r1) @ PReg(#r2) @ Enil));
+ (#CZ, Op(Arith (OArithComparisonPP_CZ n)) (PReg(#r1) @ PReg(#r2) @ Enil));
+ (#CC, Op(Arith (OArithComparisonPP_CC n)) (PReg(#r1) @ PReg(#r2) @ Enil));
+ (#CV, Op(Arith (OArithComparisonPP_CV n)) (PReg(#r1) @ PReg(#r2) @ Enil))]
+ | PArithComparisonR0R n r1 r2 =>
+ let is := arith_comparison_r0r_isize n in
+ match r1 with
+ | RR0 r1' => [(#CN, Op(Arith (OArithComparisonR0R_CN n is)) (PReg(#r1') @ PReg(#r2) @ Enil));
+ (#CZ, Op(Arith (OArithComparisonR0R_CZ n is)) (PReg(#r1') @ PReg(#r2) @ Enil));
+ (#CC, Op(Arith (OArithComparisonR0R_CC n is)) (PReg(#r1') @ PReg(#r2) @ Enil));
+ (#CV, Op(Arith (OArithComparisonR0R_CV n is)) (PReg(#r1') @ PReg(#r2) @ Enil))]
+ | XZR => let vz := if is then Vint Int.zero else Vlong Int64.zero in
+ [(#CN, Op(Arith (OArithComparisonR0R_CN_XZR n is vz)) (PReg(#r2) @ Enil));
+ (#CZ, Op(Arith (OArithComparisonR0R_CZ_XZR n is vz)) (PReg(#r2) @ Enil));
+ (#CC, Op(Arith (OArithComparisonR0R_CC_XZR n is vz)) (PReg(#r2) @ Enil));
+ (#CV, Op(Arith (OArithComparisonR0R_CV_XZR n is vz)) (PReg(#r2) @ Enil))]
+ end
+ | PArithComparisonP n r1 =>
+ [(#CN, Op(Arith (OArithComparisonP_CN n)) (PReg(#r1) @ Enil));
+ (#CZ, Op(Arith (OArithComparisonP_CZ n)) (PReg(#r1) @ Enil));
+ (#CC, Op(Arith (OArithComparisonP_CC n)) (PReg(#r1) @ Enil));
+ (#CV, Op(Arith (OArithComparisonP_CV n)) (PReg(#r1) @ Enil))]
+ | Pcset rd c =>
+ let lr := get_testcond_rlocs c in
+ [(#rd, Op(Arith (Ocset c)) lr)]
+ | Pfmovi fsz rd r1 =>
+ let lr := match r1 with
+ | RR0 r1' => Op(Arith (Ofmovi fsz)) (PReg(#r1') @ Enil)
+ | XZR => Op(Arith (Ofmovi_XZR fsz)) Enil
+ end in
+ [(#rd, lr)]
+ | Pcsel rd r1 r2 c =>
+ let lr := get_testcond_rlocs c in
+ [(#rd, Op(Arith (Ocsel c)) (PReg(#r1) @ PReg (#r2) @ lr))]
+ | Pfnmul fsz rd r1 r2 => [(#rd, Op(Arith (Ofnmul fsz)) (PReg(#r1) @ PReg(#r2) @ Enil))]
+ end.
+
+Definition eval_addressing_rlocs_st (st: store_rs_a) (rs: dreg) (a: addressing) :=
+ match a with
+ | ADimm base n => Op (Store (Ostore1 st a)) (PReg (#rs) @ PReg (#base) @ PReg (pmem) @ Enil)
+ | ADreg base r => Op (Store (Ostore2 st a)) (PReg (#rs) @ PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADlsl base r n => Op (Store (Ostore2 st a)) (PReg (#rs) @ PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADsxt base r n => Op (Store (Ostore2 st a)) (PReg (#rs) @ PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADuxt base r n => Op (Store (Ostore2 st a)) (PReg (#rs) @ PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADadr base id ofs => Op (Store (Ostore1 st a)) (PReg (#rs) @ PReg (#base) @ PReg (pmem) @ Enil)
+ | ADpostincr base n => Op (Store (OstoreU st a)) (PReg (#rs) @ PReg (pmem) @ Enil) (* not modeled yet *)
+ end.
+
+Definition eval_addressing_rlocs_ld (ld: load_rd_a) (a: addressing) :=
+ match a with
+ | ADimm base n => Op (Load (Oload1 ld a)) (PReg (#base) @ PReg (pmem) @ Enil)
+ | ADreg base r => Op (Load (Oload2 ld a)) (PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADlsl base r n => Op (Load (Oload2 ld a)) (PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADsxt base r n => Op (Load (Oload2 ld a)) (PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADuxt base r n => Op (Load (Oload2 ld a)) (PReg (#base) @ PReg(#r) @ PReg (pmem) @ Enil)
+ | ADadr base id ofs => Op (Load (Oload1 ld a)) (PReg (#base) @ PReg (pmem) @ Enil)
+ | ADpostincr base n => Op (Load (OloadU ld a)) (PReg (pmem) @ Enil) (* not modeled yet *)
+ end.
+
+Definition trans_basic (b: basic) : inst :=
+ match b with
+ | PArith ai => trans_arith ai
+ | PLoad ld r a =>
+ let lr := eval_addressing_rlocs_ld ld a in [(#r, lr)]
+ | PStore st r a =>
+ let lr := eval_addressing_rlocs_st st r a in [(pmem, lr)]
+ | Pallocframe sz linkofs =>
+ [(#X29, PReg(#SP));
+ (#SP, Op (Allocframe (OAllocf_SP sz linkofs)) (PReg (#SP) @ PReg pmem @ Enil));
+ (#X16, Op (Constant Vundef) Enil);
+ (pmem, Op (Allocframe (OAllocf_Mem sz linkofs)) (Old(PReg(#SP)) @ PReg pmem @ Enil))]
+ | Pfreeframe sz linkofs =>
+ [(pmem, Op (Freeframe (OFreef_Mem sz linkofs)) (PReg (#SP) @ PReg pmem @ Enil));
+ (#SP, Op (Freeframe (OFreef_SP sz linkofs)) (PReg (#SP) @ Old (PReg pmem) @ Enil));
+ (#X16, Op (Constant Vundef) Enil)]
+ | Ploadsymbol rd id => [(#rd, Op (Loadsymbol id) Enil)]
+ | Pcvtsw2x rd r1 => [(#rd, Op (Cvtsw2x) (PReg (#r1) @ Enil))]
+ | Pcvtuw2x rd r1 => [(#rd, Op (Cvtuw2x) (PReg (#r1) @ Enil))]
+ | Pcvtx2w rd => [(#rd, Op (Cvtx2w) (PReg (#rd) @ Enil))]
+ end.
+
+Fixpoint trans_body (b: list basic) : list L.inst :=
+ match b with
+ | nil => nil
+ | b :: lb => (trans_basic b) :: (trans_body lb)
+ end.
+
+Definition trans_pcincr (sz: Z) (k: L.inst) := (#PC, Op (Control (OIncremPC sz)) (PReg(#PC) @ Enil)) :: k.
+
+Definition trans_block (b: Asmblock.bblock) : L.bblock :=
+ trans_body (body b) ++ (trans_pcincr (size b) (trans_exit (exit b)) :: nil).
+
+(*Theorem trans_block_noheader_inv: forall bb, trans_block (no_header bb) = trans_block bb.*)
+(*Proof.*)
+ (*intros. destruct bb as [hd bdy ex COR]; unfold no_header; simpl. unfold trans_block. simpl. reflexivity.*)
+(*Qed.*)
+
+(*Theorem trans_block_header_inv: forall bb hd, trans_block (stick_header hd bb) = trans_block bb.*)
+(*Proof.*)
+ (*intros. destruct bb as [hdr bdy ex COR]; unfold no_header; simpl. unfold trans_block. simpl. reflexivity.*)
+(*Qed.*)
+
+(** Lemmas on the translation *)
+
+Definition state := L.mem.
+Definition exec := L.run.
+
+Definition match_states (s: Asm.state) (s': state) :=
+ let (rs, m) := s in
+ s' pmem = Memstate m
+ /\ forall r, s' (#r) = Val (rs r).
+
+Definition match_outcome (o:outcome) (s: option state) :=
+ match o with
+ | Some n => exists s', s=Some s' /\ match_states n s'
+ | None => s=None
+ end.
+
+Notation "a <[ b <- c ]>" := (assign a b c) (at level 102, right associativity).
+
+Definition trans_state (s: Asm.state) : state :=
+ let (rs, m) := s in
+ fun x => if (Pos.eq_dec x pmem) then Memstate m
+ else match (inv_ppos x) with
+ | Some r => Val (rs r)
+ | None => Val Vundef
+ end.
+
+Lemma not_eq_IR:
+ forall r r', r <> r' -> IR r <> IR r'.
+Proof.
+ intros. congruence.
+Qed.
+
+(*Lemma inv_ppos_from_ireg: forall (ir: ireg),*)
+ (*exists x,*)
+ (*inv_ppos (x) = Some (DR (IR ir)).*)
+(*Proof.*)
+ (*intros. unfold inv_ppos.*)
+ (*eexists (ireg_to_pos ir). destruct ir; simpl; reflexivity.*)
+(*Qed.*)
+
+Lemma ireg_pos_ppos: forall (sr: state) r,
+ sr (ireg_to_pos r) = sr (# r).
+Proof.
+ intros. simpl. reflexivity.
+Qed.
+
+Lemma freg_pos_ppos: forall (sr: state) r,
+ sr (freg_to_pos r) = sr (# r).
+Proof.
+ intros. simpl. reflexivity.
+Qed.
+
+Lemma ireg_not_pc: forall r,
+ (#PC) <> ireg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma ireg_not_pmem: forall r,
+ ireg_to_pos r <> pmem.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma ireg_not_CN: forall r,
+ 2 <> ireg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma ireg_not_CZ: forall r,
+ 3 <> ireg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma ireg_not_CC: forall r,
+ 4 <> ireg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma ireg_not_CV: forall r,
+ 5 <> ireg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma freg_not_pmem: forall r,
+ freg_to_pos r <> pmem.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma freg_not_CN: forall r,
+ 2 <> freg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma freg_not_CZ: forall r,
+ 3 <> freg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma freg_not_CC: forall r,
+ 4 <> freg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma freg_not_CV: forall r,
+ 5 <> freg_to_pos r.
+Proof.
+ intros; destruct r; discriminate.
+Qed.
+
+Lemma sr_ireg_update_both: forall sr rsr r1 rr v
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ (sr <[ ireg_to_pos r1 <- Val (v) ]>) (#rr) =
+ Val (rsr # r1 <- v rr).
+Proof.
+ intros. unfold assign.
+ destruct (PregEq.eq r1 rr); subst.
+ - rewrite Pregmap.gss. simpl. destruct r1; simpl; reflexivity.
+ - rewrite Pregmap.gso; eauto.
+ destruct rr; try congruence.
+ + destruct d as [i|f]; try destruct i as [ir|]; try destruct f; try destruct ir; try rewrite HEQV; destruct r1; simpl; try congruence.
+ + destruct c; destruct r1; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+ + destruct r1; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+Qed.
+
+Lemma sr_freg_update_both: forall sr rsr r1 rr v
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ (sr <[ freg_to_pos r1 <- Val (v) ]>) (#rr) =
+ Val (rsr # r1 <- v rr).
+Proof.
+ intros. unfold assign.
+ destruct (PregEq.eq r1 rr); subst.
+ - rewrite Pregmap.gss. simpl. destruct r1; simpl; reflexivity.
+ - rewrite Pregmap.gso; eauto.
+ destruct rr; try congruence.
+ + destruct d as [i|f]; try destruct i as [ir|]; try destruct f; try destruct ir; try rewrite HEQV; destruct r1; simpl; try congruence.
+ + destruct c; destruct r1; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+ + destruct r1; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+Qed.
+
+Lemma sr_xsp_update_both: forall sr rsr rr v
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ (sr <[ #XSP <- Val (v) ]>) (#rr) =
+ Val (rsr # XSP <- v rr).
+Proof.
+ intros. unfold assign.
+ destruct (PregEq.eq XSP rr); subst.
+ - rewrite Pregmap.gss. simpl. reflexivity.
+ - rewrite Pregmap.gso; eauto.
+ destruct rr; try congruence.
+ + destruct d as [i|f]; try destruct i as [ir|]; try destruct f; try destruct ir; try rewrite HEQV; simpl; try congruence.
+ + destruct c; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+ + simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+Qed.
+
+Lemma sr_pc_update_both: forall sr rsr rr v
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ (sr <[ #PC <- Val (v) ]>) (#rr) =
+ Val (rsr # PC <- v rr).
+Proof.
+ intros. unfold assign.
+ destruct (PregEq.eq PC rr); subst.
+ - rewrite Pregmap.gss. simpl. reflexivity.
+ - rewrite Pregmap.gso; eauto.
+ destruct rr; try congruence.
+ + destruct d as [i|f]; try destruct i as [ir|]; try destruct f; try destruct ir; try rewrite HEQV; simpl; try congruence.
+ + destruct c; simpl; try rewrite <- HEQV; unfold ppos; try congruence.
+Qed.
+
+Lemma sr_gss: forall sr pos v,
+ (sr <[ pos <- v ]>) pos = v.
+Proof.
+ intros. unfold assign.
+ destruct (R.eq_dec pos pos) eqn:REQ; try reflexivity; try congruence.
+Qed.
+
+Lemma sr_update_overwrite: forall sr pos v1 v2,
+ (sr <[ pos <- v1 ]>) <[ pos <- v2 ]> = (sr <[ pos <- v2 ]>).
+Proof.
+ intros.
+ unfold assign. apply functional_extensionality; intros x.
+ destruct (R.eq_dec pos x); reflexivity.
+Qed.
+
+(*Ltac Simplif :=*)
+ (*[>((rewrite nextblock_inv by eauto with asmgen)<]*)
+ (*[>|| (rewrite nextblock_inv1 by eauto with asmgen)<]*)
+ (*((rewrite Pregmap.gss)*)
+ (*[>|| (rewrite nextblock_pc)<]*)
+ (*|| (rewrite Pregmap.gso by eauto with asmgen)*)
+ (*|| (rewrite assign_diff by (auto; try discriminate; try (apply ppos_discr; try discriminate; congruence); try (apply ppos_pmem_discr); *)
+ (*try (apply not_eq_sym; apply ppos_discr; try discriminate; congruence); try (apply not_eq_sym; apply ppos_pmem_discr); auto))*)
+ (*|| (rewrite assign_eq)*)
+ (*); auto with asmgen.*)
+
+(*Ltac Simpl := repeat Simplif.*)
+
+Ltac sr_val_rwrt :=
+ repeat match goal with
+ | [H: forall r: preg, ?sr (# r) = Val (?rsr r) |- _ ]
+ => rewrite H
+ end.
+
+Ltac sr_memstate_rwrt :=
+ repeat match goal with
+ | [H: ?sr pmem = Memstate ?mr |- _ ]
+ => rewrite <- H
+ end.
+
+Ltac replace_ppos :=
+ try erewrite !ireg_pos_ppos;
+ try erewrite !freg_pos_ppos.
+
+Ltac DI0N0 ir0 := destruct ir0; subst; simpl.
+
+Ltac DIRN1 ir := destruct ir as [irrDIRN1|]; subst; try destruct irrDIRN1; simpl.
+
+Ltac DDRM dr :=
+ destruct dr as [irsDDRF|frDDRF];
+ [destruct irsDDRF as [irsDDRF|]
+ | idtac ].
+
+Ltac DDRF dr :=
+ destruct dr as [irsDDRF|frDDRF];
+ [destruct irsDDRF as [irsDDRF|]; [destruct irsDDRF|]
+ | destruct frDDRF].
+
+Ltac DPRF pr :=
+ destruct pr as [drDPRF|crDPRF|];
+ [destruct drDPRF as [irDPRF|frDPRF]; [destruct irDPRF as [irrDPRF|]; [destruct irrDPRF|]
+ | destruct frDPRF]
+ | destruct crDPRF|].
+
+Ltac DPRM pr :=
+ destruct pr as [drDPRF|crDPRF|];
+ [destruct drDPRF as [irDPRF|frDPRF]; [destruct irDPRF |]
+ | destruct crDPRF|].
+
+Ltac DPRI pr :=
+ destruct pr as [drDPRI|crDPRI|];
+ [destruct drDPRI as [irDPRI|frDPRI]; [destruct irDPRI as [irrDPRI|]; [destruct irrDPRI|]|]
+ | idtac
+ | idtac ].
+
+Ltac discriminate_ppos :=
+ try apply ireg_not_pmem;
+ try apply ireg_not_pc;
+ try apply freg_not_pmem;
+ try apply ireg_not_CN;
+ try apply ireg_not_CZ;
+ try apply ireg_not_CC;
+ try apply ireg_not_CV;
+ try apply freg_not_CN;
+ try apply freg_not_CZ;
+ try apply freg_not_CC;
+ try apply freg_not_CV;
+ try(simpl; discriminate).
+
+Ltac replace_pc := try replace (6) with (#PC) by eauto.
+
+Ltac replace_regs_pos sr :=
+ try replace (sr 7) with (sr (ppos XSP)) by eauto;
+ try replace (sr 6) with (sr (ppos PC)) by eauto;
+ try replace (sr 2) with (sr (ppos CN)) by eauto;
+ try replace (sr 3) with (sr (ppos CZ)) by eauto;
+ try replace (sr 4) with (sr (ppos CC)) by eauto;
+ try replace (sr 5) with (sr (ppos CV)) by eauto.
+
+Ltac Simpl_exists sr :=
+ replace_ppos;
+ replace_regs_pos sr;
+ try sr_val_rwrt;
+ try (eexists; split; [| split]); eauto;
+ try (sr_memstate_rwrt; rewrite assign_diff;
+ try reflexivity;
+ discriminate_ppos
+ ).
+
+Ltac Simpl_rep sr :=
+ replace_ppos;
+ replace_regs_pos sr;
+ try sr_val_rwrt;
+ try (sr_memstate_rwrt; rewrite assign_diff;
+ try reflexivity;
+ discriminate_ppos
+ ).
+
+Ltac Simpl_update :=
+ try eapply sr_ireg_update_both; eauto;
+ try eapply sr_freg_update_both; eauto;
+ try eapply sr_xsp_update_both; eauto;
+ try eapply sr_pc_update_both; eauto.
+
+Ltac Simpl sr := Simpl_exists sr; intros rr; try rewrite sr_update_overwrite; replace_regs_pos sr; DPRM rr; Simpl_update.
+
+Ltac destruct_res_flag rsr := try (rewrite Pregmap.gso; discriminate_ppos); destruct (rsr _); simpl; try reflexivity.
+
+Ltac discriminate_preg_flags := rewrite !assign_diff; try rewrite !Pregmap.gso; discriminate_ppos; sr_val_rwrt; reflexivity.
+
+Ltac validate_crbit_flags c :=
+ destruct c;
+ [
+ do 3 (rewrite assign_diff; discriminate_ppos);
+ do 3 (rewrite Pregmap.gso; try discriminate);
+ rewrite sr_gss; rewrite Pregmap.gss; reflexivity |
+ do 2 (rewrite assign_diff; discriminate_ppos);
+ do 2 (rewrite Pregmap.gso; try discriminate);
+ rewrite sr_gss; rewrite Pregmap.gss; reflexivity |
+ do 1 (rewrite assign_diff; discriminate_ppos);
+ do 1 (rewrite Pregmap.gso; try discriminate);
+ rewrite sr_gss; rewrite Pregmap.gss; reflexivity |
+ rewrite sr_gss; rewrite Pregmap.gss; reflexivity
+ ].
+
+
+Lemma reg_update_overwrite: forall rsr sr r rd v1 v2
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((sr <[ # rd <- Val (v1) ]>) <[ # rd <- Val (v2) ]>) (# r) =
+ Val ((rsr # rd <- v1) # rd <- v2 r).
+Proof.
+ intros.
+ unfold Pregmap.set; destruct (PregEq.eq r rd).
+ - rewrite e; apply sr_gss; reflexivity.
+ - rewrite sr_update_overwrite. rewrite assign_diff; eauto.
+ unfold not; intros. apply ppos_equal in H. congruence.
+Qed.
+
+Lemma compare_single_res_aux: forall sr mr rsr rr
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_single Vundef Vundef)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_single Vundef Vundef)) ]>) <[ 4 <-
+ Val (_CC (v_compare_single Vundef Vundef)) ]>) <[ 5 <-
+ Val (_CV (v_compare_single Vundef Vundef)) ]>) (# rr) =
+Val
+ ((compare_single rsr Vundef Vundef) rr).
+Proof.
+ intros. unfold v_compare_single, compare_single.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_single_res: forall sr mr rsr rr v1 v2
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_single v1 v2)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_single v1 v2)) ]>) <[ 4 <-
+ Val (_CC (v_compare_single v1 v2)) ]>) <[ 5 <-
+ Val (_CV (v_compare_single v1 v2)) ]>) (# rr) =
+Val
+ ((compare_single rsr v1 v2) rr).
+Proof.
+ intros.
+ destruct v1; destruct v2;
+ try eapply compare_single_res_aux; eauto.
+ unfold v_compare_single, compare_single.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_float_res_aux: forall sr mr rsr rr
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_float Vundef Vundef)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_float Vundef Vundef)) ]>) <[ 4 <-
+ Val (_CC (v_compare_float Vundef Vundef)) ]>) <[ 5 <-
+ Val (_CV (v_compare_float Vundef Vundef)) ]>) (# rr) =
+Val
+ ((compare_float rsr Vundef Vundef) rr).
+Proof.
+ intros. unfold v_compare_float, compare_float.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_float_res: forall sr mr rsr rr v1 v2
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_float v1 v2)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_float v1 v2)) ]>) <[ 4 <-
+ Val (_CC (v_compare_float v1 v2)) ]>) <[ 5 <-
+ Val (_CV (v_compare_float v1 v2)) ]>) (# rr) =
+Val
+ ((compare_float rsr v1 v2) rr).
+Proof.
+ intros.
+ destruct v1; destruct v2;
+ try eapply compare_float_res_aux; eauto.
+ unfold v_compare_float, compare_float.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_long_res_aux: forall sr mr rsr rr
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_long Vundef Vundef)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_long Vundef Vundef)) ]>) <[ 4 <-
+ Val (_CC (v_compare_long Vundef Vundef)) ]>) <[ 5 <-
+ Val (_CV (v_compare_long Vundef Vundef)) ]>) (# rr) =
+Val
+ ((compare_long rsr Vundef Vundef) rr).
+Proof.
+ intros. unfold v_compare_long, compare_long.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_long_res: forall sr mr rsr rr v1 v2
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_long v1 v2)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_long v1 v2)) ]>) <[ 4 <-
+ Val (_CC (v_compare_long v1 v2)) ]>) <[ 5 <-
+ Val (_CV (v_compare_long v1 v2)) ]>) (# rr) =
+Val
+ ((compare_long rsr v1 v2) rr).
+Proof.
+ intros.
+ destruct v1; destruct v2;
+ try eapply compare_long_res_aux; eauto;
+ unfold v_compare_long, compare_long;
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_int_res_aux: forall sr mr rsr rr
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_int Vundef Vundef)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_int Vundef Vundef)) ]>) <[ 4 <-
+ Val (_CC (v_compare_int Vundef Vundef)) ]>) <[ 5 <-
+ Val (_CV (v_compare_int Vundef Vundef)) ]>) (# rr) =
+Val
+ ((compare_int rsr Vundef Vundef) rr).
+Proof.
+ intros. unfold v_compare_int, compare_int.
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+Lemma compare_int_res: forall sr mr rsr rr v1 v2
+ (HMEM: sr pmem = Memstate mr)
+ (HEQV: forall r : preg, sr (# r) = Val (rsr r)),
+ ((((sr <[ 2 <- Val (_CN (v_compare_int v1 v2)) ]>) <[ 3 <-
+ Val (_CZ (v_compare_int v1 v2)) ]>) <[ 4 <-
+ Val (_CC (v_compare_int v1 v2)) ]>) <[ 5 <-
+ Val (_CV (v_compare_int v1 v2)) ]>) (# rr) =
+Val
+ ((compare_int rsr v1 v2) rr).
+Proof.
+ intros.
+ destruct v1; destruct v2;
+ try eapply compare_int_res_aux; eauto;
+ unfold v_compare_int, compare_int;
+ (destruct rr;
+ [ DDRF d; discriminate_preg_flags |
+ validate_crbit_flags c |
+ discriminate_preg_flags ]).
+Qed.
+
+(** Parallelizability test of a bblock (bundle), and bisimulation of the Asmblock and L parallel semantics *)
+
+(*Module PChk := ParallelChecks L PosPseudoRegSet.*)
+
+(*Definition bblock_para_check (p: Asmvliw.bblock) : bool :=*)
+ (*PChk.is_parallelizable (trans_block p).*)
+
+Section SECT_SEQ.
+
+(*Import PChk.*)
+
+(*Arguments Pos.add: simpl never.*)
+(*Arguments ppos: simpl never.*)
+
+Variable Ge: genv.
+
+Lemma trans_arith_correct rsr mr sr rsw' old i:
+ (*Ge = Genv ge fn ->*)
+ (*match_states (State rs m) m' ->*)
+ (*exists em,*)
+ (*L.inst_run Ge (trans_arith o) m' old = Some em /\ match_states .*)
+ match_states (State rsr mr) sr ->
+ (*match_states (State rsw mw) sw ->*)
+ exec_arith_instr Ge.(_lk) i rsr = rsw' ->
+ exists sw,
+ inst_run Ge (trans_arith i) sr old = Some sw
+ /\ match_states (State rsw' mr) sw.
+Proof.
+ induction i.
+ all: intros MS EARITH; subst; inv MS; unfold exec_arith_instr.
+ - (* PArithP *)
+ DIRN1 rd; Simpl sr.
+ - (* PArithPP *)
+ DIRN1 rs; DIRN1 rd; Simpl sr.
+ - (* PArithPPP *)
+ DIRN1 r1; DIRN1 r2; DIRN1 rd; Simpl sr.
+ - (* PArithRR0R *)
+ simpl. destruct r1.
+ + (* OArithRR0R *) simpl; Simpl sr.
+ + (* OArithRR0R_XZR *) simpl; destruct (arith_rr0r_isize _); Simpl sr.
+ - (* PArithRR0 *)
+ simpl. destruct r1.
+ + (* OArithRR0 *) simpl; Simpl sr.
+ + (* OArithRR0_XZR *) simpl; destruct (arith_rr0_isize _); Simpl sr.
+ - (* PArithARRRR0 *)
+ simpl. destruct r3.
+ + (* OArithARRRR0 *) simpl; Simpl sr.
+ + (* OArithARRRR0_XZR *) simpl; destruct (arith_arrrr0_isize _); Simpl sr.
+ - (* PArithComparisonPP *)
+ DIRN1 r2; DIRN1 r1; destruct i;
+ repeat Simpl_rep sr; Simpl_exists sr;
+ unfold arith_eval_comparison_pp; destruct arith_prepare_comparison_pp;
+ simpl; intros rr; try destruct sz;
+ try (eapply compare_single_res; eauto);
+ try (eapply compare_long_res; eauto);
+ try (eapply compare_float_res; eauto).
+ - (* PArithComparisonR0R *)
+ simpl. destruct r1; (
+ simpl; destruct i;
+ repeat Simpl_rep sr; Simpl_exists sr;
+ unfold arith_eval_comparison_r0r, arith_comparison_r0r_isize; destruct arith_prepare_comparison_r0r; destruct is;
+ simpl; intros rr; try destruct sz;
+ try (eapply compare_long_res; eauto);
+ try (eapply compare_int_res; eauto)).
+ - (* PArithComparisonP *)
+ DIRN1 r1; destruct i;
+ repeat Simpl_rep sr; Simpl_exists sr;
+ unfold arith_eval_comparison_p; destruct arith_prepare_comparison_p;
+ simpl; try intros rr; try destruct sz;
+ try (eapply compare_single_res; eauto);
+ try (eapply compare_long_res; eauto);
+ try (eapply compare_int_res; eauto);
+ try (eapply compare_float_res; eauto).
+ - (* Pcset *)
+ simpl; (*DI0N0 rd.*) unfold eval_testcond, get_testcond_rlocs, cflags_eval;
+ unfold cond_eval_is; unfold flags_testcond_value, list_exp_eval; destruct c; simpl;
+ repeat Simpl_rep sr; Simpl_exists sr;
+ destruct_res_flag rsr;
+ Simpl sr.
+ - (* Pfmovi *)
+ simpl; destruct r1; simpl; destruct fsz; Simpl sr.
+ - (* Pcsel *)
+ simpl.
+ unfold eval_testcond, cflags_eval. DIRN1 r1; DIRN1 r2; destruct c; simpl;
+ repeat Simpl_rep sr;
+ (eexists; split; [| split]; [reflexivity | DDRM rd; Simpl_exists sr | idtac]).
+ all: intros rr; destruct (PregEq.eq rr rd);
+ [ subst; erewrite Pregmap.gss; erewrite sr_gss; reflexivity |
+ try erewrite Pregmap.gso; try erewrite assign_diff; try rewrite H0; try fold (ppos rd); try eapply ppos_discr; eauto ].
+ - (* Pfnmul *)
+ simpl; destruct fsz; Simpl sr.
+Qed.
+
+Lemma sp_xsp:
+ SP = XSP.
+Proof.
+ econstructor.
+Qed.
+
+Theorem bisimu_basic rsr mr sr bi:
+ match_states (State rsr mr) sr ->
+ match_outcome (exec_basic Ge.(_lk) Ge.(_genv) bi rsr mr) (inst_run Ge (trans_basic bi) sr sr).
+Proof.
+
+(* a little tactic to automate reasoning on preg_eq *)
+Local Hint Resolve not_eq_sym ppos_pmem_discr ppos_discr: core.
+Local Ltac preg_eq_discr r rd :=
+ destruct (preg_eq r rd); try (subst r; rewrite assign_eq, Pregmap.gss; auto);
+ rewrite (assign_diff _ (#rd) (#r) _); auto;
+ rewrite Pregmap.gso; auto.
+
+ intros MS; inversion MS as (H & H0).
+ destruct bi; simpl.
+ (* Loadsymbol / Cvtsw2x / Cvtuw2x / Cvtx2w *)
+ 6,7,8,9: Simpl sr.
+ - (* Arith *)
+ exploit trans_arith_correct; eauto.
+ - (* Load *)
+ unfold exec_load, eval_addressing_rlocs_ld, exp_eval;
+ destruct a; simpl; try destruct base; Simpl_exists sr; erewrite H;
+ unfold exec_load1, exec_load2, exec_loadU; unfold call_ll_loadv;
+ try destruct (Mem.loadv _ _ _); simpl; auto.
+ all: eexists; split; [| split]; [ eauto | DDRF rd; eauto | idtac ];
+ intros rr; destruct (PregEq.eq rr rd); subst; [ rewrite Pregmap.gss; rewrite sr_gss; reflexivity |
+ rewrite assign_diff; try rewrite Pregmap.gso;
+ try rewrite H0; try (fold (ppos rd); eapply ppos_discr); auto].
+ - (* Store *)
+ unfold exec_store, eval_addressing_rlocs_st, exp_eval;
+ destruct a; simpl; DIRN1 r; try destruct base; Simpl_exists sr; erewrite H;
+ unfold exec_store1, exec_store2, exec_storeU; unfold call_ll_storev;
+ try destruct (Mem.storev _ _ _ _); simpl; auto.
+ all: eexists; split; [| split]; [ eauto | eauto |
+ intros rr; rewrite assign_diff; [ rewrite H0; auto | apply ppos_pmem_discr ]].
+ - (* Alloc *)
+ destruct (Mem.alloc _ _ _) eqn:MEMAL. destruct (Mem.store _ _ _ _) eqn:MEMS.
+ + eexists; repeat split.
+ * rewrite !assign_diff; try discriminate_ppos; Simpl_exists sr;
+ rewrite H; destruct (Mem.alloc _ _ _) eqn:MEMAL2;
+ injection MEMAL; intros Hm Hb; try rewrite Hm, Hb;
+ rewrite sp_xsp in MEMS; rewrite MEMS.
+ rewrite !assign_diff; try discriminate_ppos; Simpl_exists sr; rewrite H;
+ destruct (Mem.alloc _ _ _) eqn:MEMAL3;
+ injection MEMAL2; intros Hm2 Hb2; try rewrite Hm2, Hb2;
+ rewrite Hm, Hb; rewrite MEMS; reflexivity.
+ * eauto.
+ * intros rr; DPRF rr; repeat Simpl_exists sr.
+ + simpl; repeat Simpl_exists sr. erewrite H. destruct (Mem.alloc _ _ _) eqn:HMEMAL2.
+ injection MEMAL; intros Hm Hb.
+ try rewrite Hm, Hb; clear Hm Hb.
+ try rewrite sp_xsp in MEMS; rewrite MEMS. reflexivity.
+ - (* Free *)
+ destruct (Mem.loadv _ _ _) eqn:MLOAD; simpl; auto;
+ repeat Simpl_exists sr; rewrite H; simpl.
+ + destruct (rsr SP) eqn:EQSP; simpl; rewrite <- sp_xsp; rewrite EQSP; rewrite MLOAD; try reflexivity.
+ destruct (Mem.free _ _ _) eqn:EQFREE; try reflexivity. rewrite assign_diff; discriminate_ppos.
+ replace_regs_pos sr; sr_val_rwrt. rewrite <- sp_xsp; rewrite EQSP; rewrite MLOAD. rewrite EQFREE.
+ Simpl_exists sr. intros rr; DPRF rr; repeat Simpl_exists sr.
+ + rewrite <- sp_xsp; rewrite MLOAD; reflexivity.
+Qed.
+
+Theorem bisimu_body:
+ forall bdy rsr mr sr,
+ match_states (State rsr mr) sr ->
+ match_outcome (exec_body Ge.(_lk) Ge.(_genv) bdy rsr mr) (exec Ge (trans_body bdy) sr).
+Proof.
+ induction bdy as [|i bdy]; simpl; eauto.
+ intros.
+ exploit (bisimu_basic rsr mr sr i); eauto.
+ destruct (exec_basic _ _ _ _ _); simpl.
+ - intros (s' & X1 & X2).
+ rewrite X1; simpl; eauto. eapply IHbdy; eauto; simpl.
+ unfold match_states in *. destruct s. unfold Asm._m. eauto.
+ - intros X; rewrite X; simpl; auto.
+Qed.
+
+Theorem bisimu_control ex sz rsr mr sr:
+ match_states (State rsr mr) sr ->
+ match_outcome (exec_cfi Ge.(_genv) Ge.(_fn) ex (incrPC (Ptrofs.repr sz) rsr) mr) (inst_run Ge (trans_pcincr sz (trans_exit (Some (PCtlFlow ex)))) sr sr).
+Proof.
+ intros MS.
+ simpl in *. inv MS.
+ destruct ex.
+ (* Obr / Oret *)
+ 6,7: unfold control_eval, incrPC; simpl; destruct Ge;
+ replace_pc; rewrite (H0 PC);
+ repeat Simpl_rep sr; Simpl_exists sr;
+ intros rr; destruct (preg_eq rr PC); [
+ rewrite e; rewrite sr_gss; rewrite Pregmap.gss;
+ try rewrite Pregmap.gso; discriminate_ppos; fold (ppos r); auto |
+ repeat Simpl_rep sr; try rewrite !Pregmap.gso; auto; apply ppos_discr in n; auto ].
+ (* Ocbnz / Ocbz *)
+ 6,7,8,9: unfold control_eval; destruct Ge; simpl;
+ replace_pc; rewrite (H0 PC);
+ unfold eval_branch, eval_neg_branch, eval_testzero, eval_testbit,
+ incrPC, goto_label_deps, goto_label;
+ destruct (PregEq.eq r PC);
+ [ rewrite e; destruct sz0; simpl; Simpl sr |
+ destruct sz0; simpl; replace_pc; rewrite Pregmap.gso; auto; repeat Simpl_rep sr; try rewrite H0;
+ try (destruct (Val_cmpu_bool _ _ _) eqn:EQCMP; try reflexivity; destruct b);
+ try (destruct (Val_cmplu_bool _ _ _) eqn:EQCMP; try reflexivity; destruct b);
+ try (destruct (Val.cmp_bool _ _ _) eqn:EQCMP; try reflexivity; destruct b);
+ try (destruct (Val.cmpl_bool _ _ _) eqn:EQCMP; try reflexivity; destruct b);
+ try (Simpl_exists sr; intros rr; destruct (PregEq.eq rr PC); subst;
+ [ rewrite sr_gss, Pregmap.gss; reflexivity | rewrite !assign_diff, Pregmap.gso; auto ]);
+ try (destruct (label_pos _ _ _); try reflexivity; rewrite Pregmap.gss;
+ destruct Val.offset_ptr; try reflexivity; Simpl_exists sr;
+ intros rr; destruct (PregEq.eq rr PC); subst;
+ [ rewrite sr_gss, Pregmap.gss; reflexivity | rewrite !assign_diff, Pregmap.gso; auto ];
+ rewrite Pregmap.gso; auto)].
+ - (* Ob *)
+ replace_pc. rewrite (H0 PC). simpl.
+ unfold goto_label, control_eval. destruct Ge.
+ unfold goto_label_deps. destruct (label_pos _ _ _); auto.
+ + unfold incrPC. rewrite Pregmap.gss; eauto. destruct (Val.offset_ptr _ _); auto;
+ try (rewrite sr_gss; unfold Stuck; reflexivity).
+ simpl. eexists; split; split.
+ * rewrite sr_update_overwrite. unfold pmem, assign in *. simpl. rewrite H; reflexivity.
+ * intros. rewrite sr_update_overwrite. unfold Pregmap.set, assign.
+ destruct r as [dr|cr|]; try destruct dr as [ir|fr]; try destruct ir as [irr|];
+ try destruct irr; try destruct fr; try destruct cr; simpl; try rewrite <- H0; eauto.
+ + rewrite sr_gss; reflexivity.
+ - (* Obc *)
+ replace_pc. rewrite (H0 PC). simpl.
+ unfold eval_branch, goto_label, control_eval. destruct Ge.
+ unfold goto_label_deps, cflags_eval, eval_testcond, list_exp_eval.
+ destruct c; simpl; unfold incrPC;
+ repeat (replace_ppos; replace_pc; replace_regs_pos sr; sr_val_rwrt; try rewrite !assign_diff; discriminate_ppos).
+ 1,2,3,4,5,6: destruct_res_flag rsr.
+ 7,8,9,10: do 2 (destruct_res_flag rsr).
+ 11,12 : do 3 (destruct_res_flag rsr).
+ 1,2,3,4,5,6,9,10: destruct (Int.eq _ _); [| Simpl sr ];
+ destruct (label_pos _ _ _); [| reflexivity]; replace_pc;
+ rewrite !Pregmap.gss; destruct Val.offset_ptr;
+ try (unfold Stuck; reflexivity); Simpl_exists sr; intros rr;
+ apply reg_update_overwrite; eauto.
+ 1,3: destruct (andb); [| Simpl sr ];
+ destruct (label_pos _ _ _); [| reflexivity]; replace_pc; rewrite !Pregmap.gss;
+ destruct Val.offset_ptr; try (unfold Stuck; reflexivity); Simpl_exists sr;
+ intros rr; apply reg_update_overwrite; eauto.
+ 1,2: destruct (orb); [| Simpl sr ];
+ destruct (label_pos _ _ _); [| reflexivity]; replace_pc; rewrite !Pregmap.gss;
+ destruct Val.offset_ptr; try (unfold Stuck; reflexivity); Simpl_exists sr;
+ intros rr; apply reg_update_overwrite; eauto.
+ - (* Obl *)
+ replace_pc. rewrite (H0 PC). simpl.
+ unfold control_eval. destruct Ge.
+ rewrite sr_gss.
+ repeat Simpl_rep sr. Simpl_exists sr.
+ Simpl sr.
+ all: repeat (intros; replace_regs_pos sr; try replace (38) with (#X30) by eauto; unfold incrPC; Simpl_update).
+ - (* Obs *)
+ unfold control_eval. destruct Ge. replace_pc. rewrite (H0 PC). simpl; unfold incrPC.
+ replace_pc; Simpl_exists sr; intros rr; apply reg_update_overwrite; eauto.
+ - (* Oblr *)
+ replace_pc. rewrite (H0 PC).
+ unfold control_eval. destruct Ge. simpl. unfold incrPC.
+ try (eexists; split; [ | split ]); eauto.
+ intros rr; DPRF rr; Simpl_update.
+ 68: rewrite sr_gss, Pregmap.gss;
+ try rewrite Pregmap.gso; discriminate_ppos; fold (ppos r); rewrite H0; auto.
+ all: repeat Simpl_rep sr; rewrite !Pregmap.gso; discriminate_ppos; auto.
+ - (* Obtbl *)
+ replace_pc. rewrite (H0 PC).
+ unfold control_eval. destruct Ge. simpl. unfold incrPC.
+ destruct r1.
+ 17: rewrite Pregmap.gss, sr_gss; try reflexivity.
+ all: rewrite !Pregmap.gso, !assign_diff; discriminate_ppos;
+ rewrite ireg_pos_ppos; try erewrite H0; destruct (rsr _);
+ try destruct (list_nth_z _ _); try reflexivity;
+ unfold goto_label, goto_label_deps; destruct (label_pos _ _ _);
+ try rewrite 2Pregmap.gso, Pregmap.gss; destruct (Val.offset_ptr (rsr PC) (Ptrofs.repr sz));
+ try reflexivity; discriminate_ppos; simpl; Simpl_exists sr;
+ intros rr;
+ destruct (PregEq.eq X16 rr); [ subst; Simpl_update |];
+ destruct (PregEq.eq X17 rr); [ subst; Simpl_update |];
+ destruct (PregEq.eq PC rr); [ subst; Simpl_update |];
+ rewrite !Pregmap.gso; auto; apply ppos_discr in n; apply ppos_discr in n0; apply ppos_discr in n1;
+ simpl in *;repeat Simpl_rep sr; auto.
+Qed.
+
+Theorem bisimu_exit ex sz rsr mr sr:
+ match_states (State rsr mr) sr ->
+ match_outcome (estep Ge.(_genv) Ge.(_fn) ex (Ptrofs.repr sz) rsr mr) (inst_run Ge (trans_pcincr sz (trans_exit (Some (PCtlFlow ex)))) sr sr).
+Proof.
+ intros; unfold estep.
+ exploit (bisimu_control ex sz rsr mr sr); eauto.
+Qed.
+
+Definition trans_block_aux bdy sz ex := (trans_body bdy) ++ (trans_pcincr sz (trans_exit ex) :: nil).
+
+Theorem bisimu rsr mr sr bdy ex sz:
+ match_states (State rsr mr) sr ->
+ match_outcome (bbstep Ge.(_lk) Ge.(_genv) Ge.(_fn) ex (Ptrofs.repr sz) bdy rsr mr) (run Ge (trans_block_aux bdy sz (Some (PCtlFlow ex))) sr).
+Proof.
+ intros MS. unfold bbstep, trans_block_aux.
+ exploit (bisimu_body bdy rsr mr sr); eauto.
+ destruct (exec_body _ _ _ _ _); simpl.
+ - unfold match_states in *. intros (s' & X1 & X2). destruct s.
+ erewrite run_app_Some; eauto.
+ exploit (bisimu_exit ex sz _rs _m s'); eauto.
+ destruct Ge; simpl. destruct MS as (Y1 & Y2). destruct X2 as (X2 & X3).
+ replace_pc. erewrite !X3; simpl.
+ destruct (inst_run _ _ _ _); simpl; auto.
+ - intros X; erewrite run_app_None; eauto.
+Qed.
+
+(* TODO We should use this version, but our current definitions
+does not match
+Theorem bisimu rsr mr b sr ex sz:
+ match_states (State rsr mr) sr ->
+ match_outcome (bbstep Ge.(_lk) Ge.(_genv) Ge.(_fn) ex (Ptrofs.repr sz) (body b) rsr mr) (exec Ge (trans_block b) sr).
+Proof.
+
+ intros MS. unfold bbstep.
+ exploit (bisimu_body (body b) rsr mr sr); eauto.
+ unfold exec, trans_block; simpl.
+ destruct (exec_body _ _ _ _); simpl.
+ - unfold match_states in *. intros (s' & X1 & X2). destruct s.
+ erewrite run_app_Some; eauto.
+ exploit (bisimu_exit ex sz _rs _m s' s'); eauto.
+ destruct Ge; simpl. destruct X2 as (X2 & X3). destruct MS as (Y1 & Y2).
+ replace (6) with (#PC) by auto. erewrite X3; simpl.
+ unfold trans_exit.
+ destruct (inst_run _ _ _); simpl; auto.
+ - intros X; erewrite run_app_None; eauto.
+
+ intros MS. unfold bbstep, trans_block.
+ exploit (bisimu_body (body b) rsr mr sr); eauto.
+ destruct (exec_body _ _ _ _ _); simpl.
+ - unfold match_states in *. intros (s' & X1 & X2). destruct s.
+ erewrite run_app_Some; eauto.
+ exploit (bisimu_exit ex sz _rs _m s' s'); eauto.
+ destruct Ge; simpl. destruct MS as (Y1 & Y2). destruct X2 as (X2 & X3).
+ replace (6) with (#PC) by auto. erewrite !X3; simpl.
+ destruct (inst_run _ _ _ _); simpl; auto.
+ - intros X; erewrite run_app_None; eauto.
+Qed.*)
+
+(*Theorem bisimu_bblock rsr mr sr bdy1 bdy2 ex sz:*)
+ (*match_states (State rsr mr) sr ->*)
+ (*match_outcome *)
+ (*match bbstep Ge.(_lk) Ge.(_genv) Ge.(_fn) ex (Ptrofs.repr sz) bdy1 rsr mr with*)
+ (*| Some (State rs' m') => exec_body Ge.(_lk) Ge.(_genv) bdy2 rs' m'*)
+ (*| Stuck => Stuck*)
+ (*end*)
+ (*(run Ge ((trans_block_aux bdy1 sz (Some (PCtlFlow (ex))))++(trans_body bdy2)) sr).*)
+(*Proof.*)
+ (*intros.*)
+ (*exploit (bisimu rsr mr sr bdy1 ex sz); eauto.*)
+ (*destruct (bbstep _ _ _ _ _ _); simpl.*)
+ (*- intros (s' & X1 & X2).*)
+ (*erewrite run_app_Some; eauto. destruct s.*)
+ (*eapply bisimu_body; eauto.*)
+ (*- intros; erewrite run_app_None; eauto.*)
+(*Qed.*)
+
+(*Lemma trans_body_perserves_permutation bdy1 bdy2:*)
+ (*Permutation bdy1 bdy2 ->*)
+ (*Permutation (trans_body bdy1) (trans_body bdy2).*)
+(*Proof.*)
+ (*induction 1; simpl; econstructor; eauto.*)
+(*Qed.*)
+(*
+Lemma trans_body_app bdy1: forall bdy2,
+ trans_body (bdy1++bdy2) = (trans_body bdy1) ++ (trans_body bdy2).
+Proof.
+ induction bdy1; simpl; congruence.
+Qed.
+*)
+(*Theorem trans_block_perserves_permutation bdy1 bdy2 b:*)
+ (*Permutation (bdy1 ++ bdy2) (body b) ->*)
+ (*Permutation (trans_block b) ((trans_block_aux bdy1 (size b) (exit b))++(trans_body bdy2)).*)
+(*Proof.*)
+ (*intro H; unfold trans_block, trans_block_aux.*)
+ (*eapply perm_trans.*)
+ (*- eapply Permutation_app_tail. *)
+ (*apply trans_body_perserves_permutation.*)
+ (*apply Permutation_sym; eapply H.*)
+ (*- rewrite trans_body_app. rewrite <-! app_assoc.*)
+ (*apply Permutation_app_head.*)
+ (*apply Permutation_app_comm.*)
+(*Qed.*)
+
+(*Theorem bisimu_par rs1 m1 s1' b ge fn o2:*)
+ (*Ge = Genv ge fn ->*)
+ (*match_states (State rs1 m1) s1' -> *)
+ (*parexec_bblock ge fn b rs1 m1 o2 ->*)
+ (*exists o2',*)
+ (*prun Ge (trans_block b) s1' o2'*)
+ (*/\ match_outcome o2 o2'.*)
+(*Proof.*)
+ (*intros GENV MS PAREXEC.*)
+ (*inversion PAREXEC as (bdy1 & bdy2 & PERM & WIO).*)
+ (*exploit trans_block_perserves_permutation; eauto.*)
+ (*intros Perm.*)
+ (*exploit (bisimu_par_wio_bblock ge fn rs1 m1 s1' bdy1 bdy2 (exit b) (size b)); eauto.*)
+ (*rewrite <- WIO. clear WIO.*)
+ (*intros H; eexists; split. 2: eapply H.*)
+ (*unfold prun; eexists; split; eauto. *)
+ (*destruct (prun_iw _ _ _ _); simpl; eauto.*)
+(*Qed.*)
+
+(** sequential execution *)
+(*Theorem bisimu_basic ge fn bi rs m s:*)
+ (*Ge = Genv ge fn ->*)
+ (*match_states (State rs m) s ->*)
+ (*match_outcome (exec_basic_instr ge bi rs m) (inst_run Ge (trans_basic bi) s s).*)
+(*Proof.*)
+ (*intros; unfold exec_basic_instr. rewrite inst_run_prun.*)
+ (*eapply bisimu_par_wio_basic; eauto.*)
+(*Qed.*)
+
+(*Lemma bisimu_body:*)
+ (*forall bdy ge fn rs m s,*)
+ (*Ge = Genv ge fn ->*)
+ (*match_states (State rs m) s ->*)
+ (*match_outcome (exec_body ge bdy rs m) (exec Ge (trans_body bdy) s).*)
+(*Proof.*)
+ (*induction bdy as [|i bdy]; simpl; eauto. *)
+ (*intros.*)
+ (*exploit (bisimu_basic ge fn i rs m s); eauto.*)
+ (*destruct (exec_basic_instr _ _ _ _); simpl.*)
+ (*- intros (s' & X1 & X2). rewrite X1; simpl; eauto.*)
+ (*- intros X; rewrite X; simpl; auto.*)
+(*Qed.*)
+
+(*Theorem bisimu_exit ge fn b rs m s:*)
+ (*Ge = Genv ge fn ->*)
+ (*match_states (State rs m) s ->*)
+ (*match_outcome (exec_control ge fn (exit b) (nextblock b rs) m) (inst_run Ge (trans_pcincr (size b) (trans_exit (exit b))) s s).*)
+(*Proof.*)
+ (*intros; unfold exec_control, nextblock. rewrite inst_run_prun. *)
+ (*apply (bisimu_par_control (exit b) (size b) (Val.offset_ptr (rs PC) (Ptrofs.repr (size b))) ge fn rs rs m m s s); auto.*)
+(*Qed.*)
+
+(*Lemma bbstep_is_exec_bblock: forall bb (cfi: cf_instruction) size_bb bdy rs m rs' m' t,*)
+ (*(body bb) = bdy ->*)
+ (*(exit bb) = Some (PCtlFlow cfi) ->*)
+ (*Ptrofs.repr (size bb) = size_bb ->*)
+ (*exec_bblock Ge.(_lk) Ge.(_genv) Ge.(_fn) bb rs m t rs' m'*)
+ (*<-> (bbstep Ge.(_lk) Ge.(_genv) Ge.(_fn) (cfi) size_bb bdy rs m = Next rs' m' /\ t = E0).*)
+(*Proof.*)
+ (*intros.*)
+(*Admitted.*)
+
+(* TODO This is the lemma we should use if we want to modelize
+builtins in our scheduling process.
+If we do not modelize builtins, we could use a simpler definition (trace E0) *)
+(*
+Theorem bisimu' rs m rs' m' bb s:
+ match_states (State rs m) s ->
+ (exists t, exec_bblock Ge.(_lk) Ge.(_genv) Ge.(_fn) bb rs m t rs' m')
+ <-> (exists s', (exec Ge (trans_block bb) s) = Some s' /\ match_states (State rs' m') s').
+Proof.
+ intros MS.
+ destruct (exit bb) eqn:EQEXIT.
+ destruct c eqn:EQC.
+ - split.
+ + intros (t & H).
+ rewrite bbstep_is_exec_bblock in H; eauto.
+ eexists; split. destruct H as [H0 H1].
+ generalize (bisimu )
+ unfold exec_bblock.
+ exploit (bisimu_body (body b) ge fn rs m s); eauto.
+ unfold exec, trans_block; simpl.
+ destruct (exec_body _ _ _ _); simpl.
+ - intros (s' & X1 & X2).
+ erewrite run_app_Some; eauto.
+ exploit (bisimu_exit ge fn b rs0 m0 s'); eauto.
+ subst Ge; simpl. destruct X2 as (Y1 & Y2). erewrite Y2; simpl.
+ destruct (inst_run _ _ _); simpl; auto.
+ - intros X; erewrite run_app_None; eauto.
+Qed.*)
+
+Theorem trans_state_match: forall S, match_states S (trans_state S).
+Proof.
+ intros. destruct S as (rs & m). simpl.
+ split. reflexivity.
+ intro. destruct r as [dr|cr|]; try destruct dr as [ir|fr]; try destruct cr;
+ try destruct ir as [irr|]; try destruct irr; try destruct fr; try reflexivity.
+Qed.
+
+Lemma state_eq_decomp:
+ forall rs1 m1 rs2 m2, rs1 = rs2 -> m1 = m2 -> State rs1 m1 = State rs2 m2.
+Proof.
+ intros. congruence.
+Qed.
+
+Theorem state_equiv S1 S2 S': match_states S1 S' -> match_states S2 S' -> S1 = S2.
+Proof.
+ unfold match_states; intros H0 H1. destruct S1 as (rs1 & m1). destruct S2 as (rs2 & m2). inv H0. inv H1.
+ apply state_eq_decomp.
+ - apply functional_extensionality. intros. assert (Val (rs1 x) = Val (rs2 x)) by congruence. congruence.
+ - congruence.
+Qed.
+
+(*Lemma bblock_para_check_correct ge fn bb rs m rs' m':*)
+ (*Ge = Genv ge fn ->*)
+ (*exec_bblock ge fn bb rs m = Next rs' m' ->*)
+ (*bblock_para_check bb = true ->*)
+ (*det_parexec ge fn bb rs m rs' m'.*)
+(*Proof.*)
+ (*intros H H0 H1 o H2. unfold bblock_para_check in H1.*)
+ (*exploit (bisimu rs m bb ge fn); eauto. eapply trans_state_match.*)
+ (*rewrite H0; simpl.*)
+ (*intros (s2' & EXEC & MS).*)
+ (*exploit bisimu_par. 2: apply (trans_state_match (State rs m)). all: eauto.*)
+ (*intros (o2' & PRUN & MO).*)
+ (*exploit parallelizable_correct. apply is_para_correct_aux. eassumption.*)
+ (*intro. eapply H3 in PRUN. clear H3. destruct o2'.*)
+ (*- inv PRUN. inv H3. unfold exec in EXEC; unfold trans_state in H.*)
+ (*assert (x = s2') by congruence. subst. clear H.*)
+ (*assert (m0 = s2') by (apply functional_extensionality; auto). subst. clear H4.*)
+ (*destruct o; try discriminate. inv MO. inv H. assert (s2' = x) by congruence. subst.*)
+ (*exploit (state_equiv (State rs' m') (State rs0 m0)).*)
+ (*2: eapply H4. eapply MS. intro H. inv H. reflexivity.*)
+ (*- unfold match_outcome in MO. destruct o.*)
+ (*+ inv MO. inv H3. discriminate.*)
+ (*+ clear MO. unfold exec in EXEC.*)
+ (*unfold trans_state in PRUN; rewrite EXEC in PRUN. discriminate.*)
+(*Qed.*)
+
+End SECT_SEQ.
+
+Section SECT_BBLOCK_EQUIV.
+
+Variable Ge: genv.
+
+Local Hint Resolve trans_state_match: core.
+
+Lemma bblock_simu_reduce:
+ forall p1 p2,
+ L.bblock_simu Ge (trans_block p1) (trans_block p2) ->
+ (has_builtin p1 = true -> exit p1 = exit p2) ->
+ Asmblockprops.bblock_simu Ge.(_lk) Ge.(_genv) Ge.(_fn) p1 p2.
+Proof.
+ unfold bblock_simu. intros p1 p2 H BLT rs m rs' m' t EBB.
+ generalize (H (trans_state (State rs m))); clear H.
+ intro H. (* TODO How to define this correctly ?
+ exploit (bisimu rs m (body p1) (trans_state (State rs m))); eauto.
+ exploit (bisimu Ge rs m p2 ge fn (trans_state (State rs m))); eauto.
+ destruct (exec_bblock ge fn p1 rs m); try congruence.
+ intros H3 (s2' & exp2 & MS'). unfold exec in exp2, H3. rewrite exp2 in H2.
+ destruct H2 as (m2' & H2 & H4). discriminate. rewrite H2 in H3.
+ destruct (exec_bblock ge fn p2 rs m); simpl in H3.
+ * destruct H3 as (s' & H3 & H5 & H6). inv H3. inv MS'.
+ cutrewrite (rs0=rs1).
+ - cutrewrite (m0=m1); auto. congruence.
+ - apply functional_extensionality. intros r.
+ generalize (H0 r). intros Hr. congruence.
+ * discriminate.
+Qed.*)
+Admitted.
+
+(** Used for debug traces *)
+
+Definition ireg_name (ir: ireg) : pstring :=
+ match ir with
+ | X0 => Str ("X0") | X1 => Str ("X1") | X2 => Str ("X2") | X3 => Str ("X3") | X4 => Str ("X4") | X5 => Str ("X5") | X6 => Str ("X6") | X7 => Str ("X7")
+ | X8 => Str ("X8") | X9 => Str ("X9") | X10 => Str ("X10") | X11 => Str ("X11") | X12 => Str ("X12") | X13 => Str ("X13") | X14 => Str ("X14") | X15 => Str ("X15")
+ | X16 => Str ("X16") | X17 => Str ("X17") | X18 => Str ("X18") | X19 => Str ("X19") | X20 => Str ("X20") | X21 => Str ("X21") | X22 => Str ("X22") | X23 => Str ("X23")
+ | X24 => Str ("X24") | X25 => Str ("X25") | X26 => Str ("X26") | X27 => Str ("X27") | X28 => Str ("X28") | X29 => Str ("X29") | X30 => Str ("X30")
+ end
+.
+
+Definition freg_name (fr: freg) : pstring :=
+ match fr with
+ | D0 => Str ("D0") | D1 => Str ("D1") | D2 => Str ("D2") | D3 => Str ("D3") | D4 => Str ("D4") | D5 => Str ("D5") | D6 => Str ("D6") | D7 => Str ("D7")
+ | D8 => Str ("D8") | D9 => Str ("D9") | D10 => Str ("D10") | D11 => Str ("D11") | D12 => Str ("D12") | D13 => Str ("D13") | D14 => Str ("D14") | D15 => Str ("D15")
+ | D16 => Str ("D16") | D17 => Str ("D17") | D18 => Str ("D18") | D19 => Str ("D19") | D20 => Str ("D20") | D21 => Str ("D21") | D22 => Str ("D22") | D23 => Str ("D23")
+ | D24 => Str ("D24") | D25 => Str ("D25") | D26 => Str ("D26") | D27 => Str ("D27") | D28 => Str ("D28") | D29 => Str ("D29") | D30 => Str ("D30") | D31 => Str ("D31")
+ end
+.
+
+Definition string_of_name (x: P.R.t): ?? pstring :=
+ if (Pos.eqb x pmem) then
+ RET (Str "MEM")
+ else
+ match inv_ppos x with
+ | Some (CR cr) => match cr with
+ | CN => RET (Str ("CN"))
+ | CZ => RET (Str ("CZ"))
+ | CC => RET (Str ("CC"))
+ | CV => RET (Str ("CV"))
+ end
+ | Some (PC) => RET (Str ("PC"))
+ | Some (DR dr) => match dr with
+ | IR ir => match ir with
+ | XSP => RET (Str ("XSP"))
+ | RR1 irr => RET (ireg_name irr)
+ end
+ | FR fr => RET (freg_name fr)
+ end
+ | _ => RET (Str ("UNDEFINED"))
+ end.
+
+Definition string_of_name_ArithP (n: arith_p) : pstring :=
+ match n with
+ | Padrp _ _ => "Padrp"
+ | Pmovz _ _ _ => "Pmov"
+ | Pmovn _ _ _ => "Pmov"
+ | Pfmovimms _ => "Pfmovimm"
+ | Pfmovimmd _ => "Pfmovimm"
+ end.
+
+Definition string_of_name_ArithPP (n: arith_pp) : pstring :=
+ match n with
+ | Pmov => "Pmov"
+ | Pmovk _ _ _ => "Pmovk"
+ | Paddadr _ _ => "Paddadr"
+ | Psbfiz _ _ _ => "Psbfiz"
+ | Psbfx _ _ _ => "Psbfx"
+ | Pubfiz _ _ _ => "Pubfiz"
+ | Pubfx _ _ _ => "Pubfx"
+ | Pfmov => "Pfmov"
+ | Pfcvtds => "Pfcvtds"
+ | Pfcvtsd => "Pfcvtsd"
+ | Pfabs _ => "Pfabs"
+ | Pfneg _ => "Pfneg"
+ | Pscvtf _ _ => "Pscvtf"
+ | Pucvtf _ _ => "Pucvtf"
+ | Pfcvtzs _ _ => "Pfcvtzs"
+ | Pfcvtzu _ _ => "Pfcvtzu"
+ | Paddimm _ _ => "Paddimm"
+ | Psubimm _ _ => "Psubimm"
+ end.
+
+Definition string_of_name_ArithPPP (n: arith_ppp) : pstring :=
+ match n with
+ | Pasrv _ => "Pasrv"
+ | Plslv _ => "Plslv"
+ | Plsrv _ => "Plsrv"
+ | Prorv _ => "Prorv"
+ | Psmulh => "Psmulh"
+ | Pumulh => "Pumulh"
+ | Psdiv _ => "Psdiv"
+ | Pudiv _ => "Pudiv"
+ | Paddext _ => "Paddext"
+ | Psubext _ => "Psubext"
+ | Pfadd _ => "Pfadd"
+ | Pfdiv _ => "Pfdiv"
+ | Pfmul _ => "Pfmul"
+ | Pfsub _ => "Pfsub"
+ end.
+
+Definition string_of_name_ArithRR0R (n: arith_rr0r) : pstring :=
+ match n with
+ | Padd _ _ => "ArithRR0R=>Padd"
+ | Psub _ _ => "ArithRR0R=>Psub"
+ | Pand _ _ => "ArithRR0R=>Pand"
+ | Pbic _ _ => "ArithRR0R=>Pbic"
+ | Peon _ _ => "ArithRR0R=>Peon"
+ | Peor _ _ => "ArithRR0R=>Peor"
+ | Porr _ _ => "ArithRR0R=>Porr"
+ | Porn _ _ => "ArithRR0R=>Porn"
+ end.
+
+Definition string_of_name_ArithRR0R_XZR (n: arith_rr0r) : pstring :=
+ match n with
+ | Padd _ _ => "ArithRR0R_XZR=>Padd"
+ | Psub _ _ => "ArithRR0R_XZR=>Psub"
+ | Pand _ _ => "ArithRR0R_XZR=>Pand"
+ | Pbic _ _ => "ArithRR0R_XZR=>Pbic"
+ | Peon _ _ => "ArithRR0R_XZR=>Peon"
+ | Peor _ _ => "ArithRR0R_XZR=>Peor"
+ | Porr _ _ => "ArithRR0R_XZR=>Porr"
+ | Porn _ _ => "ArithRR0R_XZR=>Porn"
+ end.
+
+Definition string_of_name_ArithRR0 (n: arith_rr0) : pstring :=
+ match n with
+ | Pandimm _ _ => "ArithRR0=>Pandimm"
+ | Peorimm _ _ => "ArithRR0=>Peorimm"
+ | Porrimm _ _ => "ArithRR0=>Porrimm"
+ end.
+
+Definition string_of_name_ArithRR0_XZR (n: arith_rr0) : pstring :=
+match n with
+ | Pandimm _ _ => "ArithRR0_XZR=>Pandimm"
+ | Peorimm _ _ => "ArithRR0_XZR=>Peorimm"
+ | Porrimm _ _ => "ArithRR0_XZR=>Porrimm"
+ end.
+
+Definition string_of_name_ArithARRRR0 (n: arith_arrrr0) : pstring :=
+ match n with
+ | Pmadd _ => "ArithARRRR0=>Pmadd"
+ | Pmsub _ => "ArithARRRR0=>Pmsub"
+ end.
+
+Definition string_of_name_ArithARRRR0_XZR (n: arith_arrrr0) : pstring :=
+ match n with
+ | Pmadd _ => "ArithARRRR0_XZR=>Pmadd"
+ | Pmsub _ => "ArithARRRR0_XZR=>Pmsub"
+ end.
+
+Definition string_of_name_ArithComparisonPP_CN (n: arith_comparison_pp) : pstring :=
+ match n with
+ | Pcmpext _ => "ArithComparisonPP_CN=>Pcmpext"
+ | Pcmnext _ => "ArithComparisonPP_CN=>Pcmnext"
+ | Pfcmp _ => "ArithComparisonPP_CN=>Pfcmp"
+ end.
+
+Definition string_of_name_ArithComparisonPP_CZ (n: arith_comparison_pp) : pstring :=
+ match n with
+ | Pcmpext _ => "ArithComparisonPP_CZ=>Pcmpext"
+ | Pcmnext _ => "ArithComparisonPP_CZ=>Pcmnext"
+ | Pfcmp _ => "ArithComparisonPP_CZ=>Pfcmp"
+ end.
+
+Definition string_of_name_ArithComparisonPP_CC (n: arith_comparison_pp) : pstring :=
+match n with
+ | Pcmpext _ => "ArithComparisonPP_CC=>Pcmpext"
+ | Pcmnext _ => "ArithComparisonPP_CC=>Pcmnext"
+ | Pfcmp _ => "ArithComparisonPP_CC=>Pfcmp"
+ end.
+
+Definition string_of_name_ArithComparisonPP_CV (n: arith_comparison_pp) : pstring :=
+match n with
+ | Pcmpext _ => "ArithComparisonPP_CV=>Pcmpext"
+ | Pcmnext _ => "ArithComparisonPP_CV=>Pcmnext"
+ | Pfcmp _ => "ArithComparisonPP_CV=>Pfcmp"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CN (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CN=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CN=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CN=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CZ (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CZ=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CZ=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CZ=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CC (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CC=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CC=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CC=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CV (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CV=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CV=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CV=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CN_XZR (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CN_XZR=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CN_XZR=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CN_XZR=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CZ_XZR (n: arith_comparison_r0r) : pstring :=
+ match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CZ_XZR=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CZ_XZR=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CZ_XZR=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CC_XZR (n: arith_comparison_r0r) : pstring :=
+match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CC_XZR=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CC_XZR=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CC_XZR=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonR0R_CV_XZR (n: arith_comparison_r0r) : pstring :=
+match n with
+ | Pcmp _ _ => "ArithComparisonR0R_CV_XZR=>Pcmp"
+ | Pcmn _ _ => "ArithComparisonR0R_CV_XZR=>Pcmn"
+ | Ptst _ _ => "ArithComparisonR0R_CV_XZR=>Ptst"
+ end.
+
+Definition string_of_name_ArithComparisonP_CN (n: arith_comparison_p) : pstring :=
+ match n with
+ | Pfcmp0 _ => "ArithComparisonP_CN=>Pfcmp0"
+ | Pcmpimm _ _ => "ArithComparisonP_CN=>Pcmpimm"
+ | Pcmnimm _ _ => "ArithComparisonP_CN=>Pcmnimm"
+ | Ptstimm _ _ => "ArithComparisonP_CN=>Ptstimm"
+ end.
+
+Definition string_of_name_ArithComparisonP_CZ (n: arith_comparison_p) : pstring :=
+ match n with
+ | Pfcmp0 _ => "ArithComparisonP_CZ=>Pfcmp0"
+ | Pcmpimm _ _ => "ArithComparisonP_CZ=>Pcmpimm"
+ | Pcmnimm _ _ => "ArithComparisonP_CZ=>Pcmnimm"
+ | Ptstimm _ _ => "ArithComparisonP_CZ=>Ptstimm"
+ end.
+
+Definition string_of_name_ArithComparisonP_CC (n: arith_comparison_p) : pstring :=
+ match n with
+ | Pfcmp0 _ => "ArithComparisonP_CC=>Pfcmp0"
+ | Pcmpimm _ _ => "ArithComparisonP_CC=>Pcmpimm"
+ | Pcmnimm _ _ => "ArithComparisonP_CC=>Pcmnimm"
+ | Ptstimm _ _ => "ArithComparisonP_CC=>Ptstimm"
+ end.
+
+Definition string_of_name_ArithComparisonP_CV (n: arith_comparison_p) : pstring :=
+ match n with
+ | Pfcmp0 _ => "ArithComparisonP_CV=>Pfcmp0"
+ | Pcmpimm _ _ => "ArithComparisonP_CV=>Pcmpimm"
+ | Pcmnimm _ _ => "ArithComparisonP_CV=>Pcmnimm"
+ | Ptstimm _ _ => "ArithComparisonP_CV=>Ptstimm"
+ end.
+
+Definition string_of_name_cset (c: testcond) : pstring :=
+ match c with
+ | TCeq => "Cset=>TCeq"
+ | TCne => "Cset=>TCne"
+ | TChs => "Cset=>TChs"
+ | TClo => "Cset=>TClo"
+ | TCmi => "Cset=>TCmi"
+ | TCpl => "Cset=>TCpl"
+ | TChi => "Cset=>TChi"
+ | TCls => "Cset=>TCls"
+ | TCge => "Cset=>TCge"
+ | TClt => "Cset=>TClt"
+ | TCgt => "Cset=>TCgt"
+ | TCle => "Cset=>TCle"
+ end.
+
+Definition string_of_arith (op: arith_op): pstring :=
+ match op with
+ | OArithP n => string_of_name_ArithP n
+ | OArithPP n => string_of_name_ArithPP n
+ | OArithPPP n => string_of_name_ArithPPP n
+ | OArithRR0R n => string_of_name_ArithRR0R n
+ | OArithRR0R_XZR n _ => string_of_name_ArithRR0R_XZR n
+ | OArithRR0 n => string_of_name_ArithRR0 n
+ | OArithRR0_XZR n _ => string_of_name_ArithRR0_XZR n
+ | OArithARRRR0 n => string_of_name_ArithARRRR0 n
+ | OArithARRRR0_XZR n _ => string_of_name_ArithARRRR0_XZR n
+ | OArithComparisonPP_CN n => string_of_name_ArithComparisonPP_CN n
+ | OArithComparisonPP_CZ n => string_of_name_ArithComparisonPP_CZ n
+ | OArithComparisonPP_CC n => string_of_name_ArithComparisonPP_CC n
+ | OArithComparisonPP_CV n => string_of_name_ArithComparisonPP_CV n
+ | OArithComparisonR0R_CN n _ => string_of_name_ArithComparisonR0R_CN n
+ | OArithComparisonR0R_CZ n _ => string_of_name_ArithComparisonR0R_CZ n
+ | OArithComparisonR0R_CC n _ => string_of_name_ArithComparisonR0R_CC n
+ | OArithComparisonR0R_CV n _ => string_of_name_ArithComparisonR0R_CV n
+ | OArithComparisonR0R_CN_XZR n _ _ => string_of_name_ArithComparisonR0R_CN_XZR n
+ | OArithComparisonR0R_CZ_XZR n _ _ => string_of_name_ArithComparisonR0R_CZ_XZR n
+ | OArithComparisonR0R_CC_XZR n _ _ => string_of_name_ArithComparisonR0R_CC_XZR n
+ | OArithComparisonR0R_CV_XZR n _ _ => string_of_name_ArithComparisonR0R_CV_XZR n
+ | OArithComparisonP_CN n => string_of_name_ArithComparisonP_CN n
+ | OArithComparisonP_CZ n => string_of_name_ArithComparisonP_CZ n
+ | OArithComparisonP_CC n => string_of_name_ArithComparisonP_CC n
+ | OArithComparisonP_CV n => string_of_name_ArithComparisonP_CV n
+ | Ocset c => string_of_name_cset c
+ | Ofmovi _ => "Ofmovi"
+ | Ofmovi_XZR _ => "Ofmovi_XZR"
+ | Ocsel _ => "Ocsel"
+ | Ofnmul _ => "Ofnmul"
+ end.
+
+Definition string_of_store (op: store_op) : pstring :=
+ match op with
+ | Ostore1 _ _ => "Ostore1"
+ | Ostore2 _ _ => "Ostore2"
+ | OstoreU _ _ => "OstoreU"
+ end.
+
+Definition string_of_load (op: load_op) : pstring :=
+ match op with
+ | Oload1 _ _ => "Oload1"
+ | Oload2 _ _ => "Oload2"
+ | OloadU _ _ => "OloadU"
+ end.
+
+Definition string_of_control (op: control_op) : pstring :=
+ match op with
+ | Ob _ => "Ob"
+ | Obc _ _ => "Obc"
+ | Obl _ => "Obl"
+ | Obs _ => "Obs"
+ | Ocbnz _ _ => "Ocbnz"
+ | Ocbz _ _ => "Ocbz"
+ | Otbnz _ _ _ => "Otbnz"
+ | Otbz _ _ _ => "Otbz"
+ | Obtbl _ => "Obtbl"
+ | OIncremPC _ => "OIncremPC"
+ (*| Oj_l _ => "Oj_l"*)
+ (*| Ocbu _ _ => "Ocbu"*)
+ (*| Odiv => "Odiv"*)
+ (*| Odivu => "Odivu"*)
+ (*| Ojumptable _ => "Ojumptable"*)
+ | OError => "OError"
+ (*| OIncremPC _ => "OIncremPC"*)
+ end.
+
+Definition string_of_allocf (op: allocf_op) : pstring :=
+ match op with
+ | OAllocf_SP _ _ => "OAllocf_SP"
+ | OAllocf_Mem _ _ => "OAllocf_Mem"
+ end.
+
+Definition string_of_freef (op: freef_op) : pstring :=
+ match op with
+ | OFreef_SP _ _ => "OFreef_SP"
+ | OFreef_Mem _ _ => "OFreef_Mem"
+ end.
+
+Definition string_of_op (op: P.op): ?? pstring :=
+ match op with
+ | Arith op => RET (string_of_arith op)
+ | Load op => RET (string_of_load op)
+ | Store op => RET (string_of_store op)
+ | Control op => RET (string_of_control op)
+ | Allocframe op => RET (string_of_allocf op)
+ | Freeframe op => RET (string_of_freef op)
+ | Loadsymbol _ => RET (Str "Loadsymbol")
+ | Constant _ => RET (Str "Constant")
+ | Cvtsw2x => RET (Str "Cvtsw2x")
+ | Cvtuw2x => RET (Str "Cvtuw2x")
+ | Cvtx2w => RET (Str "Cvtx2w")
+ (*| Fail => RET (Str "Fail")*)
+ end.
+End SECT_BBLOCK_EQUIV.
+
+(** REWRITE RULES *)
+
+Definition is_constant (o: op): bool :=
+ match o with (* TODO *)
+ | OArithP _ | OArithRR0_XZR _ _ | Ofmovi_XZR _ => true
+ | _ => false
+ end.
+
+Lemma is_constant_correct ge o: is_constant o = true -> op_eval ge o [] <> None.
+Proof.
+ destruct o; simpl in * |- *; try congruence.
+ destruct op0; simpl in * |- *; try congruence;
+ destruct n; simpl in * |- *; try congruence;
+ unfold arith_eval; destruct ge; simpl in * |- *; try congruence.
+Qed.
+
+Definition main_reduce (t: Terms.term):= RET (Terms.nofail is_constant t).
+
+Local Hint Resolve is_constant_correct: wlp.
+
+Lemma main_reduce_correct t:
+ WHEN main_reduce t ~> pt THEN Terms.match_pt t pt.
+Proof.
+ wlp_simplify.
+Qed.
+
+Definition reduce := {| Terms.result := main_reduce; Terms.result_correct := main_reduce_correct |}.
+
+Definition bblock_simu_test (verb: bool) (p1 p2: Asmblock.bblock) : ?? bool :=
+ assert_same_builtin p1 p2;;
+ if verb then
+ IST.verb_bblock_simu_test reduce string_of_name string_of_op (trans_block p1) (trans_block p2)
+ else
+ IST.bblock_simu_test reduce (trans_block p1) (trans_block p2).
+
+Local Hint Resolve IST.bblock_simu_test_correct IST.verb_bblock_simu_test_correct: wlp.
+
+(** Main simulation (Impure) theorem *)
+Theorem bblock_simu_test_correct verb p1 p2 :
+ WHEN bblock_simu_test verb p1 p2 ~> b THEN b=true -> forall ge fn lk, Asmblockprops.bblock_simu lk ge fn p1 p2.
+Proof.
+ wlp_simplify; eapply bblock_simu_reduce with (Ge:={| _genv := ge; _fn := fn; _lk := lk |}); eauto.
+Qed.
+(*Qed.*)
+Hint Resolve bblock_simu_test_correct: wlp.
+
+(** ** Coerce bblock_simu_test into a pure function (this is a little unsafe like all oracles in CompCert). *)
+
+Import UnsafeImpure.
+
+Definition pure_bblock_simu_test (verb: bool) (p1 p2: Asmblock.bblock): bool :=
+ match unsafe_coerce (bblock_simu_test verb p1 p2) with
+ | Some b => b
+ | None => false
+ end.
+
+Theorem pure_bblock_simu_test_correct verb p1 p2 lk ge fn: pure_bblock_simu_test verb p1 p2 = true -> Asmblockprops.bblock_simu lk ge fn p1 p2.
+Proof.
+ unfold pure_bblock_simu_test.
+ destruct (unsafe_coerce (bblock_simu_test verb p1 p2)) eqn: UNSAFE; try discriminate.
+ intros; subst. eapply bblock_simu_test_correct; eauto.
+ apply unsafe_coerce_not_really_correct; eauto.
+Qed.
+
+Definition bblock_simub: Asmblock.bblock -> Asmblock.bblock -> bool := pure_bblock_simu_test true.
+
+Lemma bblock_simub_correct p1 p2 lk ge fn: bblock_simub p1 p2 = true -> Asmblockprops.bblock_simu lk ge fn p1 p2.
+Proof.
+ eapply (pure_bblock_simu_test_correct true).
+Qed.
diff --git a/aarch64/Asmblockgen.v b/aarch64/Asmblockgen.v
new file mode 100644
index 00000000..0a21485c
--- /dev/null
+++ b/aarch64/Asmblockgen.v
@@ -0,0 +1,1258 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(** * Translation from Machblock to AArch64 assembly block language (Asmblock)
+ Inspired from the Mach->Asm pass of original Leroy's backend, but adapted to the block structure like the KVX backend. *)
+
+Require Import Recdef Coqlib Zwf Zbits.
+Require Import Errors AST Integers Floats Op.
+Require Import Locations Machblock Asm Asmblock.
+
+Local Open Scope string_scope.
+Local Open Scope list_scope.
+Local Open Scope error_monad_scope.
+
+(** Extracting integer or float registers. *)
+
+Definition ireg_of (r: mreg) : res ireg :=
+ match preg_of r with
+ | IR irs => match irs with
+ | RR1 mr => OK mr
+ | _ => Error(msg "Asmgenblock.ireg_of")
+ end
+ | _ => Error(msg "Asmgenblock.iregsp_of")
+ end.
+
+Definition freg_of (r: mreg) : res freg :=
+ match preg_of r with FR mr => OK mr | _ => Error(msg "Asmgenblock.freg_of") end.
+
+(** Recognition of immediate arguments for logical integer operations.*)
+
+(** Valid immediate arguments are repetitions of a bit pattern [B]
+ of length [e] = 2, 4, 8, 16, 32 or 64.
+ The bit pattern [B] must be of the form [0*1*0*] or [1*0*1*]
+ but must not be all zeros or all ones. *)
+
+(** The following automaton recognizes [0*1*0*|1*0*1*].
+<<
+ 0 1 0
+ / \ / \ / \
+ \ / \ / \ /
+ -0--> [B] --1--> [D] --0--> [F]
+ /
+ [A]
+ \
+ -1--> [C] --0--> [E] --1--> [G]
+ / \ / \ / \
+ \ / \ / \ /
+ 1 0 1
+>>
+*)
+
+Module Automaton.
+
+Inductive state : Type := SA | SB | SC | SD | SE | SF | SG | Sbad.
+
+Definition start := SA.
+
+Definition next (s: state) (b: bool) :=
+ match s, b with
+ | SA,false => SB | SA,true => SC
+ | SB,false => SB | SB,true => SD
+ | SC,false => SE | SC,true => SC
+ | SD,false => SF | SD,true => SD
+ | SE,false => SE | SE,true => SG
+ | SF,false => SF | SF,true => Sbad
+ | SG,false => Sbad | SG,true => SG
+ | Sbad,_ => Sbad
+ end.
+
+Definition accepting (s: state) :=
+ match s with
+ | SA | SB | SC | SD | SE | SF | SG => true
+ | Sbad => false
+ end.
+
+Fixpoint run (len: nat) (s: state) (x: Z) : bool :=
+ match len with
+ | Datatypes.O => accepting s
+ | Datatypes.S len => run len (next s (Z.odd x)) (Z.div2 x)
+ end.
+
+End Automaton.
+
+(** The following function determines the candidate length [e],
+ ensuring that [x] is a repetition [BB...B]
+ of a bit pattern [B] of length [e]. *)
+
+Definition logical_imm_length (x: Z) (sixtyfour: bool) : nat :=
+ (** [test n] checks that the low [2n] bits of [x] are of the
+ form [BB], that is, two occurrences of the same [n] bits *)
+ let test (n: Z) : bool :=
+ Z.eqb (Zzero_ext n x) (Zzero_ext n (Z.shiftr x n)) in
+ (** If [test n] fails, we know that the candidate length [e] is
+ at least [2n]. Hence we test with decreasing values of [n]:
+ 32, 16, 8, 4, 2. *)
+ if sixtyfour && negb (test 32) then 64%nat
+ else if negb (test 16) then 32%nat
+ else if negb (test 8) then 16%nat
+ else if negb (test 4) then 8%nat
+ else if negb (test 2) then 4%nat
+ else 2%nat.
+
+(** A valid logical immediate is
+- neither [0] nor [-1];
+- composed of a repetition [BBBBB] of a bit-pattern [B] of length [e]
+- the low [e] bits of the number, that is, [B], match [0*1*0*] or [1*0*1*].
+*)
+
+Definition is_logical_imm32 (x: int) : bool :=
+ negb (Int.eq x Int.zero) && negb (Int.eq x Int.mone) &&
+ Automaton.run (logical_imm_length (Int.unsigned x) false)
+ Automaton.start (Int.unsigned x).
+
+Definition is_logical_imm64 (x: int64) : bool :=
+ negb (Int64.eq x Int64.zero) && negb (Int64.eq x Int64.mone) &&
+ Automaton.run (logical_imm_length (Int64.unsigned x) true)
+ Automaton.start (Int64.unsigned x).
+
+(** Arithmetic immediates are 12-bit unsigned numbers, possibly shifted left 12 bits *)
+
+Definition is_arith_imm32 (x: int) : bool :=
+ Int.eq x (Int.zero_ext 12 x)
+ || Int.eq x (Int.shl (Int.zero_ext 12 (Int.shru x (Int.repr 12))) (Int.repr 12)).
+
+Definition is_arith_imm64 (x: int64) : bool :=
+ Int64.eq x (Int64.zero_ext 12 x)
+ || Int64.eq x (Int64.shl (Int64.zero_ext 12 (Int64.shru x (Int64.repr 12))) (Int64.repr 12)).
+
+Program Definition single_basic (bi: basic): bblock :=
+ {| header := nil; body:= bi::nil; exit := None |}.
+
+(* insert [bi] at the head of [k] *)
+Program Definition insert_basic (bi: basic) (k:bblocks): bblocks :=
+ match k with
+ | bb::k' =>
+ match bb.(header) with
+ | nil => {| header := nil; body := bi :: (body bb); exit := exit bb |}::k'
+ | _ => (single_basic bi)::k
+ end
+ | _ => (single_basic bi)::k
+ end.
+
+Notation "bi ::b k" := (insert_basic bi k) (at level 49, right associativity).
+
+(* insert [ctl] at the head of [k] *)
+Program Definition insert_ctl (ctl: control) (k:bblocks): bblocks :=
+ {| header := nil; body := nil; exit := Some ctl |}::k.
+
+Notation "ctl ::c k" := (insert_ctl ctl k) (at level 49, right associativity).
+
+(* TODO: Coercions to move in Asmblock ? *)
+Coercion PArithP: arith_p >-> Funclass.
+Coercion PArithPP: arith_pp >-> Funclass.
+Coercion PArithPPP: arith_ppp >-> Funclass.
+Coercion PArithRR0: arith_rr0 >-> Funclass.
+Coercion PArithRR0R: arith_rr0r >-> Funclass.
+Coercion PArithARRRR0: arith_arrrr0 >-> Funclass.
+Coercion PArithComparisonP: arith_comparison_p >-> Funclass.
+Coercion PArithComparisonPP: arith_comparison_pp >-> Funclass.
+Coercion PArithComparisonR0R: arith_comparison_r0r >-> Funclass.
+Coercion PArith: ar_instruction >-> basic.
+
+Definition bcode := list basic.
+
+Notation "i ::bi k" := (cons (A:=basic) i k) (at level 49, right associativity).
+(* NB: this notation helps the Coq typechecker to infer coercion [PArith] in [bcode] expressions *)
+(** Alignment check for symbols *)
+
+Parameter symbol_is_aligned : ident -> Z -> bool.
+(** [symbol_is_aligned id sz] checks whether the symbol [id] is [sz] aligned *)
+
+(***************************************************************************************)
+
+(** Decompose integer literals into 16-bit fragments *)
+
+Fixpoint decompose_int (N: nat) (n p: Z) {struct N} : list (Z * Z) :=
+ match N with
+ | Datatypes.O => nil
+ | Datatypes.S N =>
+ let frag := Zzero_ext 16 (Z.shiftr n p) in
+ if Z.eqb frag 0 then
+ decompose_int N n (p + 16)
+ else
+ (frag, p) :: decompose_int N (Z.ldiff n (Z.shiftl 65535 p)) (p + 16)
+ end.
+
+Definition negate_decomposition (l: list (Z * Z)) :=
+ List.map (fun np => (Z.lxor (fst np) 65535, snd np)) l.
+
+Definition loadimm_k (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: bcode) : bcode :=
+ List.fold_right (fun np k => Pmovk sz (fst np) (snd np) rd rd ::bi k) k l.
+
+Definition loadimm_z (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: bcode) : bcode :=
+ match l with
+ | nil => Pmovz sz 0 0 rd ::bi k
+ | (n1, p1) :: l => (Pmovz sz n1 p1 rd) ::bi loadimm_k sz rd l k
+ end.
+
+Definition loadimm_n (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: bcode) : bcode :=
+ match l with
+ | nil => Pmovn sz 0 0 rd ::bi k
+ | (n1, p1) :: l => Pmovn sz n1 p1 rd ::bi loadimm_k sz rd (negate_decomposition l) k
+ end.
+
+Definition loadimm (sz: isize) (rd: ireg) (n: Z) (k: bcode) : bcode :=
+ let N := match sz with W => 2%nat | X => 4%nat end in
+ let dz := decompose_int N n 0 in
+ let dn := decompose_int N (Z.lnot n) 0 in
+ if Nat.leb (List.length dz) (List.length dn)
+ then loadimm_z sz rd dz k
+ else loadimm_n sz rd dn k.
+
+Definition loadimm32 (rd: ireg) (n: int) (k: bcode) : bcode :=
+ if is_logical_imm32 n
+ then Porrimm W (Int.unsigned n) rd XZR ::bi k
+ else loadimm W rd (Int.unsigned n) k.
+
+Definition loadimm64 (rd: ireg) (n: int64) (k: bcode) : bcode :=
+ if is_logical_imm64 n
+ then Porrimm X (Int64.unsigned n) rd XZR ::bi k
+ else loadimm X rd (Int64.unsigned n) k.
+
+(* STUB inspired from kvx/Asmblockgen.v and the reference aarch64/Asmgen.v (see below) *)
+
+Definition indexed_memory_access (insn: addressing -> basic)
+ (sz: Z) (base: iregsp) (ofs: ptrofs) (k: bblocks) : bblocks :=
+ let ofs := Ptrofs.to_int64 ofs in
+ insn (ADimm base ofs) ::b k. (* STUB: change me ! See Asmgen below *)
+
+Definition indexed_memory_access_bc (insn: addressing -> basic)
+ (sz: Z) (base: iregsp) (ofs: ptrofs) (k: bcode) : bcode :=
+ let ofs := Ptrofs.to_int64 ofs in
+ insn (ADimm base ofs) :: k.
+
+Definition loadind (base: iregsp) (ofs: ptrofs) (ty: typ) (dst: mreg) (k: bcode) :=
+ match ty, preg_of dst with
+ | Tint, IR rd => OK (indexed_memory_access_bc (PLoad Pldrw rd) 4 base ofs k)
+ | Tlong, IR rd => OK (indexed_memory_access_bc (PLoad Pldrx rd) 8 base ofs k)
+ | Tsingle, FR rd => OK (indexed_memory_access_bc (PLoad Pldrs rd) 4 base ofs k)
+ | Tfloat, FR rd => OK (indexed_memory_access_bc (PLoad Pldrd rd) 8 base ofs k)
+ | Tany32, IR rd => OK (indexed_memory_access_bc (PLoad Pldrw_a rd) 4 base ofs k)
+ | Tany64, IR rd => OK (indexed_memory_access_bc (PLoad Pldrx_a rd) 8 base ofs k)
+ | Tany64, FR rd => OK (indexed_memory_access_bc (PLoad Pldrd_a rd) 8 base ofs k)
+ | _, _ => Error (msg "Asmgen.loadind")
+ end.
+
+Definition storeind (src: mreg) (base: iregsp) (ofs: ptrofs) (ty: typ) (k: bcode) :=
+ match ty, preg_of src with
+ | Tint, IR rd => OK (indexed_memory_access_bc (PStore Pstrw rd) 4 base ofs k)
+ | Tlong, IR rd => OK (indexed_memory_access_bc (PStore Pstrx rd) 8 base ofs k)
+ | Tsingle, FR rd => OK (indexed_memory_access_bc (PStore Pstrs rd) 4 base ofs k)
+ | Tfloat, FR rd => OK (indexed_memory_access_bc (PStore Pstrd rd) 8 base ofs k)
+ | Tany32, IR rd => OK (indexed_memory_access_bc (PStore Pstrw_a rd) 4 base ofs k)
+ | Tany64, IR rd => OK (indexed_memory_access_bc (PStore Pstrx_a rd) 8 base ofs k)
+ | Tany64, FR rd => OK (indexed_memory_access_bc (PStore Pstrd_a rd) 8 base ofs k)
+ | _, _ => Error (msg "Asmgen.storeind")
+ end.
+
+Definition loadptr (base: iregsp) (ofs: ptrofs) (dst: ireg) (k: bblocks): bblocks :=
+ indexed_memory_access (PLoad Pldrx dst) 8 base ofs k.
+
+Definition loadptr_bc (base: iregsp) (ofs: ptrofs) (dst: ireg) (k: bcode): bcode :=
+ indexed_memory_access_bc (PLoad Pldrx dst) 8 base ofs k.
+
+Definition storeptr (src: ireg) (base: iregsp) (ofs: ptrofs) (k: bblocks): bblocks :=
+ indexed_memory_access (PStore Pstrx src) 8 base ofs k.
+
+(*Definition storeptr_bc (src: ireg) (base: iregsp) (ofs: ptrofs) (k: bcode): bcode :=*)
+ (*indexed_memory_access_bc (PStore Pstrx src) 8 base ofs k.*)
+
+(** Function epilogue *)
+
+(*Definition make_epilogue (f: Machblock.function) (k: bblocks) : bblocks :=*)
+ (*(* FIXME*)
+ (*Cannot be used because memcpy destroys X30;*)
+ (*issue being discussed with X. Leroy *)*)
+ (*(* if is_leaf_function f*)
+ (*then Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k*)
+ (*else*) loadptr XSP f.(fn_retaddr_ofs) RA*)
+ (*(Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) ::b k).*)
+
+Definition make_epilogue (f: Machblock.function) : bcode :=
+ loadptr_bc XSP f.(fn_retaddr_ofs) RA
+ (Pfreeframe f.(fn_stacksize) f.(fn_link_ofs)::nil).
+
+(** Add immediate *)
+
+Definition addimm_aux (insn: Z -> arith_pp)
+ (rd r1: iregsp) (n: Z) (k: bcode) :=
+ let nlo := Zzero_ext 12 n in
+ let nhi := n - nlo in
+ if Z.eqb nhi 0 then
+ insn nlo rd r1 ::bi k
+ else if Z.eqb nlo 0 then
+ insn nhi rd r1 ::bi k
+ else
+ insn nhi rd r1 ::bi insn nlo rd rd ::bi k.
+
+Definition addimm32 (rd r1: ireg) (n: int) (k: bcode) : bcode :=
+ let m := Int.neg n in
+ if Int.eq n (Int.zero_ext 24 n) then
+ addimm_aux (Paddimm W) rd r1 (Int.unsigned n) k
+ else if Int.eq m (Int.zero_ext 24 m) then
+ addimm_aux (Psubimm W) rd r1 (Int.unsigned m) k
+ else if Int.lt n Int.zero then
+ loadimm32 X16 m (Psub W SOnone rd r1 X16 ::bi k)
+ else
+ loadimm32 X16 n (Padd W SOnone rd r1 X16 ::bi k).
+
+Definition addimm64 (rd r1: iregsp) (n: int64) (k: bcode) : bcode :=
+ let m := Int64.neg n in
+ if Int64.eq n (Int64.zero_ext 24 n) then
+ addimm_aux (Paddimm X) rd r1 (Int64.unsigned n) k
+ else if Int64.eq m (Int64.zero_ext 24 m) then
+ addimm_aux (Psubimm X) rd r1 (Int64.unsigned m) k
+ else if Int64.lt n Int64.zero then
+ loadimm64 X16 m (Psubext (EOuxtx Int.zero) rd r1 X16 ::bi k)
+ else
+ loadimm64 X16 n (Paddext (EOuxtx Int.zero) rd r1 X16 ::bi k).
+
+(** Logical immediate *)
+
+Definition logicalimm32
+ (insn1: Z -> arith_rr0)
+ (insn2: shift_op -> arith_rr0r)
+ (rd r1: ireg) (n: int) (k: bcode) : bcode :=
+ if is_logical_imm32 n
+ then insn1 (Int.unsigned n) rd r1 ::bi k
+ else loadimm32 X16 n (insn2 SOnone rd r1 X16 ::bi k).
+
+Definition logicalimm64
+ (insn1: Z -> arith_rr0)
+ (insn2: shift_op -> arith_rr0r)
+ (rd r1: ireg) (n: int64) (k: bcode) : bcode :=
+ if is_logical_imm64 n
+ then insn1 (Int64.unsigned n) rd r1 ::bi k
+ else loadimm64 X16 n (insn2 SOnone rd r1 X16 ::bi k).
+
+(** Sign- or zero-extended arithmetic *)
+
+Definition transl_extension (ex: extension) (a: int) : extend_op :=
+ match ex with Xsgn32 => EOsxtw a | Xuns32 => EOuxtw a end.
+
+Definition move_extended_base
+ (rd: ireg) (r1: ireg) (ex: extension) (k: bcode) : bcode :=
+ match ex with
+ | Xsgn32 => Pcvtsw2x rd r1 ::bi k
+ | Xuns32 => Pcvtuw2x rd r1 ::bi k
+ end.
+
+Definition move_extended
+ (rd: ireg) (r1: ireg) (ex: extension) (a: int) (k: bcode) : bcode :=
+ if Int.eq a Int.zero then
+ move_extended_base rd r1 ex k
+ else
+ move_extended_base rd r1 ex (Padd X (SOlsl a) rd XZR rd ::bi k).
+
+Definition arith_extended
+ (insnX: extend_op -> arith_ppp)
+ (insnS: shift_op -> arith_rr0r)
+ (rd r1 r2: ireg) (ex: extension) (a: int) (k: bcode) : bcode :=
+ if Int.ltu a (Int.repr 5) then
+ insnX (transl_extension ex a) rd r1 r2 ::bi k
+ else
+ move_extended_base X16 r2 ex (insnS (SOlsl a) rd r1 X16 ::bi k).
+
+(** Extended right shift *)
+
+Definition shrx32 (rd r1: ireg) (n: int) (k: bcode) : bcode :=
+ if Int.eq n Int.zero then
+ Pmov rd r1 ::bi k
+ else
+ Porr W (SOasr (Int.repr 31)) X16 XZR r1 ::bi
+ Padd W (SOlsr (Int.sub Int.iwordsize n)) X16 r1 X16 ::bi
+ Porr W (SOasr n) rd XZR X16 ::bi k.
+
+Definition shrx64 (rd r1: ireg) (n: int) (k: bcode) : bcode :=
+ if Int.eq n Int.zero then
+ Pmov rd r1 ::bi k
+ else
+ Porr X (SOasr (Int.repr 63)) X16 XZR r1 ::bi
+ Padd X (SOlsr (Int.sub Int64.iwordsize' n)) X16 r1 X16 ::bi
+ Porr X (SOasr n) rd XZR X16 ::bi k.
+
+(** Load the address [id + ofs] in [rd] *)
+
+Definition loadsymbol (rd: ireg) (id: ident) (ofs: ptrofs) (k: bcode) : bcode :=
+ if Archi.pic_code tt then
+ if Ptrofs.eq ofs Ptrofs.zero then
+ Ploadsymbol rd id ::bi k
+ else
+ Ploadsymbol rd id :: addimm64 rd rd (Ptrofs.to_int64 ofs) k
+ else
+ Padrp id ofs rd ::bi Paddadr id ofs rd rd ::bi k.
+
+(** Translate a shifted operand *)
+
+Definition transl_shift (s: Op.shift) (a: int): Asm.shift_op :=
+ match s with
+ | Slsl => SOlsl a
+ | Slsr => SOlsr a
+ | Sasr => SOasr a
+ | Sror => SOror a
+ end.
+
+(** Translation of a condition. Prepends to [k] the instructions
+ that evaluate the condition and leave its boolean result in one of
+ the bits of the condition register. The bit in question is
+ determined by the [crbit_for_cond] function. *)
+
+Definition transl_cond
+ (cond: condition) (args: list mreg) (k: bcode) :=
+ match cond, args with
+ | (Ccomp c | Ccompu c), a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pcmp W SOnone r1 r2 ::bi k)
+ | (Ccompshift c s a | Ccompushift c s a), a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pcmp W (transl_shift s a) r1 r2 ::bi k)
+ | (Ccompimm c n | Ccompuimm c n), a1 :: nil =>
+ do r1 <- ireg_of a1;
+ OK (if is_arith_imm32 n then
+ Pcmpimm W (Int.unsigned n) r1 ::bi k
+ else if is_arith_imm32 (Int.neg n) then
+ Pcmnimm W (Int.unsigned (Int.neg n)) r1 ::bi k
+ else
+ loadimm32 X16 n (Pcmp W SOnone r1 X16 ::bi k))
+ | (Cmaskzero n | Cmasknotzero n), a1 :: nil =>
+ do r1 <- ireg_of a1;
+ OK (if is_logical_imm32 n then
+ Ptstimm W (Int.unsigned n) r1 ::bi k
+ else
+ loadimm32 X16 n (Ptst W SOnone r1 X16 ::bi k))
+ | (Ccompl c | Ccomplu c), a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pcmp X SOnone r1 r2 ::bi k)
+ | (Ccomplshift c s a | Ccomplushift c s a), a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pcmp X (transl_shift s a) r1 r2 ::bi k)
+ | (Ccomplimm c n | Ccompluimm c n), a1 :: nil =>
+ do r1 <- ireg_of a1;
+ OK (if is_arith_imm64 n then
+ Pcmpimm X (Int64.unsigned n) r1 ::bi k
+ else if is_arith_imm64 (Int64.neg n) then
+ Pcmnimm X (Int64.unsigned (Int64.neg n)) r1 ::bi k
+ else
+ loadimm64 X16 n (Pcmp X SOnone r1 X16 ::bi k))
+ | (Cmasklzero n | Cmasklnotzero n), a1 :: nil =>
+ do r1 <- ireg_of a1;
+ OK (if is_logical_imm64 n then
+ Ptstimm X (Int64.unsigned n) r1 ::bi k
+ else
+ loadimm64 X16 n (Ptst X SOnone r1 X16 ::bi k))
+ | Ccompf cmp, a1 :: a2 :: nil =>
+ do r1 <- freg_of a1; do r2 <- freg_of a2;
+ OK (Pfcmp D r1 r2 ::bi k)
+ | Cnotcompf cmp, a1 :: a2 :: nil =>
+ do r1 <- freg_of a1; do r2 <- freg_of a2;
+ OK (Pfcmp D r1 r2 ::bi k)
+ | Ccompfzero cmp, a1 :: nil =>
+ do r1 <- freg_of a1;
+ OK (Pfcmp0 D r1 ::bi k)
+ | Cnotcompfzero cmp, a1 :: nil =>
+ do r1 <- freg_of a1;
+ OK (Pfcmp0 D r1 ::bi k)
+ | Ccompfs cmp, a1 :: a2 :: nil =>
+ do r1 <- freg_of a1; do r2 <- freg_of a2;
+ OK (Pfcmp S r1 r2 ::bi k)
+ | Cnotcompfs cmp, a1 :: a2 :: nil =>
+ do r1 <- freg_of a1; do r2 <- freg_of a2;
+ OK (Pfcmp S r1 r2 ::bi k)
+ | Ccompfszero cmp, a1 :: nil =>
+ do r1 <- freg_of a1;
+ OK (Pfcmp0 S r1 ::bi k)
+ | Cnotcompfszero cmp, a1 :: nil =>
+ do r1 <- freg_of a1;
+ OK (Pfcmp0 S r1 ::bi k)
+ | _, _ =>
+ Error(msg "Asmgenblock.transl_cond")
+ end.
+
+Definition cond_for_signed_cmp (cmp: comparison) :=
+ match cmp with
+ | Ceq => TCeq
+ | Cne => TCne
+ | Clt => TClt
+ | Cle => TCle
+ | Cgt => TCgt
+ | Cge => TCge
+ end.
+
+Definition cond_for_unsigned_cmp (cmp: comparison) :=
+ match cmp with
+ | Ceq => TCeq
+ | Cne => TCne
+ | Clt => TClo
+ | Cle => TCls
+ | Cgt => TChi
+ | Cge => TChs
+ end.
+
+Definition cond_for_float_cmp (cmp: comparison) :=
+ match cmp with
+ | Ceq => TCeq
+ | Cne => TCne
+ | Clt => TCmi
+ | Cle => TCls
+ | Cgt => TCgt
+ | Cge => TCge
+ end.
+
+Definition cond_for_float_not_cmp (cmp: comparison) :=
+ match cmp with
+ | Ceq => TCne
+ | Cne => TCeq
+ | Clt => TCpl
+ | Cle => TChi
+ | Cgt => TCle
+ | Cge => TClt
+ end.
+
+Definition cond_for_cond (cond: condition) :=
+ match cond with
+ | Ccomp cmp => cond_for_signed_cmp cmp
+ | Ccompu cmp => cond_for_unsigned_cmp cmp
+ | Ccompshift cmp s a => cond_for_signed_cmp cmp
+ | Ccompushift cmp s a => cond_for_unsigned_cmp cmp
+ | Ccompimm cmp n => cond_for_signed_cmp cmp
+ | Ccompuimm cmp n => cond_for_unsigned_cmp cmp
+ | Cmaskzero n => TCeq
+ | Cmasknotzero n => TCne
+ | Ccompl cmp => cond_for_signed_cmp cmp
+ | Ccomplu cmp => cond_for_unsigned_cmp cmp
+ | Ccomplshift cmp s a => cond_for_signed_cmp cmp
+ | Ccomplushift cmp s a => cond_for_unsigned_cmp cmp
+ | Ccomplimm cmp n => cond_for_signed_cmp cmp
+ | Ccompluimm cmp n => cond_for_unsigned_cmp cmp
+ | Cmasklzero n => TCeq
+ | Cmasklnotzero n => TCne
+ | Ccompf cmp => cond_for_float_cmp cmp
+ | Cnotcompf cmp => cond_for_float_not_cmp cmp
+ | Ccompfzero cmp => cond_for_float_cmp cmp
+ | Cnotcompfzero cmp => cond_for_float_not_cmp cmp
+ | Ccompfs cmp => cond_for_float_cmp cmp
+ | Cnotcompfs cmp => cond_for_float_not_cmp cmp
+ | Ccompfszero cmp => cond_for_float_cmp cmp
+ | Cnotcompfszero cmp => cond_for_float_not_cmp cmp
+ end.
+
+(** Translation of a conditional branch. Prepends to [k] the instructions
+ that evaluate the condition and ranch to [lbl] if it holds.
+ We recognize some conditional branches that can be implemented
+ without setting then testing condition flags. *)
+
+Definition transl_cond_branch_default
+ (c: condition) (args: list mreg) (lbl: label) (k: bcode) : res (bcode*control) :=
+ do ccode <- transl_cond c args k;
+ OK(ccode, PCtlFlow (Pbc (cond_for_cond c) lbl)).
+
+Definition transl_cond_branch
+ (c: condition) (args: list mreg) (lbl: label) (k: bcode) : res (bcode*control) :=
+ match args, c with
+ | a1 :: nil, (Ccompimm Cne n | Ccompuimm Cne n) =>
+ if Int.eq n Int.zero
+ then (do r1 <- ireg_of a1; OK (k, PCtlFlow (Pcbnz W r1 lbl)))
+ else transl_cond_branch_default c args lbl k
+ | a1 :: nil, (Ccompimm Ceq n | Ccompuimm Ceq n) =>
+ if Int.eq n Int.zero
+ then (do r1 <- ireg_of a1; OK (k, PCtlFlow (Pcbz W r1 lbl)))
+ else transl_cond_branch_default c args lbl k
+ | a1 :: nil, (Ccomplimm Cne n | Ccompluimm Cne n) =>
+ if Int64.eq n Int64.zero
+ then (do r1 <- ireg_of a1; OK (k, PCtlFlow (Pcbnz X r1 lbl)))
+ else transl_cond_branch_default c args lbl k
+ | a1 :: nil, (Ccomplimm Ceq n | Ccompluimm Ceq n) =>
+ if Int64.eq n Int64.zero
+ then (do r1 <- ireg_of a1; OK (k, PCtlFlow (Pcbz X r1 lbl)))
+ else transl_cond_branch_default c args lbl k
+ | a1 :: nil, Cmaskzero n =>
+ match Int.is_power2 n with
+ | Some bit => do r1 <- ireg_of a1; OK (k, PCtlFlow (Ptbz W r1 bit lbl))
+ | None => transl_cond_branch_default c args lbl k
+ end
+ | a1 :: nil, Cmasknotzero n =>
+ match Int.is_power2 n with
+ | Some bit => do r1 <- ireg_of a1; OK (k, PCtlFlow (Ptbnz W r1 bit lbl))
+ | None => transl_cond_branch_default c args lbl k
+ end
+ | a1 :: nil, Cmasklzero n =>
+ match Int64.is_power2' n with
+ | Some bit => do r1 <- ireg_of a1; OK (k, PCtlFlow (Ptbz X r1 bit lbl))
+ | None => transl_cond_branch_default c args lbl k
+ end
+ | a1 :: nil, Cmasklnotzero n =>
+ match Int64.is_power2' n with
+ | Some bit => do r1 <- ireg_of a1; OK (k, PCtlFlow (Ptbnz X r1 bit lbl))
+ | None => transl_cond_branch_default c args lbl k
+ end
+ | _, _ =>
+ transl_cond_branch_default c args lbl k
+ end.
+
+(** Translation of the arithmetic operation [r <- op(args)].
+ The corresponding instructions are prepended to [k]. *)
+
+Definition transl_op
+ (op: operation) (args: list mreg) (res: mreg) (k: bcode) :=
+ match op, args with
+ | Omove, a1 :: nil =>
+ match preg_of res, preg_of a1 with
+ | IR r, IR a => OK (Pmov r a ::bi k)
+ | FR r, FR a => OK (Pfmov r a ::bi k)
+ | _ , _ => Error(msg "Asmgenblock.Omove")
+ end
+ | Ointconst n, nil =>
+ do rd <- ireg_of res;
+ OK (loadimm32 rd n k)
+ | Olongconst n, nil =>
+ do rd <- ireg_of res;
+ OK (loadimm64 rd n k)
+ | Ofloatconst f, nil =>
+ do rd <- freg_of res;
+ OK (if Float.eq_dec f Float.zero
+ then Pfmovi D rd XZR ::bi k
+ else Pfmovimmd f rd ::bi k)
+ | Osingleconst f, nil =>
+ do rd <- freg_of res;
+ OK (if Float32.eq_dec f Float32.zero
+ then Pfmovi S rd XZR ::bi k
+ else Pfmovimms f rd ::bi k)
+ | Oaddrsymbol id ofs, nil =>
+ do rd <- ireg_of res;
+ OK (loadsymbol rd id ofs k)
+ | Oaddrstack ofs, nil =>
+ do rd <- ireg_of res;
+ OK (addimm64 rd XSP (Ptrofs.to_int64 ofs) k)
+ (** 32-bit integer arithmetic *)
+ | Oshift s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porr W (transl_shift s a) rd XZR r1 ::bi k)
+ | Oadd, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Padd W SOnone rd r1 r2 ::bi k)
+ | Oaddshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Padd W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oaddimm n, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- ireg_of a1;
+ OK (addimm32 rd rs n k)
+ | Oneg, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psub W SOnone rd XZR r1 ::bi k)
+ | Onegshift s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psub W (transl_shift s a) rd XZR r1 ::bi k)
+ | Osub, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psub W SOnone rd r1 r2 ::bi k)
+ | Osubshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psub W (transl_shift s a) rd r1 r2 ::bi k)
+ | Omul, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do rs1 <- ireg_of a1; do rs2 <- ireg_of a2;
+ OK (Pmadd W rd rs1 rs2 XZR ::bi k)
+ | Omuladd, a1 :: a2 :: a3 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
+ OK (Pmadd W rd r2 r3 r1 ::bi k)
+ | Omulsub, a1 :: a2 :: a3 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
+ OK (Pmsub W rd r2 r3 r1 ::bi k)
+ | Odiv, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psdiv W rd r1 r2 ::bi k)
+ | Odivu, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pudiv W rd r1 r2 ::bi k)
+ | Oand, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pand W SOnone rd r1 r2 ::bi k)
+ | Oandshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pand W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oandimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm32 (Pandimm W) (Pand W) rd r1 n k)
+ | Oor, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porr W SOnone rd r1 r2 ::bi k)
+ | Oorshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porr W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oorimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm32 (Porrimm W) (Porr W) rd r1 n k)
+ | Oxor, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peor W SOnone rd r1 r2 ::bi k)
+ | Oxorshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peor W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oxorimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm32 (Peorimm W) (Peor W) rd r1 n k)
+ | Onot, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porn W SOnone rd XZR r1 ::bi k)
+ | Onotshift s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porn W (transl_shift s a) rd XZR r1 ::bi k)
+ | Obic, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pbic W SOnone rd r1 r2 ::bi k)
+ | Obicshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pbic W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oorn, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porn W SOnone rd r1 r2 ::bi k)
+ | Oornshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porn W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oeqv, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peon W SOnone rd r1 r2 ::bi k)
+ | Oeqvshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peon W (transl_shift s a) rd r1 r2 ::bi k)
+ | Oshl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Plslv W rd r1 r2 ::bi k)
+ | Oshr, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pasrv W rd r1 r2 ::bi k)
+ | Oshru, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Plsrv W rd r1 r2 ::bi k)
+ | Oshrximm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (shrx32 rd r1 n k)
+ | Ozext s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfiz W Int.zero s rd r1 ::bi k)
+ | Osext s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfiz W Int.zero s rd r1 ::bi k)
+ | Oshlzext s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfiz W a (Z.min s (Int.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Oshlsext s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfiz W a (Z.min s (Int.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Ozextshr a s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfx W a (Z.min s (Int.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Osextshr a s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfx W a (Z.min s (Int.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ (** 64-bit integer arithmetic *)
+ | Oshiftl s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porr X (transl_shift s a) rd XZR r1 ::bi k)
+ | Oextend x a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (move_extended rd r1 x a k)
+ (* [Omakelong] and [Ohighlong] should not occur *)
+ | Olowlong, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ assertion (ireg_eq rd r1);
+ OK (Pcvtx2w rd ::bi k)
+ | Oaddl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Padd X SOnone rd r1 r2 ::bi k)
+ | Oaddlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Padd X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oaddlext x a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (arith_extended Paddext (Padd X) rd r1 r2 x a k)
+ | Oaddlimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (addimm64 rd r1 n k)
+ | Onegl, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psub X SOnone rd XZR r1 ::bi k)
+ | Oneglshift s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psub X (transl_shift s a) rd XZR r1 ::bi k)
+ | Osubl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psub X SOnone rd r1 r2 ::bi k)
+ | Osublshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psub X (transl_shift s a) rd r1 r2 ::bi k)
+ | Osublext x a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (arith_extended Psubext (Psub X) rd r1 r2 x a k)
+ | Omull, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pmadd X rd r1 r2 XZR ::bi k)
+ | Omulladd, a1 :: a2 :: a3 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
+ OK (Pmadd X rd r2 r3 r1 ::bi k)
+ | Omullsub, a1 :: a2 :: a3 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
+ OK (Pmsub X rd r2 r3 r1 ::bi k)
+ | Omullhs, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psmulh rd r1 r2 ::bi k)
+ | Omullhu, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pumulh rd r1 r2 ::bi k)
+ | Odivl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Psdiv X rd r1 r2 ::bi k)
+ | Odivlu, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pudiv X rd r1 r2 ::bi k)
+ | Oandl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pand X SOnone rd r1 r2 ::bi k)
+ | Oandlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pand X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oandlimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm64 (Pandimm X) (Pand X) rd r1 n k)
+ | Oorl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porr X SOnone rd r1 r2 ::bi k)
+ | Oorlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porr X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oorlimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm64 (Porrimm X) (Porr X) rd r1 n k)
+ | Oxorl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peor X SOnone rd r1 r2 ::bi k)
+ | Oxorlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peor X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oxorlimm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (logicalimm64 (Peorimm X) (Peor X) rd r1 n k)
+ | Onotl, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porn X SOnone rd XZR r1 ::bi k)
+ | Onotlshift s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Porn X (transl_shift s a) rd XZR r1 ::bi k)
+ | Obicl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pbic X SOnone rd r1 r2 ::bi k)
+ | Obiclshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pbic X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oornl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porn X SOnone rd r1 r2 ::bi k)
+ | Oornlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Porn X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oeqvl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peon X SOnone rd r1 r2 ::bi k)
+ | Oeqvlshift s a, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Peon X (transl_shift s a) rd r1 r2 ::bi k)
+ | Oshll, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Plslv X rd r1 r2 ::bi k)
+ | Oshrl, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Pasrv X rd r1 r2 ::bi k)
+ | Oshrlu, a1 :: a2 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (Plsrv X rd r1 r2 ::bi k)
+ | Oshrlximm n, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (shrx64 rd r1 n k)
+ | Ozextl s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfiz X Int.zero s rd r1 ::bi k)
+ | Osextl s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfiz X Int.zero s rd r1 ::bi k)
+ | Oshllzext s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfiz X a (Z.min s (Int64.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Oshllsext s a, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfiz X a (Z.min s (Int64.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Ozextshrl a s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Pubfx X a (Z.min s (Int64.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ | Osextshrl a s, a1 :: nil =>
+ do rd <- ireg_of res; do r1 <- ireg_of a1;
+ OK (Psbfx X a (Z.min s (Int64.zwordsize - Int.unsigned a)) rd r1 ::bi k)
+ (** 64-bit floating-point arithmetic *)
+ | Onegf, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfneg D rd rs ::bi k)
+ | Oabsf, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfabs D rd rs ::bi k)
+ | Oaddf, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfadd D rd rs1 rs2 ::bi k)
+ | Osubf, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfsub D rd rs1 rs2 ::bi k)
+ | Omulf, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfmul D rd rs1 rs2 ::bi k)
+ | Odivf, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfdiv D rd rs1 rs2 ::bi k)
+ (** 32-bit floating-point arithmetic *)
+ | Onegfs, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfneg S rd rs ::bi k)
+ | Oabsfs, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfabs S rd rs ::bi k)
+ | Oaddfs, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfadd S rd rs1 rs2 ::bi k)
+ | Osubfs, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfsub S rd rs1 rs2 ::bi k)
+ | Omulfs, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfmul S rd rs1 rs2 ::bi k)
+ | Odivfs, a1 :: a2 :: nil =>
+ do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
+ OK (Pfdiv S rd rs1 rs2 ::bi k)
+ | Osingleoffloat, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfcvtsd rd rs ::bi k)
+ | Ofloatofsingle, a1 :: nil =>
+ do rd <- freg_of res; do rs <- freg_of a1;
+ OK (Pfcvtds rd rs ::bi k)
+ (** Conversions between int and float *)
+ | Ointoffloat, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzs W D rd rs ::bi k)
+ | Ointuoffloat, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzu W D rd rs ::bi k)
+ | Ofloatofint, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pscvtf D W rd rs ::bi k)
+ | Ofloatofintu, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pucvtf D W rd rs ::bi k)
+ | Ointofsingle, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzs W S rd rs ::bi k)
+ | Ointuofsingle, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzu W S rd rs ::bi k)
+ | Osingleofint, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pscvtf S W rd rs ::bi k)
+ | Osingleofintu, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pucvtf S W rd rs ::bi k)
+ | Olongoffloat, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzs X D rd rs ::bi k)
+ | Olonguoffloat, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzu X D rd rs ::bi k)
+ | Ofloatoflong, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pscvtf D X rd rs ::bi k)
+ | Ofloatoflongu, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pucvtf D X rd rs ::bi k)
+ | Olongofsingle, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzs X S rd rs ::bi k)
+ | Olonguofsingle, a1 :: nil =>
+ do rd <- ireg_of res; do rs <- freg_of a1;
+ OK (Pfcvtzu X S rd rs ::bi k)
+ | Osingleoflong, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pscvtf S X rd rs ::bi k)
+ | Osingleoflongu, a1 :: nil =>
+ do rd <- freg_of res; do rs <- ireg_of a1;
+ OK (Pucvtf S X rd rs ::bi k)
+ (** Boolean tests *)
+ | Ocmp c, _ =>
+ do rd <- ireg_of res;
+ transl_cond c args (Pcset rd (cond_for_cond c) ::bi k)
+ (** Conditional move *)
+ | Osel cmp ty, a1 :: a2 :: args =>
+ match preg_of res with
+ | IR r =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ transl_cond cmp args (Pcsel r r1 r2 (cond_for_cond cmp) ::bi k)
+ | FR r =>
+ do r1 <- freg_of a1; do r2 <- freg_of a2;
+ transl_cond cmp args (Pcsel r r1 r2 (cond_for_cond cmp) ::bi k)
+ | _ =>
+ Error(msg "Asmgenblock.Osel")
+ end
+ | _, _ => Error(msg "Asmgenblock.transl_op")
+ end.
+
+(** Translation of addressing modes *)
+
+Definition offset_representable (sz: Z) (ofs: int64) : bool :=
+ let isz := Int64.repr sz in
+ (** either unscaled 9-bit signed *)
+ Int64.eq ofs (Int64.sign_ext 9 ofs) ||
+ (** or scaled 12-bit unsigned *)
+ (Int64.eq (Int64.modu ofs isz) Int64.zero
+ && Int64.ltu ofs (Int64.shl isz (Int64.repr 12))).
+
+Definition transl_addressing (sz: Z) (addr: Op.addressing) (args: list mreg)
+ (insn: Asm.addressing -> basic) (k: bcode) : res bcode :=
+ match addr, args with
+ | Aindexed ofs, a1 :: nil =>
+ do r1 <- ireg_of a1;
+ if offset_representable sz ofs then
+ OK (insn (ADimm r1 ofs) ::bi k)
+ else
+ OK (loadimm64 X16 ofs (insn (ADreg r1 X16) ::bi k))
+ | Aindexed2, a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ OK (insn (ADreg r1 r2) ::bi k)
+ | Aindexed2shift a, a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ if Int.eq a Int.zero then
+ OK (insn (ADreg r1 r2) ::bi k)
+ else if Int.eq (Int.shl Int.one a) (Int.repr sz) then
+ OK (insn (ADlsl r1 r2 a) ::bi k)
+ else
+ OK (Padd X (SOlsl a) X16 r1 r2 ::bi insn (ADimm X16 Int64.zero) ::bi k)
+ | Aindexed2ext x a, a1 :: a2 :: nil =>
+ do r1 <- ireg_of a1; do r2 <- ireg_of a2;
+ if Int.eq a Int.zero || Int.eq (Int.shl Int.one a) (Int.repr sz) then
+ OK (insn (match x with Xsgn32 => ADsxt r1 r2 a
+ | Xuns32 => ADuxt r1 r2 a end) ::bi k)
+ else
+ OK (arith_extended Paddext (Padd X) X16 r1 r2 x a
+ (insn (ADimm X16 Int64.zero) ::bi k))
+ | Aglobal id ofs, nil =>
+ assertion (negb (Archi.pic_code tt));
+ if Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero && symbol_is_aligned id sz
+ then OK (Padrp id ofs X16 ::bi insn (ADadr X16 id ofs) ::bi k)
+ else OK (loadsymbol X16 id ofs (insn (ADimm X16 Int64.zero) ::bi k))
+ | Ainstack ofs, nil =>
+ let ofs := Ptrofs.to_int64 ofs in
+ if offset_representable sz ofs then
+ OK (insn (ADimm XSP ofs) ::bi k)
+ else
+ OK (loadimm64 X16 ofs (insn (ADreg XSP X16) ::bi k))
+ | _, _ =>
+ Error(msg "Asmgen.transl_addressing")
+ end.
+
+(** Translation of loads and stores *)
+
+Definition transl_load (chunk: memory_chunk) (addr: Op.addressing)
+ (args: list mreg) (dst: mreg) (k: bcode) : res bcode :=
+ match chunk with
+ | Mint8unsigned =>
+ do rd <- ireg_of dst; transl_addressing 1 addr args (PLoad (Pldrb W) rd) k
+ | Mint8signed =>
+ do rd <- ireg_of dst; transl_addressing 1 addr args (PLoad (Pldrsb W) rd) k
+ | Mint16unsigned =>
+ do rd <- ireg_of dst; transl_addressing 2 addr args (PLoad (Pldrh W) rd) k
+ | Mint16signed =>
+ do rd <- ireg_of dst; transl_addressing 2 addr args (PLoad (Pldrsh W) rd) k
+ | Mint32 =>
+ do rd <- ireg_of dst; transl_addressing 4 addr args (PLoad Pldrw rd) k
+ | Mint64 =>
+ do rd <- ireg_of dst; transl_addressing 8 addr args (PLoad Pldrx rd) k
+ | Mfloat32 =>
+ do rd <- freg_of dst; transl_addressing 4 addr args (PLoad Pldrs rd) k
+ | Mfloat64 =>
+ do rd <- freg_of dst; transl_addressing 8 addr args (PLoad Pldrd rd) k
+ | Many32 =>
+ do rd <- ireg_of dst; transl_addressing 4 addr args (PLoad Pldrw_a rd) k
+ | Many64 =>
+ do rd <- ireg_of dst; transl_addressing 8 addr args (PLoad Pldrx_a rd) k
+ end.
+
+Definition transl_store (chunk: memory_chunk) (addr: Op.addressing)
+ (args: list mreg) (src: mreg) (k: bcode) : res bcode :=
+ match chunk with
+ | Mint8unsigned | Mint8signed =>
+ do r1 <- ireg_of src; transl_addressing 1 addr args (PStore Pstrb r1) k
+ | Mint16unsigned | Mint16signed =>
+ do r1 <- ireg_of src; transl_addressing 2 addr args (PStore Pstrh r1) k
+ | Mint32 =>
+ do r1 <- ireg_of src; transl_addressing 4 addr args (PStore Pstrw r1) k
+ | Mint64 =>
+ do r1 <- ireg_of src; transl_addressing 8 addr args (PStore Pstrx r1) k
+ | Mfloat32 =>
+ do r1 <- freg_of src; transl_addressing 4 addr args (PStore Pstrs r1) k
+ | Mfloat64 =>
+ do r1 <- freg_of src; transl_addressing 8 addr args (PStore Pstrd r1) k
+ | Many32 =>
+ do r1 <- ireg_of src; transl_addressing 4 addr args (PStore Pstrw_a r1) k
+ | Many64 =>
+ do r1 <- ireg_of src; transl_addressing 8 addr args (PStore Pstrx_a r1) k
+ end.
+
+(** Translation of a Machblock instruction. *)
+
+Definition transl_instr_basic (f: Machblock.function) (i: Machblock.basic_inst)
+ (ep: bool) (k: bcode) :=
+ match i with
+ | MBgetstack ofs ty dst =>
+ loadind XSP ofs ty dst k
+ | MBsetstack src ofs ty =>
+ storeind src XSP ofs ty k
+ | MBgetparam ofs ty dst =>
+ do c <- loadind X29 ofs ty dst k;
+ OK (if ep then c else loadptr_bc XSP f.(fn_link_ofs) X29 c)
+ | MBop op args res =>
+ transl_op op args res k
+ | MBload _ chunk addr args dst =>
+ transl_load chunk addr args dst k
+ | MBstore chunk addr args src =>
+ transl_store chunk addr args src k
+ end.
+
+(** Translation of a code sequence *)
+
+Definition it1_is_parent (before: bool) (i: Machblock.basic_inst) : bool :=
+ match i with
+ (*| MBgetstack ofs ty dst => before && negb (mreg_eq dst R29)*)
+ | MBsetstack src ofs ty => before
+ | MBgetparam ofs ty dst => negb (mreg_eq dst R29)
+ | MBop op args res => before && negb (mreg_eq res R29)
+ (*| MBload trapping_mode chunk addr args dst => before && negb (mreg_eq dst R29)*)
+ | _ => false
+ end.
+
+Fixpoint transl_basic_code (f: Machblock.function) (il: list Machblock.basic_inst) (it1p: bool) (k: bcode):=
+ match il with
+ | nil => OK (k)
+ | i1 :: il' =>
+ do k1 <- transl_basic_code f il' (it1_is_parent it1p i1) k;
+ transl_instr_basic f i1 it1p k1
+ end.
+
+(** Translation of a whole function. Note that we must check
+ that the generated code contains less than [2^64] instructions,
+ otherwise the offset part of the [PC] code pointer could wrap
+ around, leading to incorrect executions. *)
+
+(* NB Sylvain: this issue with PExpand seems specific to kvx -- and not necessary here *)
+(* gen_bblocks can generate two bblocks if the ctl is a PExpand (since the PExpand must be alone in its block) *)
+(*
+Program Definition gen_bblocks (hd: list label) (c: bcode) (ctl: list instruction) :=
+ match (extract_ctl ctl) with
+ | None =>
+ (* XXX Que faire du Pnop ? *)
+ match c with
+ | nil => {| header := hd; body := Pnop::nil; exit := None |} :: nil
+ | i :: c => {| header := hd; body := ((i :: c) ++ extract_basic ctl); exit := None |} :: nil
+ end
+ (*| Some (i) =>*)
+ (*match c with*)
+ (*| nil => {| header := hd; body := nil; exit := Some (PExpand (Pbuiltin ef args res)) |} :: nil*)
+ (*| _ => {| header := hd; body := c; exit := None |} *)
+ (*:: {| header := nil; body := nil; exit := Some (PExpand (Pbuiltin ef args res)) |} :: nil*)
+ (*end*)
+ | Some ex => {| header := hd; body := (c ++ extract_basic ctl); exit := Some ex |} :: nil
+ end
+.
+*)
+
+(* XXX: the simulation proof may be complex with this pattern. We may fix this later *)
+Program Definition cons_bblocks (ll: list label) (bdy: list basic) (ex: option control) (k:bblocks): bblocks :=
+ match non_empty_bblockb bdy ex with
+ | true => {| header := ll; body:= bdy; exit := ex |}::k
+ | false => k
+ end.
+Obligation 1.
+ rewrite <- Heq_anonymous. constructor.
+Qed.
+
+Definition transl_control (f: Machblock.function) (ctl: control_flow_inst) : res (bcode*control) :=
+ match ctl with
+ | MBcall sig (inl r) => do r1 <- ireg_of r;
+ OK (nil, PCtlFlow (Pblr r1 sig))
+ | MBcall sig (inr symb) => OK (nil, PCtlFlow (Pbl symb sig))
+ | MBtailcall sig (inr symb) => OK(make_epilogue f, PCtlFlow (Pbs symb sig))
+ | MBtailcall sig (inl r) => do r1 <- ireg_of r;
+ OK (make_epilogue f, PCtlFlow (Pbr r1 sig))
+ | MBbuiltin ef args res => OK (nil, Pbuiltin ef (List.map (map_builtin_arg dreg_of) args) (map_builtin_res dreg_of res))
+ | MBgoto lbl => OK (nil, PCtlFlow (Pb lbl))
+ | MBcond cond args lbl => transl_cond_branch cond args lbl nil
+ | MBreturn => OK (make_epilogue f, PCtlFlow (Pret RA))
+ | MBjumptable arg tbl => do r <- ireg_of arg;
+ OK (nil, PCtlFlow (Pbtbl r tbl))
+ end.
+
+Definition transl_exit (f: Machblock.function) (ext: option control_flow_inst) : res (bcode*option control) :=
+ match ext with
+ Some ctl => do (b,c) <- transl_control f ctl; OK (b, Some c)
+ | None => OK (nil, None)
+ end.
+
+Definition transl_block (f: Machblock.function) (fb: Machblock.bblock) (ep: bool) (k:bblocks): res (list bblock) :=
+ let stub := false in (* TODO: FIXME *)
+ do (bdy, ex) <- transl_exit f fb.(Machblock.exit);
+ do bdy' <- transl_basic_code f fb.(Machblock.body) ep bdy;
+ OK (cons_bblocks fb.(Machblock.header) bdy' ex k)
+ .
+
+Fixpoint transl_blocks (f: Machblock.function) (lmb: Machblock.code) (ep: bool): res bblocks :=
+ match lmb with
+ | nil => OK nil
+ | mb :: lmb =>
+ do lb <- transl_blocks f lmb false; (* TODO: check [false] here *)
+ transl_block f mb (if Machblock.header mb then ep else false) lb (* TODO: check this *)
+ end.
+ (* OK (make_epilogue f ((Pret X0)::c nil)). (* STUB: TODO CHANGE ME ! *)*)
+
+(* Currently, we assume to be after the PseudoAsmblockproof.transf_program pass... *)
+Program Definition make_prologue (f: Machblock.function) (k:bblocks) :=
+ (*({| header := nil; body := Pallocframe f.(fn_stacksize) f.(fn_link_ofs) ::*)
+ (*storeptr_bc RA XSP f.(fn_retaddr_ofs) nil;*)
+ (*exit := None |} :: k).*)
+ Pallocframe f.(fn_stacksize) f.(fn_link_ofs) ::b
+ storeptr RA XSP f.(fn_retaddr_ofs) k.
+
+Definition transl_function (f: Machblock.function) : res Asmblock.function :=
+ do lb <- transl_blocks f f.(Machblock.fn_code) true;
+ OK (mkfunction f.(Machblock.fn_sig)
+ (make_prologue f lb)).
+
+Definition transf_fundef (f: Machblock.fundef) : res Asmblock.fundef :=
+ transf_partial_fundef transl_function f. (* TODO: do we need to check the size here ? (issue only in proofs) *)
+
+Definition transf_program (p: Machblock.program) : res Asmblock.program :=
+ transform_partial_program transf_fundef p.
+
diff --git a/aarch64/Asmblockgenproof.v b/aarch64/Asmblockgenproof.v
new file mode 100644
index 00000000..41082772
--- /dev/null
+++ b/aarch64/Asmblockgenproof.v
@@ -0,0 +1,1158 @@
+(** Correctness proof for aarch64/Asmblock generation: main proof.
+CURRENTLY A STUB !
+*)
+
+Require Import Coqlib Errors.
+Require Import Integers Floats AST Linking.
+Require Import Values Memory Events Globalenvs Smallstep.
+Require Import Op Locations Machblock Conventions PseudoAsmblock Asmblock IterList.
+Require Import PseudoAsmblockproof Asmblockgen.
+
+Module MB := Machblock.
+Module AB := Asmblock.
+
+Definition match_prog (p: MB.program) (tp: AB.program) :=
+ match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
+
+Lemma transf_program_match:
+ forall p tp, transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros. eapply match_transform_partial_program; eauto.
+Qed.
+
+Parameter next: MB.function -> Z -> Z.
+
+Section PRESERVATION.
+
+Lemma next_progress: forall (f:MB.function) (pos:Z), (pos < (next f pos))%Z.
+Admitted.
+
+Variable lk: aarch64_linker.
+Variable prog: Machblock.program.
+Variable tprog: Asmblock.program.
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+
+Hypothesis symbol_high_low: forall (id: ident) (ofs: ptrofs),
+ Val.addl (symbol_high lk id ofs) (symbol_low lk id ofs) = Genv.symbol_address tge id ofs.
+
+Lemma functions_bound_max_pos: forall fb f,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ (max_pos next f) <= Ptrofs.max_unsigned.
+Admitted.
+
+
+
+Lemma transf_program_correct:
+ forward_simulation (PseudoAsmblock.semantics next prog) (AB.semantics lk tprog).
+Admitted.
+
+End PRESERVATION.
+
+
+(* ORIGINAL aarch64/Asmgenproof file that needs to be adapted
+
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Xavier Leroy, Collège de France and INRIA Paris *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+(** Correctness proof for AArch64 code generation. *)
+
+Require Import Coqlib Errors.
+Require Import Integers Floats AST Linking.
+Require Import Values Memory Events Globalenvs Smallstep.
+Require Import Op Locations Mach Conventions Asm.
+Require Import Asmgen Asmgenproof0 Asmgenproof1.
+
+Definition match_prog (p: Mach.program) (tp: Asm.program) :=
+ match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
+
+Lemma transf_program_match:
+ forall p tp, transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros. eapply match_transform_partial_program; eauto.
+Qed.
+
+Section PRESERVATION.
+
+Variable prog: Mach.program.
+Variable tprog: Asm.program.
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma symbols_preserved:
+ forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
+Proof (Genv.find_symbol_match TRANSF).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_match TRANSF).
+
+Lemma functions_translated:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some f ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some tf /\ transf_fundef f = OK tf.
+Proof (Genv.find_funct_ptr_transf_partial TRANSF).
+
+Lemma functions_transl:
+ forall fb f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ Genv.find_funct_ptr tge fb = Some (Internal tf).
+Proof.
+ intros. exploit functions_translated; eauto. intros [tf' [A B]].
+ monadInv B. rewrite H0 in EQ; inv EQ; auto.
+Qed.
+
+(** * Properties of control flow *)
+
+Lemma transf_function_no_overflow:
+ forall f tf,
+ transf_function f = OK tf -> list_length_z tf.(fn_code) <= Ptrofs.max_unsigned.
+Proof.
+ intros. monadInv H. destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0.
+ omega.
+Qed.
+
+Lemma exec_straight_exec:
+ forall fb f c ep tf tc c' rs m rs' m',
+ transl_code_at_pc ge (rs PC) fb f c ep tf tc ->
+ exec_straight tge tf tc rs m c' rs' m' ->
+ plus step tge (State rs m) E0 (State rs' m').
+Proof.
+ intros. inv H.
+ eapply exec_straight_steps_1; eauto.
+ eapply transf_function_no_overflow; eauto.
+ eapply functions_transl; eauto.
+Qed.
+
+Lemma exec_straight_at:
+ forall fb f c ep tf tc c' ep' tc' rs m rs' m',
+ transl_code_at_pc ge (rs PC) fb f c ep tf tc ->
+ transl_code f c' ep' = OK tc' ->
+ exec_straight tge tf tc rs m tc' rs' m' ->
+ transl_code_at_pc ge (rs' PC) fb f c' ep' tf tc'.
+Proof.
+ intros. inv H.
+ exploit exec_straight_steps_2; eauto.
+ eapply transf_function_no_overflow; eauto.
+ eapply functions_transl; eauto.
+ intros [ofs' [PC' CT']].
+ rewrite PC'. constructor; auto.
+Qed.
+
+(** The following lemmas show that the translation from Mach to Asm
+ preserves labels, in the sense that the following diagram commutes:
+<<
+ translation
+ Mach code ------------------------ Asm instr sequence
+ | |
+ | Mach.find_label lbl find_label lbl |
+ | |
+ v v
+ Mach code tail ------------------- Asm instr seq tail
+ translation
+>>
+ The proof demands many boring lemmas showing that Asm constructor
+ functions do not introduce new labels.
+*)
+
+Section TRANSL_LABEL.
+
+Remark loadimm_z_label: forall sz rd l k, tail_nolabel k (loadimm_z sz rd l k).
+Proof.
+ intros; destruct l as [ | [n1 p1] l]; simpl; TailNoLabel.
+ induction l as [ | [n p] l]; simpl; TailNoLabel.
+Qed.
+
+Remark loadimm_n_label: forall sz rd l k, tail_nolabel k (loadimm_n sz rd l k).
+Proof.
+ intros; destruct l as [ | [n1 p1] l]; simpl; TailNoLabel.
+ induction l as [ | [n p] l]; simpl; TailNoLabel.
+Qed.
+
+Remark loadimm_label: forall sz rd n k, tail_nolabel k (loadimm sz rd n k).
+Proof.
+ unfold loadimm; intros. destruct Nat.leb; [apply loadimm_z_label|apply loadimm_n_label].
+Qed.
+Hint Resolve loadimm_label: labels.
+
+Remark loadimm32_label: forall r n k, tail_nolabel k (loadimm32 r n k).
+Proof.
+ unfold loadimm32; intros. destruct (is_logical_imm32 n); TailNoLabel.
+Qed.
+Hint Resolve loadimm32_label: labels.
+
+Remark loadimm64_label: forall r n k, tail_nolabel k (loadimm64 r n k).
+Proof.
+ unfold loadimm64; intros. destruct (is_logical_imm64 n); TailNoLabel.
+Qed.
+Hint Resolve loadimm64_label: labels.
+
+Remark addimm_aux: forall insn rd r1 n k,
+ (forall rd r1 n, nolabel (insn rd r1 n)) ->
+ tail_nolabel k (addimm_aux insn rd r1 n k).
+Proof.
+ unfold addimm_aux; intros.
+ destruct Z.eqb. TailNoLabel. destruct Z.eqb; TailNoLabel.
+Qed.
+
+Remark addimm32_label: forall rd r1 n k, tail_nolabel k (addimm32 rd r1 n k).
+Proof.
+ unfold addimm32; intros.
+ destruct Int.eq. apply addimm_aux; intros; red; auto.
+ destruct Int.eq. apply addimm_aux; intros; red; auto.
+ destruct Int.lt; eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+Hint Resolve addimm32_label: labels.
+
+Remark addimm64_label: forall rd r1 n k, tail_nolabel k (addimm64 rd r1 n k).
+Proof.
+ unfold addimm64; intros.
+ destruct Int64.eq. apply addimm_aux; intros; red; auto.
+ destruct Int64.eq. apply addimm_aux; intros; red; auto.
+ destruct Int64.lt; eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+Hint Resolve addimm64_label: labels.
+
+Remark logicalimm32_label: forall insn1 insn2 rd r1 n k,
+ (forall rd r1 n, nolabel (insn1 rd r1 n)) ->
+ (forall rd r1 r2 s, nolabel (insn2 rd r1 r2 s)) ->
+ tail_nolabel k (logicalimm32 insn1 insn2 rd r1 n k).
+Proof.
+ unfold logicalimm32; intros.
+ destruct (is_logical_imm32 n). TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+
+Remark logicalimm64_label: forall insn1 insn2 rd r1 n k,
+ (forall rd r1 n, nolabel (insn1 rd r1 n)) ->
+ (forall rd r1 r2 s, nolabel (insn2 rd r1 r2 s)) ->
+ tail_nolabel k (logicalimm64 insn1 insn2 rd r1 n k).
+Proof.
+ unfold logicalimm64; intros.
+ destruct (is_logical_imm64 n). TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+
+Remark move_extended_label: forall rd r1 ex a k, tail_nolabel k (move_extended rd r1 ex a k).
+Proof.
+ unfold move_extended, move_extended_base; intros. destruct Int.eq, ex; TailNoLabel.
+Qed.
+Hint Resolve move_extended_label: labels.
+
+Remark arith_extended_label: forall insnX insnS rd r1 r2 ex a k,
+ (forall rd r1 r2 x, nolabel (insnX rd r1 r2 x)) ->
+ (forall rd r1 r2 s, nolabel (insnS rd r1 r2 s)) ->
+ tail_nolabel k (arith_extended insnX insnS rd r1 r2 ex a k).
+Proof.
+ unfold arith_extended; intros. destruct Int.ltu.
+ TailNoLabel.
+ destruct ex; simpl; TailNoLabel.
+Qed.
+
+Remark loadsymbol_label: forall r id ofs k, tail_nolabel k (loadsymbol r id ofs k).
+Proof.
+ intros; unfold loadsymbol.
+ destruct (Archi.pic_code tt); TailNoLabel. destruct Ptrofs.eq; TailNoLabel.
+Qed.
+Hint Resolve loadsymbol_label: labels.
+
+Remark transl_cond_label: forall cond args k c,
+ transl_cond cond args k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_cond; intros; destruct cond; TailNoLabel.
+- destruct is_arith_imm32; TailNoLabel. destruct is_arith_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_arith_imm32; TailNoLabel. destruct is_arith_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_logical_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_logical_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_arith_imm64; TailNoLabel. destruct is_arith_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_arith_imm64; TailNoLabel. destruct is_arith_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_logical_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+- destruct is_logical_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+
+Remark transl_cond_branch_default_label: forall cond args lbl k c,
+ transl_cond_branch_default cond args lbl k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_cond_branch_default; intros.
+ eapply tail_nolabel_trans; [eapply transl_cond_label;eauto|TailNoLabel].
+Qed.
+Hint Resolve transl_cond_branch_default_label: labels.
+
+Remark transl_cond_branch_label: forall cond args lbl k c,
+ transl_cond_branch cond args lbl k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_cond_branch; intros; destruct args; TailNoLabel; destruct cond; TailNoLabel.
+- destruct c0; TailNoLabel.
+- destruct c0; TailNoLabel.
+- destruct (Int.is_power2 n); TailNoLabel.
+- destruct (Int.is_power2 n); TailNoLabel.
+- destruct c0; TailNoLabel.
+- destruct c0; TailNoLabel.
+- destruct (Int64.is_power2' n); TailNoLabel.
+- destruct (Int64.is_power2' n); TailNoLabel.
+Qed.
+
+Remark transl_op_label:
+ forall op args r k c,
+ transl_op op args r k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_op; intros; destruct op; TailNoLabel.
+- destruct (preg_of r); try discriminate; destruct (preg_of m); inv H; TailNoLabel.
+- destruct (Float.eq_dec n Float.zero); TailNoLabel.
+- destruct (Float32.eq_dec n Float32.zero); TailNoLabel.
+- apply logicalimm32_label; unfold nolabel; auto.
+- apply logicalimm32_label; unfold nolabel; auto.
+- apply logicalimm32_label; unfold nolabel; auto.
+- unfold shrx32. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
+- apply arith_extended_label; unfold nolabel; auto.
+- apply arith_extended_label; unfold nolabel; auto.
+- apply logicalimm64_label; unfold nolabel; auto.
+- apply logicalimm64_label; unfold nolabel; auto.
+- apply logicalimm64_label; unfold nolabel; auto.
+- unfold shrx64. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
+- eapply tail_nolabel_trans. eapply transl_cond_label; eauto. TailNoLabel.
+- destruct (preg_of r); try discriminate; TailNoLabel;
+ (eapply tail_nolabel_trans; [eapply transl_cond_label; eauto | TailNoLabel]).
+Qed.
+
+Remark transl_addressing_label:
+ forall sz addr args insn k c,
+ transl_addressing sz addr args insn k = OK c ->
+ (forall ad, nolabel (insn ad)) ->
+ tail_nolabel k c.
+Proof.
+ unfold transl_addressing; intros; destruct addr; TailNoLabel;
+ eapply tail_nolabel_trans; TailNoLabel.
+ eapply tail_nolabel_trans. apply arith_extended_label; unfold nolabel; auto. TailNoLabel.
+Qed.
+
+Remark transl_load_label:
+ forall trap chunk addr args dst k c,
+ transl_load trap chunk addr args dst k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_load; intros; destruct trap; try discriminate; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
+Qed.
+
+Remark transl_store_label:
+ forall chunk addr args src k c,
+ transl_store chunk addr args src k = OK c -> tail_nolabel k c.
+Proof.
+ unfold transl_store; intros; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
+Qed.
+
+Remark indexed_memory_access_label:
+ forall insn sz base ofs k,
+ (forall ad, nolabel (insn ad)) ->
+ tail_nolabel k (indexed_memory_access insn sz base ofs k).
+Proof.
+ unfold indexed_memory_access; intros. destruct offset_representable.
+ TailNoLabel.
+ eapply tail_nolabel_trans; TailNoLabel.
+Qed.
+
+Remark loadind_label:
+ forall base ofs ty dst k c,
+ loadind base ofs ty dst k = OK c -> tail_nolabel k c.
+Proof.
+ unfold loadind; intros.
+ destruct ty, (preg_of dst); inv H; apply indexed_memory_access_label; intros; exact I.
+Qed.
+
+Remark storeind_label:
+ forall src base ofs ty k c,
+ storeind src base ofs ty k = OK c -> tail_nolabel k c.
+Proof.
+ unfold storeind; intros.
+ destruct ty, (preg_of src); inv H; apply indexed_memory_access_label; intros; exact I.
+Qed.
+
+Remark loadptr_label:
+ forall base ofs dst k, tail_nolabel k (loadptr base ofs dst k).
+Proof.
+ intros. apply indexed_memory_access_label. unfold nolabel; auto.
+Qed.
+
+Remark storeptr_label:
+ forall src base ofs k, tail_nolabel k (storeptr src base ofs k).
+Proof.
+ intros. apply indexed_memory_access_label. unfold nolabel; auto.
+Qed.
+
+Remark make_epilogue_label:
+ forall f k, tail_nolabel k (make_epilogue f k).
+Proof.
+ unfold make_epilogue; intros.
+ (* FIXME destruct is_leaf_function.
+ { TailNoLabel. } *)
+ eapply tail_nolabel_trans.
+ apply loadptr_label.
+ TailNoLabel.
+Qed.
+
+Lemma transl_instr_label:
+ forall f i ep k c,
+ transl_instr f i ep k = OK c ->
+ match i with Mlabel lbl => c = Plabel lbl :: k | _ => tail_nolabel k c end.
+Proof.
+ unfold transl_instr; intros; destruct i; TailNoLabel.
+- eapply loadind_label; eauto.
+- eapply storeind_label; eauto.
+- destruct ep. eapply loadind_label; eauto.
+ eapply tail_nolabel_trans. apply loadptr_label. eapply loadind_label; eauto.
+- eapply transl_op_label; eauto.
+- eapply transl_load_label; eauto.
+- eapply transl_store_label; eauto.
+- destruct s0; monadInv H; TailNoLabel.
+- destruct s0; monadInv H; (eapply tail_nolabel_trans; [eapply make_epilogue_label|TailNoLabel]).
+- eapply transl_cond_branch_label; eauto.
+- eapply tail_nolabel_trans; [eapply make_epilogue_label|TailNoLabel].
+Qed.
+
+Lemma transl_instr_label':
+ forall lbl f i ep k c,
+ transl_instr f i ep k = OK c ->
+ find_label lbl c = if Mach.is_label lbl i then Some k else find_label lbl k.
+Proof.
+ intros. exploit transl_instr_label; eauto.
+ destruct i; try (intros [A B]; apply B).
+ intros. subst c. simpl. auto.
+Qed.
+
+Lemma transl_code_label:
+ forall lbl f c ep tc,
+ transl_code f c ep = OK tc ->
+ match Mach.find_label lbl c with
+ | None => find_label lbl tc = None
+ | Some c' => exists tc', find_label lbl tc = Some tc' /\ transl_code f c' false = OK tc'
+ end.
+Proof.
+ induction c; simpl; intros.
+ inv H. auto.
+ monadInv H. rewrite (transl_instr_label' lbl _ _ _ _ _ EQ0).
+ generalize (Mach.is_label_correct lbl a).
+ destruct (Mach.is_label lbl a); intros.
+ subst a. simpl in EQ. exists x; auto.
+ eapply IHc; eauto.
+Qed.
+
+Lemma transl_find_label:
+ forall lbl f tf,
+ transf_function f = OK tf ->
+ match Mach.find_label lbl f.(Mach.fn_code) with
+ | None => find_label lbl tf.(fn_code) = None
+ | Some c => exists tc, find_label lbl tf.(fn_code) = Some tc /\ transl_code f c false = OK tc
+ end.
+Proof.
+ intros. monadInv H. destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0.
+ monadInv EQ. rewrite transl_code'_transl_code in EQ0. unfold fn_code.
+ simpl. destruct (storeptr_label X30 XSP (fn_retaddr_ofs f) x) as [A B]; rewrite B.
+ eapply transl_code_label; eauto.
+Qed.
+
+End TRANSL_LABEL.
+
+(** A valid branch in a piece of Mach code translates to a valid ``go to''
+ transition in the generated Asm code. *)
+
+Lemma find_label_goto_label:
+ forall f tf lbl rs m c' b ofs,
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ transf_function f = OK tf ->
+ rs PC = Vptr b ofs ->
+ Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
+ exists tc', exists rs',
+ goto_label tf lbl rs m = Next rs' m
+ /\ transl_code_at_pc ge (rs' PC) b f c' false tf tc'
+ /\ forall r, r <> PC -> rs'#r = rs#r.
+Proof.
+ intros. exploit (transl_find_label lbl f tf); eauto. rewrite H2.
+ intros [tc [A B]].
+ exploit label_pos_code_tail; eauto. instantiate (1 := 0).
+ intros [pos' [P [Q R]]].
+ exists tc; exists (rs#PC <- (Vptr b (Ptrofs.repr pos'))).
+ split. unfold goto_label. rewrite P. rewrite H1. auto.
+ split. rewrite Pregmap.gss. constructor; auto.
+ rewrite Ptrofs.unsigned_repr. replace (pos' - 0) with pos' in Q.
+ auto. omega.
+ generalize (transf_function_no_overflow _ _ H0). omega.
+ intros. apply Pregmap.gso; auto.
+Qed.
+
+(** Existence of return addresses *)
+
+Lemma return_address_exists:
+ forall f sg ros c, is_tail (Mcall sg ros :: c) f.(Mach.fn_code) ->
+ exists ra, return_address_offset f c ra.
+Proof.
+ intros. eapply Asmgenproof0.return_address_exists; eauto.
+- intros. exploit transl_instr_label; eauto.
+ destruct i; try (intros [A B]; apply A). intros. subst c0. repeat constructor.
+- intros. monadInv H0.
+ destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0. monadInv EQ.
+ rewrite transl_code'_transl_code in EQ0.
+ exists x; exists true; split; auto. unfold fn_code.
+ constructor. apply (storeptr_label X30 XSP (fn_retaddr_ofs f0) x).
+- exact transf_function_no_overflow.
+Qed.
+
+(** * Proof of semantic preservation *)
+
+(** Semantic preservation is proved using simulation diagrams
+ of the following form.
+<<
+ st1 --------------- st2
+ | |
+ t| *|t
+ | |
+ v v
+ st1'--------------- st2'
+>>
+ The invariant is the [match_states] predicate below, which includes:
+- The Asm code pointed by the PC register is the translation of
+ the current Mach code sequence.
+- Mach register values and Asm register values agree.
+*)
+
+Inductive match_states: Mach.state -> Asm.state -> Prop :=
+ | match_states_intro:
+ forall s fb sp c ep ms m m' rs f tf tc
+ (STACKS: match_stack ge s)
+ (FIND: Genv.find_funct_ptr ge fb = Some (Internal f))
+ (MEXT: Mem.extends m m')
+ (AT: transl_code_at_pc ge (rs PC) fb f c ep tf tc)
+ (AG: agree ms sp rs)
+ (DXP: ep = true -> rs#X29 = parent_sp s)
+ (LEAF: is_leaf_function f = true -> rs#RA = parent_ra s),
+ match_states (Mach.State s fb sp c ms m)
+ (Asm.State rs m')
+ | match_states_call:
+ forall s fb ms m m' rs
+ (STACKS: match_stack ge s)
+ (MEXT: Mem.extends m m')
+ (AG: agree ms (parent_sp s) rs)
+ (ATPC: rs PC = Vptr fb Ptrofs.zero)
+ (ATLR: rs RA = parent_ra s),
+ match_states (Mach.Callstate s fb ms m)
+ (Asm.State rs m')
+ | match_states_return:
+ forall s ms m m' rs
+ (STACKS: match_stack ge s)
+ (MEXT: Mem.extends m m')
+ (AG: agree ms (parent_sp s) rs)
+ (ATPC: rs PC = parent_ra s),
+ match_states (Mach.Returnstate s ms m)
+ (Asm.State rs m').
+
+Lemma exec_straight_steps:
+ forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2,
+ match_stack ge s ->
+ Mem.extends m2 m2' ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
+ (forall k c (TR: transl_instr f i ep k = OK c),
+ exists rs2,
+ exec_straight tge tf c rs1 m1' k rs2 m2'
+ /\ agree ms2 sp rs2
+ /\ (it1_is_parent ep i = true -> rs2#X29 = parent_sp s)
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
+ exists st',
+ plus step tge (State rs1 m1') E0 st' /\
+ match_states (Mach.State s fb sp c ms2 m2) st'.
+Proof.
+ intros. inversion H2. subst. monadInv H7.
+ exploit H3; eauto. intros [rs2 [A [B [C D]]]].
+ exists (State rs2 m2'); split.
+ - eapply exec_straight_exec; eauto.
+ - econstructor; eauto. eapply exec_straight_at; eauto.
+Qed.
+
+Lemma exec_straight_steps_goto:
+ forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2 lbl c',
+ match_stack ge s ->
+ Mem.extends m2 m2' ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
+ transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
+ it1_is_parent ep i = false ->
+ (forall k c (TR: transl_instr f i ep k = OK c),
+ exists jmp, exists k', exists rs2,
+ exec_straight tge tf c rs1 m1' (jmp :: k') rs2 m2'
+ /\ agree ms2 sp rs2
+ /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
+ exists st',
+ plus step tge (State rs1 m1') E0 st' /\
+ match_states (Mach.State s fb sp c' ms2 m2) st'.
+Proof.
+ intros. inversion H3. subst. monadInv H9.
+ exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
+ generalize (functions_transl _ _ _ H7 H8); intro FN.
+ generalize (transf_function_no_overflow _ _ H8); intro NOOV.
+ exploit exec_straight_steps_2; eauto.
+ intros [ofs' [PC2 CT2]].
+ exploit find_label_goto_label; eauto.
+ intros [tc' [rs3 [GOTO [AT' OTH]]]].
+ exists (State rs3 m2'); split.
+ eapply plus_right'.
+ eapply exec_straight_steps_1; eauto.
+ econstructor; eauto.
+ eapply find_instr_tail. eauto.
+ rewrite C. eexact GOTO.
+ traceEq.
+ econstructor; eauto.
+ apply agree_exten with rs2; auto with asmgen.
+ congruence.
+ rewrite OTH by congruence; auto.
+Qed.
+
+Lemma exec_straight_opt_steps_goto:
+ forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2 lbl c',
+ match_stack ge s ->
+ Mem.extends m2 m2' ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
+ transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
+ it1_is_parent ep i = false ->
+ (forall k c (TR: transl_instr f i ep k = OK c),
+ exists jmp, exists k', exists rs2,
+ exec_straight_opt tge tf c rs1 m1' (jmp :: k') rs2 m2'
+ /\ agree ms2 sp rs2
+ /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
+ /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
+ exists st',
+ plus step tge (State rs1 m1') E0 st' /\
+ match_states (Mach.State s fb sp c' ms2 m2) st'.
+Proof.
+ intros. inversion H3. subst. monadInv H9.
+ exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
+ generalize (functions_transl _ _ _ H7 H8); intro FN.
+ generalize (transf_function_no_overflow _ _ H8); intro NOOV.
+ inv A.
+- exploit find_label_goto_label; eauto.
+ intros [tc' [rs3 [GOTO [AT' OTH]]]].
+ exists (State rs3 m2'); split.
+ apply plus_one. econstructor; eauto.
+ eapply find_instr_tail. eauto.
+ rewrite C. eexact GOTO.
+ econstructor; eauto.
+ apply agree_exten with rs2; auto with asmgen.
+ congruence.
+ rewrite OTH by congruence; auto.
+- exploit exec_straight_steps_2; eauto.
+ intros [ofs' [PC2 CT2]].
+ exploit find_label_goto_label; eauto.
+ intros [tc' [rs3 [GOTO [AT' OTH]]]].
+ exists (State rs3 m2'); split.
+ eapply plus_right'.
+ eapply exec_straight_steps_1; eauto.
+ econstructor; eauto.
+ eapply find_instr_tail. eauto.
+ rewrite C. eexact GOTO.
+ traceEq.
+ econstructor; eauto.
+ apply agree_exten with rs2; auto with asmgen.
+ congruence.
+ rewrite OTH by congruence; auto.
+Qed.
+
+(** We need to show that, in the simulation diagram, we cannot
+ take infinitely many Mach transitions that correspond to zero
+ transitions on the Asm side. Actually, all Mach transitions
+ correspond to at least one Asm transition, except the
+ transition from [Machsem.Returnstate] to [Machsem.State].
+ So, the following integer measure will suffice to rule out
+ the unwanted behaviour. *)
+
+Definition measure (s: Mach.state) : nat :=
+ match s with
+ | Mach.State _ _ _ _ _ _ => 0%nat
+ | Mach.Callstate _ _ _ _ => 0%nat
+ | Mach.Returnstate _ _ _ => 1%nat
+ end.
+
+Remark preg_of_not_X29: forall r, negb (mreg_eq r R29) = true -> IR X29 <> preg_of r.
+Proof.
+ intros. change (IR X29) with (preg_of R29). red; intros.
+ exploit preg_of_injective; eauto. intros; subst r; discriminate.
+Qed.
+
+Lemma sp_val': forall ms sp rs, agree ms sp rs -> sp = rs XSP.
+Proof.
+ intros. eapply sp_val; eauto.
+Qed.
+
+(** This is the simulation diagram. We prove it by case analysis on the Mach transition. *)
+
+Theorem step_simulation:
+ forall S1 t S2, Mach.step return_address_offset ge S1 t S2 ->
+ forall S1' (MS: match_states S1 S1') (WF: wf_state ge S1),
+ (exists S2', plus step tge S1' t S2' /\ match_states S2 S2')
+ \/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 S1')%nat.
+Proof.
+ induction 1; intros; inv MS.
+
+- (* Mlabel *)
+ left; eapply exec_straight_steps; eauto; intros.
+ monadInv TR. econstructor; split. apply exec_straight_one. simpl; eauto. auto.
+ split. { apply agree_nextinstr; auto. }
+ split. { simpl; congruence. }
+ rewrite nextinstr_inv by congruence; assumption.
+
+- (* Mgetstack *)
+ unfold load_stack in H.
+ exploit Mem.loadv_extends; eauto. intros [v' [A B]].
+ rewrite (sp_val _ _ _ AG) in A.
+ left; eapply exec_straight_steps; eauto. intros. simpl in TR.
+ exploit loadind_correct; eauto with asmgen. intros [rs' [P [Q [R S]]]].
+ exists rs'; split. eauto.
+ split. { eapply agree_set_mreg; eauto with asmgen. congruence. }
+ split. { simpl; congruence. }
+ rewrite S. assumption.
+
+- (* Msetstack *)
+ unfold store_stack in H.
+ assert (Val.lessdef (rs src) (rs0 (preg_of src))) by (eapply preg_val; eauto).
+ exploit Mem.storev_extends; eauto. intros [m2' [A B]].
+ left; eapply exec_straight_steps; eauto.
+ rewrite (sp_val _ _ _ AG) in A. intros. simpl in TR.
+ exploit storeind_correct; eauto with asmgen. intros [rs' [P [Q R]]].
+ exists rs'; split. eauto.
+ split. eapply agree_undef_regs; eauto with asmgen.
+ simpl; intros.
+ split. rewrite Q; auto with asmgen.
+ rewrite R. assumption.
+
+- (* Mgetparam *)
+ assert (f0 = f) by congruence; subst f0.
+ unfold load_stack in *.
+ exploit Mem.loadv_extends. eauto. eexact H0. auto.
+ intros [parent' [A B]]. rewrite (sp_val' _ _ _ AG) in A.
+ exploit lessdef_parent_sp; eauto. clear B; intros B; subst parent'.
+ exploit Mem.loadv_extends. eauto. eexact H1. auto.
+ intros [v' [C D]].
+Opaque loadind.
+ left; eapply exec_straight_steps; eauto; intros. monadInv TR.
+ destruct ep.
+(* X30 contains parent *)
+ exploit loadind_correct. eexact EQ.
+ instantiate (2 := rs0). simpl; rewrite DXP; eauto. simpl; congruence.
+ intros [rs1 [P [Q [R S]]]].
+ exists rs1; split. eauto.
+ split. eapply agree_set_mreg. eapply agree_set_mreg; eauto. congruence. auto with asmgen.
+ simpl; split; intros.
+ { rewrite R; auto with asmgen.
+ apply preg_of_not_X29; auto.
+ }
+ { rewrite S; auto. }
+
+(* X30 does not contain parent *)
+ exploit loadptr_correct. eexact A. simpl; congruence. intros [rs1 [P [Q R]]].
+ exploit loadind_correct. eexact EQ. instantiate (2 := rs1). simpl; rewrite Q. eauto. simpl; congruence.
+ intros [rs2 [S [T [U V]]]].
+ exists rs2; split. eapply exec_straight_trans; eauto.
+ split. eapply agree_set_mreg. eapply agree_set_mreg. eauto. eauto.
+ instantiate (1 := rs1#X29 <- (rs2#X29)). intros.
+ rewrite Pregmap.gso; auto with asmgen.
+ congruence.
+ intros. unfold Pregmap.set. destruct (PregEq.eq r' X29). congruence. auto with asmgen.
+ split; simpl; intros. rewrite U; auto with asmgen.
+ apply preg_of_not_X29; auto.
+ rewrite V. rewrite R by congruence. auto.
+
+- (* Mop *)
+ assert (eval_operation tge sp op (map rs args) m = Some v).
+ { rewrite <- H. apply eval_operation_preserved. exact symbols_preserved. }
+ exploit eval_operation_lessdef. eapply preg_vals; eauto. eauto. eexact H0.
+ intros [v' [A B]]. rewrite (sp_val _ _ _ AG) in A.
+ left; eapply exec_straight_steps; eauto; intros. simpl in TR.
+ exploit transl_op_correct; eauto. intros [rs2 [P [Q [R S]]]].
+ exists rs2; split. eauto. split.
+ apply agree_set_undef_mreg with rs0; auto.
+ apply Val.lessdef_trans with v'; auto.
+ split; simpl; intros. InvBooleans.
+ rewrite R; auto. apply preg_of_not_X29; auto.
+Local Transparent destroyed_by_op.
+ destruct op; try exact I; simpl; congruence.
+ rewrite S.
+ auto.
+- (* Mload *)
+ destruct trap.
+ {
+ assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
+ { rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved. }
+ exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
+ intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
+ exploit Mem.loadv_extends; eauto. intros [v' [C D]].
+ left; eapply exec_straight_steps; eauto; intros. simpl in TR.
+ exploit transl_load_correct; eauto. intros [rs2 [P [Q [R S]]]].
+ exists rs2; split. eauto.
+ split. eapply agree_set_undef_mreg; eauto. congruence.
+ split. simpl; congruence.
+ rewrite S. assumption.
+ }
+
+ (* Mload notrap1 *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mload notrap *)
+ inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
+
+- (* Mstore *)
+ assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
+ { rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved. }
+ exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
+ intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
+ assert (Val.lessdef (rs src) (rs0 (preg_of src))) by (eapply preg_val; eauto).
+ exploit Mem.storev_extends; eauto. intros [m2' [C D]].
+ left; eapply exec_straight_steps; eauto.
+ intros. simpl in TR. exploit transl_store_correct; eauto. intros [rs2 [P [Q R]]].
+ exists rs2; split. eauto.
+ split. eapply agree_undef_regs; eauto with asmgen.
+ split. simpl; congruence.
+ rewrite R. assumption.
+
+- (* Mcall *)
+ assert (f0 = f) by congruence. subst f0.
+ inv AT.
+ assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
+ { eapply transf_function_no_overflow; eauto. }
+ destruct ros as [rf|fid]; simpl in H; monadInv H5.
++ (* Indirect call *)
+ assert (rs rf = Vptr f' Ptrofs.zero).
+ { destruct (rs rf); try discriminate.
+ revert H; predSpec Ptrofs.eq Ptrofs.eq_spec i Ptrofs.zero; intros; congruence. }
+ assert (rs0 x0 = Vptr f' Ptrofs.zero).
+ { exploit ireg_val; eauto. rewrite H5; intros LD; inv LD; auto. }
+ generalize (code_tail_next_int _ _ _ _ NOOV H6). intro CT1.
+ assert (TCA: transl_code_at_pc ge (Vptr fb (Ptrofs.add ofs Ptrofs.one)) fb f c false tf x).
+ { econstructor; eauto. }
+ exploit return_address_offset_correct; eauto. intros; subst ra.
+ left; econstructor; split.
+ apply plus_one. eapply exec_step_internal. Simpl. rewrite <- H2; simpl; eauto.
+ eapply functions_transl; eauto. eapply find_instr_tail; eauto.
+ simpl. eauto.
+ econstructor; eauto.
+ econstructor; eauto.
+ eapply agree_sp_def; eauto.
+ simpl. eapply agree_exten; eauto. intros. Simpl.
+ Simpl. rewrite <- H2. auto.
++ (* Direct call *)
+ generalize (code_tail_next_int _ _ _ _ NOOV H6). intro CT1.
+ assert (TCA: transl_code_at_pc ge (Vptr fb (Ptrofs.add ofs Ptrofs.one)) fb f c false tf x).
+ econstructor; eauto.
+ exploit return_address_offset_correct; eauto. intros; subst ra.
+ left; econstructor; split.
+ apply plus_one. eapply exec_step_internal. eauto.
+ eapply functions_transl; eauto. eapply find_instr_tail; eauto.
+ simpl. unfold Genv.symbol_address. rewrite symbols_preserved. rewrite H. eauto.
+ econstructor; eauto.
+ econstructor; eauto.
+ eapply agree_sp_def; eauto.
+ simpl. eapply agree_exten; eauto. intros. Simpl.
+ Simpl. rewrite <- H2. auto.
+
+- (* Mtailcall *)
+ assert (f0 = f) by congruence. subst f0.
+ inversion AT; subst.
+ assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
+ { eapply transf_function_no_overflow; eauto. }
+ exploit Mem.loadv_extends. eauto. eexact H1. auto. simpl. intros [parent' [A B]].
+ destruct ros as [rf|fid]; simpl in H; monadInv H7.
++ (* Indirect call *)
+ assert (rs rf = Vptr f' Ptrofs.zero).
+ { destruct (rs rf); try discriminate.
+ revert H; predSpec Ptrofs.eq Ptrofs.eq_spec i Ptrofs.zero; intros; congruence. }
+ assert (rs0 x0 = Vptr f' Ptrofs.zero).
+ { exploit ireg_val; eauto. rewrite H7; intros LD; inv LD; auto. }
+ exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
+ exploit exec_straight_steps_2; eauto using functions_transl.
+ intros (ofs' & P & Q).
+ left; econstructor; split.
+ (* execution *)
+ eapply plus_right'. eapply exec_straight_exec; eauto.
+ econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
+ simpl. reflexivity.
+ traceEq.
+ (* match states *)
+ econstructor; eauto.
+ apply agree_set_other; auto with asmgen.
+ Simpl. rewrite Z by (rewrite <- (ireg_of_eq _ _ EQ1); eauto with asmgen). assumption.
++ (* Direct call *)
+ exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
+ exploit exec_straight_steps_2; eauto using functions_transl.
+ intros (ofs' & P & Q).
+ left; econstructor; split.
+ (* execution *)
+ eapply plus_right'. eapply exec_straight_exec; eauto.
+ econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
+ simpl. reflexivity.
+ traceEq.
+ (* match states *)
+ econstructor; eauto.
+ apply agree_set_other; auto with asmgen.
+ Simpl. unfold Genv.symbol_address. rewrite symbols_preserved. rewrite H. auto.
+
+- (* Mbuiltin *)
+ inv AT. monadInv H4.
+ exploit functions_transl; eauto. intro FN.
+ generalize (transf_function_no_overflow _ _ H3); intro NOOV.
+ exploit builtin_args_match; eauto. intros [vargs' [P Q]].
+ exploit external_call_mem_extends; eauto.
+ intros [vres' [m2' [A [B [C D]]]]].
+ left. econstructor; split. apply plus_one.
+ eapply exec_step_builtin. eauto. eauto.
+ eapply find_instr_tail; eauto.
+ erewrite <- sp_val by eauto.
+ eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ eauto.
+ econstructor; eauto.
+ instantiate (2 := tf); instantiate (1 := x).
+ unfold nextinstr. rewrite Pregmap.gss.
+ rewrite set_res_other. rewrite undef_regs_other_2.
+ rewrite <- H1. simpl. econstructor; eauto.
+ eapply code_tail_next_int; eauto.
+ rewrite preg_notin_charact. intros. auto with asmgen.
+ auto with asmgen.
+ apply agree_nextinstr. eapply agree_set_res; auto.
+ eapply agree_undef_regs; eauto. intros. rewrite undef_regs_other_2; auto.
+ congruence.
+
+ Simpl.
+ rewrite set_res_other by trivial.
+ rewrite undef_regs_other.
+ assumption.
+ intro.
+ rewrite in_map_iff.
+ intros (x0 & PREG & IN).
+ subst r'.
+ intro.
+ apply (preg_of_not_RA x0).
+ congruence.
+
+- (* Mgoto *)
+ assert (f0 = f) by congruence. subst f0.
+ inv AT. monadInv H4.
+ exploit find_label_goto_label; eauto. intros [tc' [rs' [GOTO [AT2 INV]]]].
+ left; exists (State rs' m'); split.
+ apply plus_one. econstructor; eauto.
+ eapply functions_transl; eauto.
+ eapply find_instr_tail; eauto.
+ simpl; eauto.
+ econstructor; eauto.
+ eapply agree_exten; eauto with asmgen.
+ congruence.
+
+ rewrite INV by congruence.
+ assumption.
+
+- (* Mcond true *)
+ assert (f0 = f) by congruence. subst f0.
+ exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
+ left; eapply exec_straight_opt_steps_goto; eauto.
+ intros. simpl in TR.
+ exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
+ exists jmp; exists k; exists rs'.
+ split. eexact A.
+ split. apply agree_exten with rs0; auto with asmgen.
+ split.
+ exact B.
+ rewrite D. exact LEAF.
+
+- (* Mcond false *)
+ exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
+ left; eapply exec_straight_steps; eauto. intros. simpl in TR.
+ exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
+ econstructor; split.
+ eapply exec_straight_opt_right. eexact A. apply exec_straight_one. eexact B. auto.
+ split. apply agree_exten with rs0; auto. intros. Simpl.
+ split.
+ simpl; congruence.
+ Simpl. rewrite D.
+ exact LEAF.
+
+- (* Mjumptable *)
+ assert (f0 = f) by congruence. subst f0.
+ inv AT. monadInv H6.
+ exploit functions_transl; eauto. intro FN.
+ generalize (transf_function_no_overflow _ _ H5); intro NOOV.
+ exploit find_label_goto_label. eauto. eauto.
+ instantiate (2 := rs0#X16 <- Vundef #X17 <- Vundef).
+ Simpl. eauto.
+ eauto.
+ intros [tc' [rs' [A [B C]]]].
+ exploit ireg_val; eauto. rewrite H. intros LD; inv LD.
+ left; econstructor; split.
+ apply plus_one. econstructor; eauto.
+ eapply find_instr_tail; eauto.
+ simpl. Simpl. rewrite <- H9. unfold Mach.label in H0; unfold label; rewrite H0. eexact A.
+ econstructor; eauto.
+ eapply agree_undef_regs; eauto.
+ simpl. intros. rewrite C; auto with asmgen. Simpl.
+ congruence.
+
+ rewrite C by congruence.
+ repeat rewrite Pregmap.gso by congruence.
+ assumption.
+
+- (* Mreturn *)
+ assert (f0 = f) by congruence. subst f0.
+ inversion AT; subst. simpl in H6; monadInv H6.
+ assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
+ eapply transf_function_no_overflow; eauto.
+ exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
+ exploit exec_straight_steps_2; eauto using functions_transl.
+ intros (ofs' & P & Q).
+ left; econstructor; split.
+ (* execution *)
+ eapply plus_right'. eapply exec_straight_exec; eauto.
+ econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
+ simpl. reflexivity.
+ traceEq.
+ (* match states *)
+ econstructor; eauto.
+ apply agree_set_other; auto with asmgen.
+
+- (* internal function *)
+
+ exploit functions_translated; eauto. intros [tf [A B]]. monadInv B.
+ generalize EQ; intros EQ'. monadInv EQ'.
+ destruct (zlt Ptrofs.max_unsigned (list_length_z x0.(fn_code))); inversion EQ1. clear EQ1. subst x0.
+ unfold store_stack in *.
+ exploit Mem.alloc_extends. eauto. eauto. apply Z.le_refl. apply Z.le_refl.
+ intros [m1' [C D]].
+ exploit Mem.storev_extends. eexact D. eexact H1. eauto. eauto.
+ intros [m2' [F G]].
+ simpl chunk_of_type in F.
+ exploit Mem.storev_extends. eexact G. eexact H2. eauto. eauto.
+ intros [m3' [P Q]].
+ change (chunk_of_type Tptr) with Mint64 in *.
+ (* Execution of function prologue *)
+ monadInv EQ0. rewrite transl_code'_transl_code in EQ1.
+ set (tfbody := Pallocframe (fn_stacksize f) (fn_link_ofs f) ::
+ storeptr RA XSP (fn_retaddr_ofs f) x0) in *.
+ set (tf := {| fn_sig := Mach.fn_sig f; fn_code := tfbody |}) in *.
+ set (rs2 := nextinstr (rs0#X29 <- (parent_sp s) #SP <- sp #X16 <- Vundef)).
+ exploit (storeptr_correct tge tf XSP (fn_retaddr_ofs f) RA x0 m2' m3' rs2).
+ simpl preg_of_iregsp. change (rs2 X30) with (rs0 X30). rewrite ATLR.
+ change (rs2 X2) with sp. eexact P.
+ simpl; congruence. congruence.
+ intros (rs3 & U & V & W).
+ assert (EXEC_PROLOGUE:
+ exec_straight tge tf
+ tf.(fn_code) rs0 m'
+ x0 rs3 m3').
+ { change (fn_code tf) with tfbody; unfold tfbody.
+ apply exec_straight_step with rs2 m2'.
+ unfold exec_instr. rewrite C. fold sp.
+ rewrite <- (sp_val _ _ _ AG). rewrite F. reflexivity.
+ reflexivity.
+ eexact U. }
+ exploit exec_straight_steps_2; eauto using functions_transl. omega. constructor.
+ intros (ofs' & X & Y).
+ left; exists (State rs3 m3'); split.
+ eapply exec_straight_steps_1; eauto. omega. constructor.
+ econstructor; eauto.
+ rewrite X; econstructor; eauto.
+ apply agree_exten with rs2; eauto with asmgen.
+ unfold rs2.
+ apply agree_nextinstr. apply agree_set_other; auto with asmgen.
+ apply agree_change_sp with (parent_sp s).
+ apply agree_undef_regs with rs0. auto.
+Local Transparent destroyed_at_function_entry. simpl.
+ simpl; intros; Simpl.
+ unfold sp; congruence.
+ intros. rewrite V by auto with asmgen. reflexivity.
+
+ rewrite W.
+ unfold rs2.
+ Simpl.
+
+- (* external function *)
+ exploit functions_translated; eauto.
+ intros [tf [A B]]. simpl in B. inv B.
+ exploit extcall_arguments_match; eauto.
+ intros [args' [C D]].
+ exploit external_call_mem_extends; eauto.
+ intros [res' [m2' [P [Q [R S]]]]].
+ left; econstructor; split.
+ apply plus_one. eapply exec_step_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ econstructor; eauto.
+ unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto.
+ apply agree_undef_caller_save_regs; auto.
+
+- (* return *)
+ inv STACKS. simpl in *.
+ right. split. omega. split. auto.
+ rewrite <- ATPC in H5.
+ econstructor; eauto. congruence.
+ inv WF.
+ inv STACK.
+ inv H1.
+ congruence.
+Qed.
+
+Lemma transf_initial_states:
+ forall st1, Mach.initial_state prog st1 ->
+ exists st2, Asm.initial_state tprog st2 /\ match_states st1 st2.
+Proof.
+ intros. inversion H. unfold ge0 in *.
+ econstructor; split.
+ econstructor.
+ eapply (Genv.init_mem_transf_partial TRANSF); eauto.
+ replace (Genv.symbol_address (Genv.globalenv tprog) (prog_main tprog) Ptrofs.zero)
+ with (Vptr fb Ptrofs.zero).
+ econstructor; eauto.
+ constructor.
+ apply Mem.extends_refl.
+ split. auto. simpl. unfold Vnullptr; destruct Archi.ptr64; congruence.
+ intros. rewrite Regmap.gi. auto.
+ unfold Genv.symbol_address.
+ rewrite (match_program_main TRANSF).
+ rewrite symbols_preserved.
+ unfold ge; rewrite H1. auto.
+Qed.
+
+Lemma transf_final_states:
+ forall st1 st2 r,
+ match_states st1 st2 -> Mach.final_state st1 r -> Asm.final_state st2 r.
+Proof.
+ intros. inv H0. inv H. constructor. assumption.
+ compute in H1. inv H1.
+ generalize (preg_val _ _ _ R0 AG). rewrite H2. intros LD; inv LD. auto.
+Qed.
+
+Theorem transf_program_correct:
+ forward_simulation (Mach.semantics return_address_offset prog) (Asm.semantics tprog).
+Proof.
+ eapply forward_simulation_star with (measure := measure)
+ (match_states := fun S1 S2 => match_states S1 S2 /\ wf_state ge S1).
+ - apply senv_preserved.
+ - simpl; intros. exploit transf_initial_states; eauto.
+ intros (s2 & A & B).
+ exists s2; intuition auto. apply wf_initial; auto.
+ - simpl; intros. destruct H as [MS WF]. eapply transf_final_states; eauto.
+ - simpl; intros. destruct H0 as [MS WF].
+ exploit step_simulation; eauto. intros [ (s2' & A & B) | (A & B & C) ].
+ + left; exists s2'; intuition auto. eapply wf_step; eauto.
+ + right; intuition auto. eapply wf_step; eauto.
+Qed.
+
+End PRESERVATION.
+*) \ No newline at end of file
diff --git a/aarch64/Asmblockgenproof0.v b/aarch64/Asmblockgenproof0.v
new file mode 100644
index 00000000..92c0aa58
--- /dev/null
+++ b/aarch64/Asmblockgenproof0.v
@@ -0,0 +1,983 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(** * "block" version of Asmgenproof0
+
+ This module is largely adapted from Asmgenproof0.v of the other backends
+ It needs to stand apart because of the block structure, and the distinction control/basic that there isn't in the other backends
+ It has similar definitions than Asmgenproof0, but adapted to this new structure *)
+
+Require Import Coqlib.
+Require Intv.
+Require Import AST.
+Require Import Errors.
+Require Import Integers.
+Require Import Floats.
+Require Import Values.
+Require Import Memory.
+Require Import Globalenvs.
+Require Import Events.
+Require Import Smallstep.
+Require Import Locations.
+Require Import Machblock.
+Require Import Asmblock.
+Require Import Asmblockgen.
+Require Import Conventions1.
+Require Import Axioms.
+Require Import Machblockgenproof. (* FIXME: only use to import [is_tail_app] and [is_tail_app_inv] *)
+Require Import Asmblockprops.
+
+Module MB:=Machblock.
+Module AB:=Asmblock.
+
+(*
+Lemma ireg_of_eq:
+ forall r r', ireg_of r = OK r' -> preg_of r = IR r'.
+Proof.
+ unfold ireg_of; intros. destruct (preg_of r); inv H; auto.
+Qed.
+
+Lemma freg_of_eq:
+ forall r r', freg_of r = OK r' -> preg_of r = IR r'.
+Proof.
+ unfold freg_of; intros. destruct (preg_of r); inv H; auto.
+Qed.
+
+Lemma preg_of_injective:
+ forall r1 r2, preg_of r1 = preg_of r2 -> r1 = r2.
+Proof.
+ destruct r1; destruct r2; simpl; intros; reflexivity || discriminate.
+Qed.
+
+Lemma undef_regs_other:
+ forall r rl rs,
+ (forall r', In r' rl -> r <> r') ->
+ undef_regs rl rs r = rs r.
+Proof.
+ induction rl; simpl; intros. auto.
+ rewrite IHrl by auto. rewrite Pregmap.gso; auto.
+Qed.
+
+Fixpoint preg_notin (r: preg) (rl: list mreg) : Prop :=
+ match rl with
+ | nil => True
+ | r1 :: nil => r <> preg_of r1
+ | r1 :: rl => r <> preg_of r1 /\ preg_notin r rl
+ end.
+
+Remark preg_notin_charact:
+ forall r rl,
+ preg_notin r rl <-> (forall mr, In mr rl -> r <> preg_of mr).
+Proof.
+ induction rl; simpl; intros.
+ tauto.
+ destruct rl.
+ simpl. split. intros. intuition congruence. auto.
+ rewrite IHrl. split.
+ intros [A B]. intros. destruct H. congruence. auto.
+ auto.
+Qed.
+
+Lemma undef_regs_other_2:
+ forall r rl rs,
+ preg_notin r rl ->
+ undef_regs (map preg_of rl) rs r = rs r.
+Proof.
+ intros. apply undef_regs_other. intros.
+ exploit list_in_map_inv; eauto. intros [mr [A B]]. subst.
+ rewrite preg_notin_charact in H. auto.
+Qed.
+
+(** * Agreement between Mach registers and processor registers *)
+
+Record agree (ms: Mach.regset) (sp: val) (rs: AB.regset) : Prop := mkagree {
+ agree_sp: rs#SP = sp;
+ agree_sp_def: sp <> Vundef;
+ agree_mregs: forall r: mreg, Val.lessdef (ms r) (rs#(preg_of r))
+}.
+
+Lemma preg_val:
+ forall ms sp rs r, agree ms sp rs -> Val.lessdef (ms r) rs#(preg_of r).
+Proof.
+ intros. destruct H. auto.
+Qed.
+
+Lemma preg_vals:
+ forall ms sp rs, agree ms sp rs ->
+ forall l, Val.lessdef_list (map ms l) (map rs (map preg_of l)).
+Proof.
+ induction l; simpl. constructor. constructor. eapply preg_val; eauto. auto.
+Qed.
+
+Lemma sp_val:
+ forall ms sp rs, agree ms sp rs -> sp = rs#SP.
+Proof.
+ intros. destruct H; auto.
+Qed.
+
+Lemma ireg_val:
+ forall ms sp rs r r',
+ agree ms sp rs ->
+ ireg_of r = OK r' ->
+ Val.lessdef (ms r) rs#r'.
+Proof.
+ intros. rewrite <- (ireg_of_eq _ _ H0). eapply preg_val; eauto.
+Qed.
+
+Lemma freg_val:
+ forall ms sp rs r r',
+ agree ms sp rs ->
+ freg_of r = OK r' ->
+ Val.lessdef (ms r) (rs#r').
+Proof.
+ intros. rewrite <- (freg_of_eq _ _ H0). eapply preg_val; eauto.
+Qed.
+
+Lemma agree_exten:
+ forall ms sp rs rs',
+ agree ms sp rs ->
+ (forall r, data_preg r = true -> rs'#r = rs#r) ->
+ agree ms sp rs'.
+Proof.
+ intros. destruct H. split; auto.
+ rewrite H0; auto. auto.
+ intros. rewrite H0; auto. apply preg_of_data.
+Qed.
+
+(** Preservation of register agreement under various assignments. *)
+
+Lemma agree_set_mreg:
+ forall ms sp rs r v rs',
+ agree ms sp rs ->
+ Val.lessdef v (rs'#(preg_of r)) ->
+ (forall r', data_preg r' = true -> r' <> preg_of r -> rs'#r' = rs#r') ->
+ agree (Mach.Regmap.set r v ms) sp rs'.
+Proof.
+ intros. destruct H. split; auto.
+ rewrite H1; auto. apply not_eq_sym. apply preg_of_not_SP.
+ intros. unfold Mach.Regmap.set. destruct (Mach.RegEq.eq r0 r). congruence.
+ rewrite H1. auto. apply preg_of_data.
+ red; intros; elim n. eapply preg_of_injective; eauto.
+Qed.
+
+Corollary agree_set_mreg_parallel:
+ forall ms sp rs r v v',
+ agree ms sp rs ->
+ Val.lessdef v v' ->
+ agree (Mach.Regmap.set r v ms) sp (Pregmap.set (preg_of r) v' rs).
+Proof.
+ intros. eapply agree_set_mreg; eauto. rewrite Pregmap.gss; auto. intros; apply Pregmap.gso; auto.
+Qed.
+
+Lemma agree_set_other:
+ forall ms sp rs r v,
+ agree ms sp rs ->
+ data_preg r = false ->
+ agree ms sp (rs#r <- v).
+Proof.
+ intros. apply agree_exten with rs. auto.
+ intros. apply Pregmap.gso. congruence.
+Qed.
+
+Lemma agree_nextblock:
+ forall ms sp rs b,
+ agree ms sp rs -> agree ms sp (nextblock b rs).
+Proof.
+ intros. unfold nextblock. apply agree_set_other. auto. auto.
+Qed.
+
+Lemma agree_set_pair:
+ forall sp p v v' ms rs,
+ agree ms sp rs ->
+ Val.lessdef v v' ->
+ agree (Mach.set_pair p v ms) sp (set_pair (map_rpair preg_of p) v' rs).
+Proof.
+ intros. destruct p; simpl.
+- apply agree_set_mreg_parallel; auto.
+- apply agree_set_mreg_parallel. apply agree_set_mreg_parallel; auto.
+ apply Val.hiword_lessdef; auto. apply Val.loword_lessdef; auto.
+Qed.
+
+Lemma agree_undef_nondata_regs:
+ forall ms sp rl rs,
+ agree ms sp rs ->
+ (forall r, In r rl -> data_preg r = false) ->
+ agree ms sp (undef_regs rl rs).
+Proof.
+ induction rl; simpl; intros. auto.
+ apply IHrl. apply agree_exten with rs; auto.
+ intros. apply Pregmap.gso. red; intros; subst.
+ assert (data_preg a = false) by auto. congruence.
+ intros. apply H0; auto.
+Qed.
+
+Lemma agree_undef_regs:
+ forall ms sp rl rs rs',
+ agree ms sp rs ->
+ (forall r', data_preg r' = true -> preg_notin r' rl -> rs'#r' = rs#r') ->
+ agree (Mach.undef_regs rl ms) sp rs'.
+Proof.
+ intros. destruct H. split; auto.
+ rewrite <- agree_sp0. apply H0; auto.
+ rewrite preg_notin_charact. intros. apply not_eq_sym. apply preg_of_not_SP.
+ intros. destruct (In_dec mreg_eq r rl).
+ rewrite Mach.undef_regs_same; auto.
+ rewrite Mach.undef_regs_other; auto. rewrite H0; auto.
+ apply preg_of_data.
+ rewrite preg_notin_charact. intros; red; intros. elim n.
+ exploit preg_of_injective; eauto. congruence.
+Qed.
+
+Lemma agree_set_undef_mreg:
+ forall ms sp rs r v rl rs',
+ agree ms sp rs ->
+ Val.lessdef v (rs'#(preg_of r)) ->
+ (forall r', data_preg r' = true -> r' <> preg_of r -> preg_notin r' rl -> rs'#r' = rs#r') ->
+ agree (Mach.Regmap.set r v (Mach.undef_regs rl ms)) sp rs'.
+Proof.
+ intros. apply agree_set_mreg with (rs'#(preg_of r) <- (rs#(preg_of r))); auto.
+ apply agree_undef_regs with rs; auto.
+ intros. unfold Pregmap.set. destruct (PregEq.eq r' (preg_of r)).
+ congruence. auto.
+ intros. rewrite Pregmap.gso; auto.
+Qed.
+
+Lemma agree_undef_caller_save_regs:
+ forall ms sp rs,
+ agree ms sp rs ->
+ agree (Mach.undef_caller_save_regs ms) sp (undef_caller_save_regs rs).
+Proof.
+ intros. destruct H. unfold Mach.undef_caller_save_regs, undef_caller_save_regs; split.
+- unfold proj_sumbool; rewrite dec_eq_true. auto.
+- auto.
+- intros. unfold proj_sumbool. rewrite dec_eq_false by (apply preg_of_not_SP).
+ destruct (List.in_dec preg_eq (preg_of r) (List.map preg_of (List.filter is_callee_save all_mregs))); simpl.
++ apply list_in_map_inv in i. destruct i as (mr & A & B).
+ assert (r = mr) by (apply preg_of_injective; auto). subst mr; clear A.
+ apply List.filter_In in B. destruct B as [C D]. rewrite D. auto.
++ destruct (is_callee_save r) eqn:CS; auto.
+ elim n. apply List.in_map. apply List.filter_In. auto using all_mregs_complete.
+Qed.
+
+Lemma agree_change_sp:
+ forall ms sp rs sp',
+ agree ms sp rs -> sp' <> Vundef ->
+ agree ms sp' (rs#SP <- sp').
+Proof.
+ intros. inv H. split; auto.
+ intros. rewrite Pregmap.gso; auto with asmgen.
+Qed.
+
+(** Connection between Mach and Asm calling conventions for external
+ functions. *)
+
+Lemma extcall_arg_match:
+ forall ms sp rs m m' l v,
+ agree ms sp rs ->
+ Mem.extends m m' ->
+ Mach.extcall_arg ms m sp l v ->
+ exists v', AB.extcall_arg rs m' l v' /\ Val.lessdef v v'.
+Proof.
+ intros. inv H1.
+ exists (rs#(preg_of r)); split. constructor. eapply preg_val; eauto.
+ unfold Mach.load_stack in H2.
+ exploit Mem.loadv_extends; eauto. intros [v' [A B]].
+ rewrite (sp_val _ _ _ H) in A.
+ exists v'; split; auto.
+ econstructor. eauto. assumption.
+Qed.
+
+Lemma extcall_arg_pair_match:
+ forall ms sp rs m m' p v,
+ agree ms sp rs ->
+ Mem.extends m m' ->
+ Mach.extcall_arg_pair ms m sp p v ->
+ exists v', AB.extcall_arg_pair rs m' p v' /\ Val.lessdef v v'.
+Proof.
+ intros. inv H1.
+- exploit extcall_arg_match; eauto. intros (v' & A & B). exists v'; split; auto. constructor; auto.
+- exploit extcall_arg_match. eauto. eauto. eexact H2. intros (v1 & A1 & B1).
+ exploit extcall_arg_match. eauto. eauto. eexact H3. intros (v2 & A2 & B2).
+ exists (Val.longofwords v1 v2); split. constructor; auto. apply Val.longofwords_lessdef; auto.
+Qed.
+
+
+Lemma extcall_args_match:
+ forall ms sp rs m m', agree ms sp rs -> Mem.extends m m' ->
+ forall ll vl,
+ list_forall2 (Mach.extcall_arg_pair ms m sp) ll vl ->
+ exists vl', list_forall2 (AB.extcall_arg_pair rs m') ll vl' /\ Val.lessdef_list vl vl'.
+Proof.
+ induction 3; intros.
+ exists (@nil val); split. constructor. constructor.
+ exploit extcall_arg_pair_match; eauto. intros [v1' [A B]].
+ destruct IHlist_forall2 as [vl' [C D]].
+ exists (v1' :: vl'); split; constructor; auto.
+Qed.
+
+Lemma extcall_arguments_match:
+ forall ms m m' sp rs sg args,
+ agree ms sp rs -> Mem.extends m m' ->
+ Mach.extcall_arguments ms m sp sg args ->
+ exists args', AB.extcall_arguments rs m' sg args' /\ Val.lessdef_list args args'.
+Proof.
+ unfold Mach.extcall_arguments, AB.extcall_arguments; intros.
+ eapply extcall_args_match; eauto.
+Qed.
+
+Remark builtin_arg_match:
+ forall ge (rs: regset) sp m a v,
+ eval_builtin_arg ge (fun r => rs (preg_of r)) sp m a v ->
+ eval_builtin_arg ge rs sp m (map_builtin_arg preg_of a) v.
+Proof.
+ induction 1; simpl; eauto with barg.
+Qed.
+
+Lemma builtin_args_match:
+ forall ge ms sp rs m m', agree ms sp rs -> Mem.extends m m' ->
+ forall al vl, eval_builtin_args ge ms sp m al vl ->
+ exists vl', eval_builtin_args ge rs sp m' (map (map_builtin_arg preg_of) al) vl'
+ /\ Val.lessdef_list vl vl'.
+Proof.
+ induction 3; intros; simpl.
+ exists (@nil val); split; constructor.
+ exploit (@eval_builtin_arg_lessdef _ ge ms (fun r => rs (preg_of r))); eauto.
+ intros; eapply preg_val; eauto.
+ intros (v1' & A & B).
+ destruct IHlist_forall2 as [vl' [C D]].
+ exists (v1' :: vl'); split; constructor; auto. apply builtin_arg_match; auto.
+Qed.
+
+Lemma agree_set_res:
+ forall res ms sp rs v v',
+ agree ms sp rs ->
+ Val.lessdef v v' ->
+ agree (Mach.set_res res v ms) sp (AB.set_res (map_builtin_res preg_of res) v' rs).
+Proof.
+ induction res; simpl; intros.
+- eapply agree_set_mreg; eauto. rewrite Pregmap.gss. auto.
+ intros. apply Pregmap.gso; auto.
+- auto.
+- apply IHres2. apply IHres1. auto.
+ apply Val.hiword_lessdef; auto.
+ apply Val.loword_lessdef; auto.
+Qed.
+
+Lemma set_res_other:
+ forall r res v rs,
+ data_preg r = false ->
+ set_res (map_builtin_res preg_of res) v rs r = rs r.
+Proof.
+ induction res; simpl; intros.
+- apply Pregmap.gso. red; intros; subst r. rewrite preg_of_data in H; discriminate.
+- auto.
+- rewrite IHres2, IHres1; auto.
+Qed.
+
+(* inspired from Mach *)
+
+Lemma find_label_tail:
+ forall lbl c c', MB.find_label lbl c = Some c' -> is_tail c' c.
+Proof.
+ induction c; simpl; intros. discriminate.
+ destruct (MB.is_label lbl a). inv H. auto with coqlib. eauto with coqlib.
+Qed.
+
+(* inspired from Asmgenproof0 *)
+
+(* ... skip ... *)
+
+(** The ``code tail'' of an instruction list [c] is the list of instructions
+ starting at PC [pos]. *)
+
+Inductive code_tail: Z -> bblocks -> bblocks -> Prop :=
+ | code_tail_0: forall c,
+ code_tail 0 c c
+ | code_tail_S: forall pos bi c1 c2,
+ code_tail pos c1 c2 ->
+ code_tail (pos + (size bi)) (bi :: c1) c2.
+
+Lemma code_tail_pos:
+ forall pos c1 c2, code_tail pos c1 c2 -> pos >= 0.
+Proof.
+ induction 1. omega. generalize (size_positive bi); intros; omega.
+Qed.
+
+Lemma find_bblock_tail:
+ forall c1 bi c2 pos,
+ code_tail pos c1 (bi :: c2) ->
+ find_bblock pos c1 = Some bi.
+Proof.
+ induction c1; simpl; intros.
+ inversion H.
+ destruct (zlt pos 0). generalize (code_tail_pos _ _ _ H); intro; omega.
+ destruct (zeq pos 0). subst pos.
+ inv H. auto. generalize (size_positive a) (code_tail_pos _ _ _ H4). intro; omega.
+ inv H. congruence. replace (pos0 + size a - size a) with pos0 by omega.
+ eauto.
+Qed.
+
+
+Local Hint Resolve code_tail_0 code_tail_S: core.
+
+Lemma code_tail_next:
+ forall fn ofs c0,
+ code_tail ofs fn c0 ->
+ forall bi c1, c0 = bi :: c1 -> code_tail (ofs + (size bi)) fn c1.
+Proof.
+ induction 1; intros.
+ - subst; eauto.
+ - replace (pos + size bi + size bi0) with ((pos + size bi0) + size bi); eauto.
+ omega.
+Qed.
+
+Lemma size_blocks_pos c: 0 <= size_blocks c.
+Proof.
+ induction c as [| a l ]; simpl; try omega.
+ generalize (size_positive a); omega.
+Qed.
+
+Remark code_tail_positive:
+ forall fn ofs c,
+ code_tail ofs fn c -> 0 <= ofs.
+Proof.
+ induction 1; intros; simpl.
+ - omega.
+ - generalize (size_positive bi). omega.
+Qed.
+
+Remark code_tail_size:
+ forall fn ofs c,
+ code_tail ofs fn c -> size_blocks fn = ofs + size_blocks c.
+Proof.
+ induction 1; intros; simpl; try omega.
+Qed.
+
+Remark code_tail_bounds fn ofs c:
+ code_tail ofs fn c -> 0 <= ofs <= size_blocks fn.
+Proof.
+ intro H;
+ exploit code_tail_size; eauto.
+ generalize (code_tail_positive _ _ _ H), (size_blocks_pos c).
+ omega.
+Qed.
+
+Local Hint Resolve code_tail_next: core.
+
+Lemma code_tail_next_int:
+ forall fn ofs bi c,
+ size_blocks fn <= Ptrofs.max_unsigned ->
+ code_tail (Ptrofs.unsigned ofs) fn (bi :: c) ->
+ code_tail (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr (size bi)))) fn c.
+Proof.
+ intros.
+ exploit code_tail_size; eauto.
+ simpl; generalize (code_tail_positive _ _ _ H0), (size_positive bi), (size_blocks_pos c).
+ intros.
+ rewrite Ptrofs.add_unsigned, Ptrofs.unsigned_repr.
+ - rewrite Ptrofs.unsigned_repr; eauto.
+ omega.
+ - rewrite Ptrofs.unsigned_repr; omega.
+Qed.
+
+(** Predictor for return addresses in generated Asm code.
+
+ The [return_address_offset] predicate defined here is used in the
+ semantics for Mach to determine the return addresses that are
+ stored in activation records. *)
+
+(** Consider a Mach function [f] and a sequence [c] of Mach instructions
+ representing the Mach code that remains to be executed after a
+ function call returns. The predicate [return_address_offset f c ofs]
+ holds if [ofs] is the integer offset of the PPC instruction
+ following the call in the Asm code obtained by translating the
+ code of [f]. Graphically:
+<<
+ Mach function f |--------- Mcall ---------|
+ Mach code c | |--------|
+ | \ \
+ | \ \
+ | \ \
+ Asm code | |--------|
+ Asm function |------------- Pcall ---------|
+
+ <-------- ofs ------->
+>>
+*)
+
+Definition return_address_offset (f: MB.function) (c: MB.code) (ofs: ptrofs) : Prop :=
+ forall tf tc,
+ transf_function f = OK tf ->
+ transl_blocks f c false = OK tc ->
+ code_tail (Ptrofs.unsigned ofs) (fn_blocks tf) tc.
+
+Lemma transl_blocks_tail:
+ forall f c1 c2, is_tail c1 c2 ->
+ forall tc2 ep2, transl_blocks f c2 ep2 = OK tc2 ->
+ exists tc1, exists ep1, transl_blocks f c1 ep1 = OK tc1 /\ is_tail tc1 tc2.
+Proof.
+ induction 1; simpl; intros.
+ exists tc2; exists ep2; split; auto with coqlib.
+ monadInv H0. exploit IHis_tail; eauto. intros (tc1 & ep1 & A & B).
+ exists tc1; exists ep1; split. auto.
+ eapply is_tail_trans with x0; eauto with coqlib.
+Qed.
+
+Lemma is_tail_code_tail:
+ forall c1 c2, is_tail c1 c2 -> exists ofs, code_tail ofs c2 c1.
+Proof.
+ induction 1; eauto.
+ destruct IHis_tail; eauto.
+Qed.
+
+Section RETADDR_EXISTS.
+
+Hypothesis transf_function_inv:
+ forall f tf, transf_function f = OK tf ->
+ exists tc ep, transl_blocks f (Machblock.fn_code f) ep = OK tc /\ is_tail tc (fn_blocks tf).
+
+Hypothesis transf_function_len:
+ forall f tf, transf_function f = OK tf -> size_blocks (fn_blocks tf) <= Ptrofs.max_unsigned.
+
+
+Lemma return_address_exists:
+ forall b f c, is_tail (b :: c) f.(MB.fn_code) ->
+ exists ra, return_address_offset f c ra.
+Proof.
+ intros. destruct (transf_function f) as [tf|] eqn:TF.
+ + exploit transf_function_inv; eauto. intros (tc1 & ep1 & TR1 & TL1).
+ exploit transl_blocks_tail; eauto. intros (tc2 & ep2 & TR2 & TL2).
+ monadInv TR2.
+ assert (TL3: is_tail x0 (fn_blocks tf)).
+ { apply is_tail_trans with tc1; auto.
+ apply is_tail_trans with (x++x0); auto. eapply is_tail_app.
+ }
+ exploit is_tail_code_tail. eexact TL3. intros [ofs CT].
+ exists (Ptrofs.repr ofs). red; intros.
+ rewrite Ptrofs.unsigned_repr. congruence.
+ exploit code_tail_bounds; eauto.
+ intros; apply transf_function_len in TF. omega.
+ + exists Ptrofs.zero; red; intros. congruence.
+Qed.
+
+End RETADDR_EXISTS.
+
+(** [transl_code_at_pc pc fb f c ep tf tc] holds if the code pointer [pc] points
+ within the Asmblock code generated by translating Machblock function [f],
+ and [tc] is the tail of the generated code at the position corresponding
+ to the code pointer [pc]. *)
+
+Inductive transl_code_at_pc (ge: MB.genv):
+ val -> block -> MB.function -> MB.code -> bool -> AB.function -> AB.bblocks -> Prop :=
+ transl_code_at_pc_intro:
+ forall b ofs f c ep tf tc,
+ Genv.find_funct_ptr ge b = Some(Internal f) ->
+ transf_function f = Errors.OK tf ->
+ transl_blocks f c ep = OK tc ->
+ code_tail (Ptrofs.unsigned ofs) (fn_blocks tf) tc ->
+ transl_code_at_pc ge (Vptr b ofs) b f c ep tf tc.
+
+Remark code_tail_no_bigger:
+ forall pos c1 c2, code_tail pos c1 c2 -> (length c2 <= length c1)%nat.
+Proof.
+ induction 1; simpl; omega.
+Qed.
+
+Remark code_tail_unique:
+ forall fn c pos pos',
+ code_tail pos fn c -> code_tail pos' fn c -> pos = pos'.
+Proof.
+ induction fn; intros until pos'; intros ITA CT; inv ITA; inv CT; auto.
+ generalize (code_tail_no_bigger _ _ _ H3); simpl; intro; omega.
+ generalize (code_tail_no_bigger _ _ _ H3); simpl; intro; omega.
+ f_equal. eauto.
+Qed.
+
+Lemma return_address_offset_correct:
+ forall ge b ofs fb f c tf tc ofs',
+ transl_code_at_pc ge (Vptr b ofs) fb f c false tf tc ->
+ return_address_offset f c ofs' ->
+ ofs' = ofs.
+Proof.
+ intros. inv H. red in H0.
+ exploit code_tail_unique. eexact H12. eapply H0; eauto. intro.
+ rewrite <- (Ptrofs.repr_unsigned ofs).
+ rewrite <- (Ptrofs.repr_unsigned ofs').
+ congruence.
+Qed.
+
+(** The [find_label] function returns the code tail starting at the
+ given label. A connection with [code_tail] is then established. *)
+
+Fixpoint find_label (lbl: label) (c: bblocks) {struct c} : option bblocks :=
+ match c with
+ | nil => None
+ | bb1 :: bbl => if is_label lbl bb1 then Some c else find_label lbl bbl
+ end.
+
+Lemma label_pos_code_tail:
+ forall lbl c pos c',
+ find_label lbl c = Some c' ->
+ exists pos',
+ label_pos lbl pos c = Some pos'
+ /\ code_tail (pos' - pos) c c'
+ /\ pos <= pos' <= pos + size_blocks c.
+Proof.
+ induction c.
+ simpl; intros. discriminate.
+ simpl; intros until c'.
+ case (is_label lbl a).
+ - intros. inv H. exists pos. split; auto. split.
+ replace (pos - pos) with 0 by omega. constructor. constructor; try omega.
+ generalize (size_blocks_pos c). generalize (size_positive a). omega.
+ - intros. generalize (IHc (pos+size a) c' H). intros [pos' [A [B C]]].
+ exists pos'. split. auto. split.
+ replace (pos' - pos) with ((pos' - (pos + (size a))) + (size a)) by omega.
+ constructor. auto. generalize (size_positive a). omega.
+Qed.
+
+(** Helper lemmas to reason about
+- the "code is tail of" property
+- correct translation of labels. *)
+
+Definition tail_nolabel (k c: bblocks) : Prop :=
+ is_tail k c /\ forall lbl, find_label lbl c = find_label lbl k.
+
+Lemma tail_nolabel_refl:
+ forall c, tail_nolabel c c.
+Proof.
+ intros; split. apply is_tail_refl. auto.
+Qed.
+
+Lemma tail_nolabel_trans:
+ forall c1 c2 c3, tail_nolabel c2 c3 -> tail_nolabel c1 c2 -> tail_nolabel c1 c3.
+Proof.
+ intros. destruct H; destruct H0; split.
+ eapply is_tail_trans; eauto.
+ intros. rewrite H1; auto.
+Qed.
+
+Definition nolabel (b: bblock) :=
+ match (header b) with nil => True | _ => False end.
+
+Hint Extern 1 (nolabel _) => exact I : labels.
+
+Lemma tail_nolabel_cons:
+ forall b c k,
+ nolabel b -> tail_nolabel k c -> tail_nolabel k (b :: c).
+Proof.
+ intros. destruct H0. split.
+ constructor; auto.
+ intros. simpl. rewrite <- H1. destruct b as [hd bdy ex]; simpl in *.
+ destruct hd as [|l hd]; simpl in *.
+ - assert (is_label lbl {| AB.header := nil; AB.body := bdy; AB.exit := ex; AB.correct := correct |} = false).
+ { apply is_label_correct_false. simpl header. apply in_nil. }
+ rewrite H2. auto.
+ - contradiction.
+Qed.
+
+Hint Resolve tail_nolabel_refl: labels.
+
+Ltac TailNoLabel :=
+ eauto with labels;
+ match goal with
+ | [ |- tail_nolabel _ (_ :: _) ] => apply tail_nolabel_cons; [auto; exact I | TailNoLabel]
+ | [ H: Error _ = OK _ |- _ ] => discriminate
+ | [ H: assertion_failed = OK _ |- _ ] => discriminate
+ | [ H: OK _ = OK _ |- _ ] => inv H; TailNoLabel
+ | [ H: bind _ _ = OK _ |- _ ] => monadInv H; TailNoLabel
+ | [ H: (if ?x then _ else _) = OK _ |- _ ] => destruct x; TailNoLabel
+ | [ H: match ?x with nil => _ | _ :: _ => _ end = OK _ |- _ ] => destruct x; TailNoLabel
+ | _ => idtac
+ end.
+
+Remark tail_nolabel_find_label:
+ forall lbl k c, tail_nolabel k c -> find_label lbl c = find_label lbl k.
+Proof.
+ intros. destruct H. auto.
+Qed.
+
+Remark tail_nolabel_is_tail:
+ forall k c, tail_nolabel k c -> is_tail k c.
+Proof.
+ intros. destruct H. auto.
+Qed.
+
+Lemma exec_body_pc:
+ forall ge l rs1 m1 rs2 m2,
+ exec_body ge l rs1 m1 = Next rs2 m2 ->
+ rs2 PC = rs1 PC.
+Proof.
+ induction l.
+ - intros. inv H. auto.
+ - intros until m2. intro EXEB.
+ inv EXEB. destruct (exec_basic_instr _ _ _ _) eqn:EBI; try discriminate.
+ eapply IHl in H0. rewrite H0.
+ erewrite exec_basic_instr_pc; eauto.
+Qed.
+
+Section STRAIGHTLINE.
+
+Variable ge: genv.
+Variable fn: function.
+
+(** Straight-line code is composed of processor instructions that execute
+ in sequence (no branches, no function calls and returns).
+ The following inductive predicate relates the machine states
+ before and after executing a straight-line sequence of instructions.
+ Instructions are taken from the first list instead of being fetched
+ from memory. *)
+
+Inductive exec_straight: list instruction -> regset -> mem ->
+ list instruction -> regset -> mem -> Prop :=
+ | exec_straight_one:
+ forall i1 c rs1 m1 rs2 m2,
+ exec_basic_instr ge i1 rs1 m1 = Next rs2 m2 ->
+ exec_straight ((PBasic i1) ::g c) rs1 m1 c rs2 m2
+ | exec_straight_step:
+ forall i c rs1 m1 rs2 m2 c' rs3 m3,
+ exec_basic_instr ge i rs1 m1 = Next rs2 m2 ->
+ exec_straight c rs2 m2 c' rs3 m3 ->
+ exec_straight ((PBasic i) :: c) rs1 m1 c' rs3 m3.
+
+Inductive exec_control_rel: option control -> bblock -> regset -> mem ->
+ regset -> mem -> Prop :=
+ | exec_control_rel_intro:
+ forall rs1 m1 b rs1' ctl rs2 m2,
+ rs1' = nextblock b rs1 ->
+ exec_control ge fn ctl rs1' m1 = Next rs2 m2 ->
+ exec_control_rel ctl b rs1 m1 rs2 m2.
+
+Inductive exec_bblock_rel: bblock -> regset -> mem -> regset -> mem -> Prop :=
+ | exec_bblock_rel_intro:
+ forall rs1 m1 b rs2 m2,
+ exec_bblock ge fn b rs1 m1 = Next rs2 m2 ->
+ exec_bblock_rel b rs1 m1 rs2 m2.
+
+Lemma exec_straight_body:
+ forall c l rs1 m1 rs2 m2,
+ exec_straight c rs1 m1 nil rs2 m2 ->
+ code_to_basics c = Some l ->
+ exec_body ge l rs1 m1 = Next rs2 m2.
+Proof.
+ induction c as [|i c].
+ - intros until m2. intros EXES CTB. inv EXES.
+ - intros until m2. intros EXES CTB. inv EXES.
+ + inv CTB. simpl. rewrite H6. auto.
+ + inv CTB. destruct (code_to_basics c); try discriminate. inv H0. eapply IHc in H7; eauto.
+ rewrite <- H7. simpl. rewrite H1. auto.
+Qed.
+
+Lemma exec_straight_body2:
+ forall c rs1 m1 c' rs2 m2,
+ exec_straight c rs1 m1 c' rs2 m2 ->
+ exists body,
+ exec_body ge body rs1 m1 = Next rs2 m2
+ /\ (basics_to_code body) ++g c' = c.
+Proof.
+ intros until m2. induction 1.
+ - exists (i1::nil). split; auto. simpl. rewrite H. auto.
+ - destruct IHexec_straight as (bdy & EXEB & BTC).
+ exists (i:: bdy). split; simpl.
+ + rewrite H. auto.
+ + congruence.
+Qed.
+
+Lemma exec_straight_trans:
+ forall c1 rs1 m1 c2 rs2 m2 c3 rs3 m3,
+ exec_straight c1 rs1 m1 c2 rs2 m2 ->
+ exec_straight c2 rs2 m2 c3 rs3 m3 ->
+ exec_straight c1 rs1 m1 c3 rs3 m3.
+Proof.
+ induction 1; intros.
+ apply exec_straight_step with rs2 m2; auto.
+ apply exec_straight_step with rs2 m2; auto.
+Qed.
+
+Lemma exec_straight_two:
+ forall i1 i2 c rs1 m1 rs2 m2 rs3 m3,
+ exec_basic_instr ge i1 rs1 m1 = Next rs2 m2 ->
+ exec_basic_instr ge i2 rs2 m2 = Next rs3 m3 ->
+ exec_straight (i1 ::g i2 ::g c) rs1 m1 c rs3 m3.
+Proof.
+ intros. apply exec_straight_step with rs2 m2; auto.
+ apply exec_straight_one; auto.
+Qed.
+
+Lemma exec_straight_three:
+ forall i1 i2 i3 c rs1 m1 rs2 m2 rs3 m3 rs4 m4,
+ exec_basic_instr ge i1 rs1 m1 = Next rs2 m2 ->
+ exec_basic_instr ge i2 rs2 m2 = Next rs3 m3 ->
+ exec_basic_instr ge i3 rs3 m3 = Next rs4 m4 ->
+ exec_straight (i1 ::g i2 ::g i3 ::g c) rs1 m1 c rs4 m4.
+Proof.
+ intros. apply exec_straight_step with rs2 m2; auto.
+ eapply exec_straight_two; eauto.
+Qed.
+
+(** Like exec_straight predicate, but on blocks *)
+
+Inductive exec_straight_blocks: bblocks -> regset -> mem ->
+ bblocks -> regset -> mem -> Prop :=
+ | exec_straight_blocks_one:
+ forall b1 c rs1 m1 rs2 m2,
+ exec_bblock ge fn b1 rs1 m1 = Next rs2 m2 ->
+ rs2#PC = Val.offset_ptr rs1#PC (Ptrofs.repr (size b1)) ->
+ exec_straight_blocks (b1 :: c) rs1 m1 c rs2 m2
+ | exec_straight_blocks_step:
+ forall b c rs1 m1 rs2 m2 c' rs3 m3,
+ exec_bblock ge fn b rs1 m1 = Next rs2 m2 ->
+ rs2#PC = Val.offset_ptr rs1#PC (Ptrofs.repr (size b)) ->
+ exec_straight_blocks c rs2 m2 c' rs3 m3 ->
+ exec_straight_blocks (b :: c) rs1 m1 c' rs3 m3.
+
+Lemma exec_straight_blocks_trans:
+ forall c1 rs1 m1 c2 rs2 m2 c3 rs3 m3,
+ exec_straight_blocks c1 rs1 m1 c2 rs2 m2 ->
+ exec_straight_blocks c2 rs2 m2 c3 rs3 m3 ->
+ exec_straight_blocks c1 rs1 m1 c3 rs3 m3.
+Proof.
+ induction 1; intros.
+ apply exec_straight_blocks_step with rs2 m2; auto.
+ apply exec_straight_blocks_step with rs2 m2; auto.
+Qed.
+
+(** Linking exec_straight with exec_straight_blocks *)
+
+Lemma exec_straight_pc:
+ forall c c' rs1 m1 rs2 m2,
+ exec_straight c rs1 m1 c' rs2 m2 ->
+ rs2 PC = rs1 PC.
+Proof.
+ induction c; intros; try (inv H; fail).
+ inv H.
+ - eapply exec_basic_instr_pc; eauto.
+ - rewrite (IHc c' rs3 m3 rs2 m2); auto.
+ erewrite exec_basic_instr_pc; eauto.
+Qed.
+
+Lemma regset_same_assign (rs: regset) r:
+ rs # r <- (rs r) = rs.
+Proof.
+ apply functional_extensionality. intros x. destruct (preg_eq x r); subst; Simpl.
+Qed.
+
+Lemma exec_straight_through_singleinst:
+ forall a b rs1 m1 rs2 m2 rs2' m2' lb,
+ bblock_single_inst (PBasic a) = b ->
+ exec_straight (a ::g nil) rs1 m1 nil rs2 m2 ->
+ nextblock b rs2 = rs2' -> m2 = m2' ->
+ exec_straight_blocks (b::lb) rs1 m1 lb rs2' m2'.
+Proof.
+ intros. subst. constructor 1. unfold exec_bblock. simpl body. erewrite exec_straight_body; eauto.
+ simpl. rewrite regset_same_assign. auto.
+ simpl; auto. unfold nextblock, incrPC; simpl. Simpl. erewrite exec_straight_pc; eauto.
+Qed.
+
+(** The following lemmas show that straight-line executions
+ (predicate [exec_straight_blocks]) correspond to correct Asm executions. *)
+
+Lemma exec_straight_steps_1:
+ forall c rs m c' rs' m',
+ exec_straight_blocks c rs m c' rs' m' ->
+ size_blocks (fn_blocks fn) <= Ptrofs.max_unsigned ->
+ forall b ofs,
+ rs#PC = Vptr b ofs ->
+ Genv.find_funct_ptr ge b = Some (Internal fn) ->
+ code_tail (Ptrofs.unsigned ofs) (fn_blocks fn) c ->
+ plus step ge (State rs m) E0 (State rs' m').
+Proof.
+ induction 1; intros.
+ apply plus_one.
+ econstructor; eauto.
+ eapply find_bblock_tail. eauto.
+ eapply plus_left'.
+ econstructor; eauto.
+ eapply find_bblock_tail. eauto.
+ apply IHexec_straight_blocks with b0 (Ptrofs.add ofs (Ptrofs.repr (size b))).
+ auto. rewrite H0. rewrite H3. reflexivity.
+ auto.
+ apply code_tail_next_int; auto.
+ traceEq.
+Qed.
+
+Lemma exec_straight_steps_2:
+ forall c rs m c' rs' m',
+ exec_straight_blocks c rs m c' rs' m' ->
+ size_blocks (fn_blocks fn) <= Ptrofs.max_unsigned ->
+ forall b ofs,
+ rs#PC = Vptr b ofs ->
+ Genv.find_funct_ptr ge b = Some (Internal fn) ->
+ code_tail (Ptrofs.unsigned ofs) (fn_blocks fn) c ->
+ exists ofs',
+ rs'#PC = Vptr b ofs'
+ /\ code_tail (Ptrofs.unsigned ofs') (fn_blocks fn) c'.
+Proof.
+ induction 1; intros.
+ exists (Ptrofs.add ofs (Ptrofs.repr (size b1))). split.
+ rewrite H0. rewrite H2. auto.
+ apply code_tail_next_int; auto.
+ apply IHexec_straight_blocks with (Ptrofs.add ofs (Ptrofs.repr (size b))).
+ auto. rewrite H0. rewrite H3. reflexivity. auto.
+ apply code_tail_next_int; auto.
+Qed.
+
+End STRAIGHTLINE.
+
+(** * Properties of the Machblock call stack *)
+
+Section MATCH_STACK.
+
+Variable ge: MB.genv.
+
+Inductive match_stack: list MB.stackframe -> Prop :=
+ | match_stack_nil:
+ match_stack nil
+ | match_stack_cons: forall fb sp ra c s f tf tc,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transl_code_at_pc ge ra fb f c false tf tc ->
+ sp <> Vundef ->
+ match_stack s ->
+ match_stack (Stackframe fb sp ra c :: s).
+
+Lemma parent_sp_def: forall s, match_stack s -> parent_sp s <> Vundef.
+Proof.
+ induction 1; simpl.
+ unfold Vnullptr; destruct Archi.ptr64; congruence.
+ auto.
+Qed.
+
+Lemma parent_ra_def: forall s, match_stack s -> parent_ra s <> Vundef.
+Proof.
+ induction 1; simpl.
+ unfold Vnullptr; destruct Archi.ptr64; congruence.
+ inv H0. congruence.
+Qed.
+
+Lemma lessdef_parent_sp:
+ forall s v,
+ match_stack s -> Val.lessdef (parent_sp s) v -> v = parent_sp s.
+Proof.
+ intros. inv H0. auto. exploit parent_sp_def; eauto. tauto.
+Qed.
+
+Lemma lessdef_parent_ra:
+ forall s v,
+ match_stack s -> Val.lessdef (parent_ra s) v -> v = parent_ra s.
+Proof.
+ intros. inv H0. auto. exploit parent_ra_def; eauto. tauto.
+Qed.
+
+End MATCH_STACK.*)
diff --git a/aarch64/Asmgenproof1.v b/aarch64/Asmblockgenproof1.v
index 0e36bd05..b42309bc 100644
--- a/aarch64/Asmgenproof1.v
+++ b/aarch64/Asmblockgenproof1.v
@@ -1,3 +1,5 @@
+(* ORIGINAL aarch64/Asmgenproof1 file that needs to be adapted
+
(* *********************************************************************)
(* *)
(* The Compcert verified compiler *)
@@ -2136,3 +2138,4 @@ Proof.
Qed.
End CONSTRUCTORS.
+*) \ No newline at end of file
diff --git a/aarch64/Asmblockprops.v b/aarch64/Asmblockprops.v
new file mode 100644
index 00000000..782d8aee
--- /dev/null
+++ b/aarch64/Asmblockprops.v
@@ -0,0 +1,358 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(** Common definition and proofs on Asmblock required by various modules *)
+
+Require Import Coqlib.
+Require Import Integers.
+Require Import Memory.
+Require Import Globalenvs.
+Require Import Values.
+Require Import Asmblock.
+Require Import Axioms.
+
+Definition bblock_simu (lk: aarch64_linker) (ge: Genv.t fundef unit) (f: function) (bb bb': bblock) :=
+ forall rs m rs' m' t,
+ exec_bblock lk ge f bb rs m t rs' m' -> exec_bblock lk ge f bb rs m t rs' m'.
+
+Hint Extern 2 (_ <> _) => congruence: asmgen.
+
+Lemma preg_of_data:
+ forall r, data_preg (preg_of r) = true.
+Proof.
+ intros. destruct r; reflexivity.
+Qed.
+Hint Resolve preg_of_data: asmgen.
+
+Lemma data_diff:
+ forall r r',
+ data_preg r = true -> data_preg r' = false -> r <> r'.
+Proof.
+ congruence.
+Qed.
+Hint Resolve data_diff: asmgen.
+
+Lemma preg_of_not_PC:
+ forall r, preg_of r <> PC.
+Proof.
+ intros. apply data_diff; auto with asmgen.
+Qed.
+
+(*
+Lemma preg_of_not_SP:
+ forall r, preg_of r <> SP.
+Proof.
+ intros. unfold preg_of; destruct r; cbn; congruence.
+Qed.
+
+Hint Resolve preg_of_not_SP preg_of_not_PC: asmgen.
+
+
+Lemma nextblock_pc:
+ forall b rs, (nextblock b rs)#PC = Val.offset_ptr rs#PC (Ptrofs.repr (size b)).
+Proof.
+ intros. apply Pregmap.gss.
+Qed.
+
+Lemma nextblock_inv:
+ forall b r rs, r <> PC -> (nextblock b rs)#r = rs#r.
+Proof.
+ intros. unfold nextblock. apply Pregmap.gso. red; intro; subst. auto.
+Qed.
+
+Lemma nextblock_inv1:
+ forall b r rs, data_preg r = true -> (nextblock b rs)#r = rs#r.
+Proof.
+ intros. apply nextblock_inv. red; intro; subst; discriminate.
+Qed.
+
+Ltac Simplif :=
+ ((rewrite nextblock_inv by eauto with asmgen)
+ || (rewrite nextblock_inv1 by eauto with asmgen)
+ || (rewrite Pregmap.gss)
+ || (rewrite nextblock_pc)
+ || (rewrite Pregmap.gso by eauto with asmgen)
+ ); auto with asmgen.
+
+Ltac Simpl := repeat Simplif.
+
+(* For Asmblockgenproof0 *)
+
+Theorem exec_basic_instr_pc:
+ forall ge b rs1 m1 rs2 m2,
+ exec_basic_instr ge b rs1 m1 = Next rs2 m2 ->
+ rs2 PC = rs1 PC.
+Proof.
+ intros. destruct b; try destruct i; try destruct i.
+ all: try (inv H; Simpl).
+ 1-10: unfold parexec_load_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.loadv _ _ _); unfold parexec_incorrect_load in *; destruct trap; try discriminate; unfold concrete_default_notrap_load_value in *; inv H1; Simpl; fail.
+
+ 1-20: unfold parexec_load_reg, parexec_load_regxs in H1; destruct (Mem.loadv _ _ _); unfold parexec_incorrect_load in *; destruct trap; try discriminate; unfold concrete_default_notrap_load_value in *; inv H1; Simpl; fail.
+
+ { (* PLoadQRRO *)
+ unfold parexec_load_q_offset in H1.
+ destruct (gpreg_q_expand _) as [r0 r1] in H1.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ inv H1. Simpl. }
+ { (* PLoadORRO *)
+ unfold parexec_load_o_offset in H1.
+ destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ destruct (Mem.loadv _ _ _) in H1; try discriminate.
+ inv H1. Simpl. }
+ 1-8: unfold parexec_store_offset in H1; destruct (eval_offset ofs); try discriminate; destruct (Mem.storev _ _ _); [inv H1; auto | discriminate]; fail.
+ 1-8: unfold parexec_store_reg in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]; auto; fail.
+ 1-8: unfold parexec_store_regxs in H1; destruct (Mem.storev _ _ _); [inv H1; Simpl | discriminate]; auto; fail.
+
+ { (* PStoreQRRO *)
+ unfold parexec_store_q_offset in H1.
+ destruct (gpreg_q_expand _) as [r0 r1] in H1.
+ unfold eval_offset in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ inv H1. Simpl. reflexivity. }
+ { (* PStoreORRO *)
+ unfold parexec_store_o_offset in H1.
+ destruct (gpreg_o_expand _) as [[[r0 r1] r2] r3] in H1.
+ unfold eval_offset in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ destruct (Mem.storev _ _ _) in H1; try discriminate.
+ inv H1. Simpl. reflexivity. }
+ - destruct (Mem.alloc _ _ _). destruct (Mem.store _ _ _ _ _). inv H1. Simpl. discriminate.
+ - destruct (Mem.loadv _ _ _); try discriminate. destruct (rs1 _); try discriminate.
+ destruct (Mem.free _ _ _ _). inv H1. Simpl. discriminate.
+ - destruct rs; try discriminate. inv H1. Simpl.
+ - destruct rd; try discriminate. inv H1; Simpl.
+ - reflexivity.
+Qed.
+
+(* For PostpassSchedulingproof *)
+
+Lemma regset_double_set:
+ forall r1 r2 (rs: regset) v1 v2,
+ r1 <> r2 ->
+ (rs # r1 <- v1 # r2 <- v2) = (rs # r2 <- v2 # r1 <- v1).
+Proof.
+ intros. apply functional_extensionality. intros r. destruct (preg_eq r r1).
+ - subst. rewrite Pregmap.gso; auto. repeat (rewrite Pregmap.gss). auto.
+ - destruct (preg_eq r r2).
+ + subst. rewrite Pregmap.gss. rewrite Pregmap.gso; auto. rewrite Pregmap.gss. auto.
+ + repeat (rewrite Pregmap.gso; auto).
+Qed.
+
+Lemma next_eq:
+ forall (rs rs': regset) m m',
+ rs = rs' -> m = m' -> Next rs m = Next rs' m'.
+Proof.
+ intros; apply f_equal2; auto.
+Qed.
+
+Lemma exec_load_offset_pc_var:
+ forall trap t rs m rd ra ofs rs' m' v,
+ exec_load_offset trap t rs m rd ra ofs = Next rs' m' ->
+ exec_load_offset trap t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_offset in *. unfold parexec_load_offset in *. rewrite Pregmap.gso; try discriminate. destruct (eval_offset ofs); try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_reg_pc_var:
+ forall trap t rs m rd ra ro rs' m' v,
+ exec_load_reg trap t rs m rd ra ro = Next rs' m' ->
+ exec_load_reg trap t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_reg in *. unfold parexec_load_reg in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_regxs_pc_var:
+ forall trap t rs m rd ra ro rs' m' v,
+ exec_load_regxs trap t rs m rd ra ro = Next rs' m' ->
+ exec_load_regxs trap t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_regxs in *. unfold parexec_load_regxs in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _).
+ - inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+ - unfold parexec_incorrect_load in *.
+ destruct trap; try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros. rewrite regset_double_set; auto. discriminate.
+Qed.
+
+Lemma exec_load_offset_q_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_load_q_offset rs m rd ra ofs = Next rs' m' ->
+ exec_load_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_q_offset in *. unfold parexec_load_q_offset in *.
+ destruct (gpreg_q_expand rd) as [rd0 rd1].
+ (* destruct (ireg_eq rd0 ra); try discriminate. *)
+ rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ inv H.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ inv H1. f_equal.
+ rewrite (regset_double_set PC rd0) by discriminate.
+ rewrite (regset_double_set PC rd1) by discriminate.
+ reflexivity.
+Qed.
+
+Lemma exec_load_offset_o_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_load_o_offset rs m rd ra ofs = Next rs' m' ->
+ exec_load_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_load_o_offset in *. unfold parexec_load_o_offset in *.
+ destruct (gpreg_o_expand rd) as [[[rd0 rd1] rd2] rd3].
+(*
+ destruct (ireg_eq rd0 ra); try discriminate.
+ destruct (ireg_eq rd1 ra); try discriminate.
+ destruct (ireg_eq rd2 ra); try discriminate.
+*)
+ rewrite Pregmap.gso; try discriminate.
+ cbn in *.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (Mem.loadv _ _ _); try discriminate.
+ rewrite (regset_double_set PC rd0) by discriminate.
+ rewrite (regset_double_set PC rd1) by discriminate.
+ rewrite (regset_double_set PC rd2) by discriminate.
+ rewrite (regset_double_set PC rd3) by discriminate.
+ inv H.
+ trivial.
+Qed.
+
+Lemma exec_store_offset_pc_var:
+ forall t rs m rd ra ofs rs' m' v,
+ exec_store_offset t rs m rd ra ofs = Next rs' m' ->
+ exec_store_offset t rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_offset in *. unfold parexec_store_offset in *. rewrite Pregmap.gso; try discriminate.
+ destruct (eval_offset ofs); try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Lemma exec_store_q_offset_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_store_q_offset rs m rd ra ofs = Next rs' m' ->
+ exec_store_q_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_q_offset in *. unfold parexec_store_q_offset in *. rewrite Pregmap.gso; try discriminate.
+ cbn in *.
+ destruct (gpreg_q_expand _) as [s0 s1].
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ inv H. apply next_eq; auto.
+Qed.
+
+Lemma exec_store_o_offset_pc_var:
+ forall rs m rd ra ofs rs' m' v,
+ exec_store_o_offset rs m rd ra ofs = Next rs' m' ->
+ exec_store_o_offset rs # PC <- v m rd ra ofs = Next rs' # PC <- v m'.
+Proof.
+ intros.
+ unfold exec_store_o_offset in *. unfold parexec_store_o_offset in *.
+ destruct (gpreg_o_expand _) as [[[s0 s1] s2] s3].
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ destruct (Mem.storev _ _ _); try discriminate.
+ inv H.
+ trivial.
+Qed.
+
+Lemma exec_store_reg_pc_var:
+ forall t rs m rd ra ro rs' m' v,
+ exec_store_reg t rs m rd ra ro = Next rs' m' ->
+ exec_store_reg t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_reg in *. unfold parexec_store_reg in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Lemma exec_store_regxs_pc_var:
+ forall t rs m rd ra ro rs' m' v,
+ exec_store_regxs t rs m rd ra ro = Next rs' m' ->
+ exec_store_regxs t rs # PC <- v m rd ra ro = Next rs' # PC <- v m'.
+Proof.
+ intros. unfold exec_store_regxs in *. unfold parexec_store_regxs in *. rewrite Pregmap.gso; try discriminate.
+ destruct (Mem.storev _ _ _).
+ - inv H. apply next_eq; auto.
+ - discriminate.
+Qed.
+
+Theorem exec_basic_instr_pc_var:
+ forall ge i rs m rs' m' v,
+ exec_basic_instr ge i rs m = Next rs' m' ->
+ exec_basic_instr ge i (rs # PC <- v) m = Next (rs' # PC <- v) m'.
+Proof.
+ intros. unfold exec_basic_instr in *. unfold bstep in *. destruct i.
+ - unfold exec_arith_instr in *. destruct i; destruct i.
+ all: try (exploreInst; inv H; apply next_eq; auto;
+ apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate).
+(*
+ (* Some cases treated seperately because exploreInst destructs too much *)
+ all: try (inv H; apply next_eq; auto; apply functional_extensionality; intros; rewrite regset_double_set; auto; discriminate). *)
+ - destruct i.
+ + exploreInst; apply exec_load_offset_pc_var; auto.
+ + exploreInst; apply exec_load_reg_pc_var; auto.
+ + exploreInst; apply exec_load_regxs_pc_var; auto.
+ + apply exec_load_offset_q_pc_var; auto.
+ + apply exec_load_offset_o_pc_var; auto.
+ - destruct i.
+ + exploreInst; apply exec_store_offset_pc_var; auto.
+ + exploreInst; apply exec_store_reg_pc_var; auto.
+ + exploreInst; apply exec_store_regxs_pc_var; auto.
+ + apply exec_store_q_offset_pc_var; auto.
+ + apply exec_store_o_offset_pc_var; auto.
+ - destruct (Mem.alloc _ _ _) as (m1 & stk). repeat (rewrite Pregmap.gso; try discriminate).
+ destruct (Mem.storev _ _ _ _); try discriminate.
+ inv H. apply next_eq; auto. apply functional_extensionality. intros.
+ rewrite (regset_double_set GPR32 PC); try discriminate.
+ rewrite (regset_double_set GPR12 PC); try discriminate.
+ rewrite (regset_double_set FP PC); try discriminate. reflexivity.
+ - repeat (rewrite Pregmap.gso; try discriminate).
+ destruct (Mem.loadv _ _ _); try discriminate.
+ destruct (rs GPR12); try discriminate.
+ destruct (Mem.free _ _ _ _); try discriminate.
+ inv H. apply next_eq; auto.
+ rewrite (regset_double_set GPR32 PC).
+ rewrite (regset_double_set GPR12 PC). reflexivity.
+ all: discriminate.
+ - destruct rs0; try discriminate. inv H. apply next_eq; auto.
+ repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
+ - destruct rd; try discriminate. inv H. apply next_eq; auto.
+ repeat (rewrite Pregmap.gso; try discriminate). apply regset_double_set; discriminate.
+ - inv H. apply next_eq; auto.
+Qed.
+
+*)
diff --git a/aarch64/Asmexpand.ml b/aarch64/Asmexpand.ml
index b0787d0a..0cee763e 100644
--- a/aarch64/Asmexpand.ml
+++ b/aarch64/Asmexpand.ml
@@ -34,13 +34,13 @@ let _m1 = Z.of_sint (-1)
(* Emit instruction sequences that set or offset a register by a constant. *)
let expand_loadimm32 (dst: ireg) n =
- List.iter emit (Asmgen.loadimm32 dst n [])
+ List.iter emit (OrigAsmgen.loadimm32 dst n [])
let expand_addimm64 (dst: iregsp) (src: iregsp) n =
- List.iter emit (Asmgen.addimm64 dst src n [])
+ List.iter emit (OrigAsmgen.addimm64 dst src n [])
let expand_storeptr (src: ireg) (base: iregsp) ofs =
- List.iter emit (Asmgen.storeptr src base ofs [])
+ List.iter emit (OrigAsmgen.storeptr src base ofs [])
(* Handling of varargs *)
@@ -132,9 +132,9 @@ let expand_builtin_va_start r =
let expand_annot_val kind txt targ args res =
emit (Pbuiltin (EF_annot(kind,txt,[targ]), args, BR_none));
match args, res with
- | [BA(IR src)], BR(IR dst) ->
- if dst <> src then emit (Pmov (RR1 dst, RR1 src))
- | [BA(FR src)], BR(FR dst) ->
+ | [BA(DR(IR src))], BR(DR(IR dst)) ->
+ if dst <> src then emit (Pmov (dst, src))
+ | [BA(DR(FR src))], BR(DR(FR dst)) ->
if dst <> src then emit (Pfmov (dst, src))
| _, _ ->
raise (Error "ill-formed __builtin_annot_val")
@@ -152,8 +152,8 @@ let offset_in_range ofs =
let memcpy_small_arg sz arg tmp =
match arg with
- | BA (IR r) ->
- (RR1 r, _0)
+ | BA (DR(IR r)) ->
+ (r, _0)
| BA_addrstack ofs ->
if offset_in_range ofs
&& offset_in_range (Ptrofs.add ofs (Ptrofs.repr (Z.of_uint sz)))
@@ -164,7 +164,7 @@ let memcpy_small_arg sz arg tmp =
let expand_builtin_memcpy_small sz al src dst =
let (tsrc, tdst) =
- if dst <> BA (IR X17) then (X17, X29) else (X29, X17) in
+ if dst <> BA (DR(IR(RR1 X17))) then (X17, X29) else (X29, X17) in
let (rsrc, osrc) = memcpy_small_arg sz src tsrc in
let (rdst, odst) = memcpy_small_arg sz dst tdst in
let rec copy osrc odst sz =
@@ -197,7 +197,7 @@ let expand_builtin_memcpy_small sz al src dst =
let memcpy_big_arg arg tmp =
match arg with
- | BA (IR r) -> emit (Pmov(RR1 tmp, RR1 r))
+ | BA (DR(IR r)) -> emit (Pmov(RR1 tmp, r))
| BA_addrstack ofs -> expand_addimm64 (RR1 tmp) XSP ofs
| _ -> assert false
@@ -241,29 +241,29 @@ let expand_builtin_memcpy sz al args =
let expand_builtin_vload_common chunk base ofs res =
let addr = ADimm(base, ofs) in
match chunk, res with
- | Mint8unsigned, BR(IR res) ->
+ | Mint8unsigned, BR(DR(IR(RR1 res))) ->
emit (Pldrb(W, res, addr))
- | Mint8signed, BR(IR res) ->
+ | Mint8signed, BR(DR(IR(RR1 res))) ->
emit (Pldrsb(W, res, addr))
- | Mint16unsigned, BR(IR res) ->
+ | Mint16unsigned, BR(DR(IR(RR1 res))) ->
emit (Pldrh(W, res, addr))
- | Mint16signed, BR(IR res) ->
+ | Mint16signed, BR(DR(IR(RR1 res))) ->
emit (Pldrsh(W, res, addr))
- | Mint32, BR(IR res) ->
+ | Mint32, BR(DR(IR(RR1 res))) ->
emit (Pldrw(res, addr))
- | Mint64, BR(IR res) ->
+ | Mint64, BR(DR(IR(RR1 res))) ->
emit (Pldrx(res, addr))
- | Mfloat32, BR(FR res) ->
+ | Mfloat32, BR(DR(FR res)) ->
emit (Pldrs(res, addr))
- | Mfloat64, BR(FR res) ->
+ | Mfloat64, BR(DR(FR res)) ->
emit (Pldrd(res, addr))
| _ ->
assert false
let expand_builtin_vload chunk args res =
match args with
- | [BA(IR addr)] ->
- expand_builtin_vload_common chunk (RR1 addr) _0 res
+ | [BA(DR(IR addr))] ->
+ expand_builtin_vload_common chunk addr _0 res
| [BA_addrstack ofs] ->
if offset_in_range (Z.add ofs (Memdata.size_chunk chunk)) then
expand_builtin_vload_common chunk XSP ofs res
@@ -271,11 +271,11 @@ let expand_builtin_vload chunk args res =
expand_addimm64 (RR1 X16) XSP ofs; (* X16 <- SP + ofs *)
expand_builtin_vload_common chunk (RR1 X16) _0 res
end
- | [BA_addptr(BA(IR addr), BA_long ofs)] ->
+ | [BA_addptr(BA(DR(IR addr)), BA_long ofs)] ->
if offset_in_range (Z.add ofs (Memdata.size_chunk chunk)) then
- expand_builtin_vload_common chunk (RR1 addr) ofs res
+ expand_builtin_vload_common chunk addr ofs res
else begin
- expand_addimm64 (RR1 X16) (RR1 addr) ofs; (* X16 <- addr + ofs *)
+ expand_addimm64 (RR1 X16) addr ofs; (* X16 <- addr + ofs *)
expand_builtin_vload_common chunk (RR1 X16) _0 res
end
| _ ->
@@ -284,25 +284,25 @@ let expand_builtin_vload chunk args res =
let expand_builtin_vstore_common chunk base ofs src =
let addr = ADimm(base, ofs) in
match chunk, src with
- | (Mint8signed | Mint8unsigned), BA(IR src) ->
+ | (Mint8signed | Mint8unsigned), BA(DR(IR(RR1 src))) ->
emit (Pstrb(src, addr))
- | (Mint16signed | Mint16unsigned), BA(IR src) ->
+ | (Mint16signed | Mint16unsigned), BA(DR(IR(RR1 src))) ->
emit (Pstrh(src, addr))
- | Mint32, BA(IR src) ->
+ | Mint32, BA(DR(IR(RR1 src))) ->
emit (Pstrw(src, addr))
- | Mint64, BA(IR src) ->
+ | Mint64, BA(DR(IR(RR1 src))) ->
emit (Pstrx(src, addr))
- | Mfloat32, BA(FR src) ->
+ | Mfloat32, BA(DR(FR src)) ->
emit (Pstrs(src, addr))
- | Mfloat64, BA(FR src) ->
+ | Mfloat64, BA(DR(FR src)) ->
emit (Pstrd(src, addr))
| _ ->
assert false
let expand_builtin_vstore chunk args =
match args with
- | [BA(IR addr); src] ->
- expand_builtin_vstore_common chunk (RR1 addr) _0 src
+ | [BA(DR(IR addr)); src] ->
+ expand_builtin_vstore_common chunk addr _0 src
| [BA_addrstack ofs; src] ->
if offset_in_range (Z.add ofs (Memdata.size_chunk chunk)) then
expand_builtin_vstore_common chunk XSP ofs src
@@ -310,11 +310,11 @@ let expand_builtin_vstore chunk args =
expand_addimm64 (RR1 X16) XSP ofs; (* X16 <- SP + ofs *)
expand_builtin_vstore_common chunk (RR1 X16) _0 src
end
- | [BA_addptr(BA(IR addr), BA_long ofs); src] ->
+ | [BA_addptr(BA(DR(IR addr)), BA_long ofs); src] ->
if offset_in_range (Z.add ofs (Memdata.size_chunk chunk)) then
- expand_builtin_vstore_common chunk (RR1 addr) ofs src
+ expand_builtin_vstore_common chunk addr ofs src
else begin
- expand_addimm64 (RR1 X16) (RR1 addr) ofs; (* X16 <- addr + ofs *)
+ expand_addimm64 (RR1 X16) addr ofs; (* X16 <- addr + ofs *)
expand_builtin_vstore_common chunk (RR1 X16) _0 src
end
| _ ->
@@ -330,37 +330,37 @@ let expand_builtin_inline name args res =
| "__builtin_nop", [], _ ->
emit Pnop
(* Byte swap *)
- | ("__builtin_bswap" | "__builtin_bswap32"), [BA(IR a1)], BR(IR res) ->
+ | ("__builtin_bswap" | "__builtin_bswap32"), [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Prev(W, res, a1))
- | "__builtin_bswap64", [BA(IR a1)], BR(IR res) ->
+ | "__builtin_bswap64", [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Prev(X, res, a1))
- | "__builtin_bswap16", [BA(IR a1)], BR(IR res) ->
+ | "__builtin_bswap16", [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Prev16(W, res, a1));
emit (Pandimm(W, res, RR0 res, Z.of_uint 0xFFFF))
(* Count leading zeros and leading sign bits *)
- | "__builtin_clz", [BA(IR a1)], BR(IR res) ->
+ | "__builtin_clz", [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Pclz(W, res, a1))
- | ("__builtin_clzl" | "__builtin_clzll"), [BA(IR a1)], BR(IR res) ->
+ | ("__builtin_clzl" | "__builtin_clzll"), [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Pclz(X, res, a1))
- | "__builtin_cls", [BA(IR a1)], BR(IR res) ->
+ | "__builtin_cls", [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Pcls(W, res, a1))
- | ("__builtin_clsl" | "__builtin_clsll"), [BA(IR a1)], BR(IR res) ->
+ | ("__builtin_clsl" | "__builtin_clsll"), [BA(DR(IR(RR1 a1)))], BR(DR(IR(RR1 res))) ->
emit (Pcls(X, res, a1))
(* Float arithmetic *)
- | "__builtin_fabs", [BA(FR a1)], BR(FR res) ->
+ | "__builtin_fabs", [BA(DR(FR a1))], BR(DR(FR res)) ->
emit (Pfabs(D, res, a1))
- | "__builtin_fsqrt", [BA(FR a1)], BR(FR res) ->
+ | "__builtin_fsqrt", [BA(DR(FR a1))], BR(DR(FR res)) ->
emit (Pfsqrt(D, res, a1))
- | "__builtin_fmadd", [BA(FR a1); BA(FR a2); BA(FR a3)], BR(FR res) ->
+ | "__builtin_fmadd", [BA(DR(FR a1)); BA(DR(FR a2)); BA(DR(FR a3))], BR(DR(FR res)) ->
emit (Pfmadd(D, res, a1, a2, a3))
- | "__builtin_fmsub", [BA(FR a1); BA(FR a2); BA(FR a3)], BR(FR res) ->
+ | "__builtin_fmsub", [BA(DR(FR a1)); BA(DR(FR a2)); BA(DR(FR a3))], BR(DR(FR res)) ->
emit (Pfmsub(D, res, a1, a2, a3))
- | "__builtin_fnmadd", [BA(FR a1); BA(FR a2); BA(FR a3)], BR(FR res) ->
+ | "__builtin_fnmadd", [BA(DR(FR a1)); BA(DR(FR a2)); BA(DR(FR a3))], BR(DR(FR res)) ->
emit (Pfnmadd(D, res, a1, a2, a3))
- | "__builtin_fnmsub", [BA(FR a1); BA(FR a2); BA(FR a3)], BR(FR res) ->
+ | "__builtin_fnmsub", [BA(DR(FR a1)); BA(DR(FR a2)); BA(DR(FR a3))], BR(DR(FR res)) ->
emit (Pfnmsub(D, res, a1, a2, a3))
(* Vararg *)
- | "__builtin_va_start", [BA(IR a)], _ ->
+ | "__builtin_va_start", [BA(DR(IR(RR1 a)))], _ ->
expand_builtin_va_start a
(* Catch-all *)
| _ ->
@@ -427,9 +427,9 @@ let float_reg_to_dwarf = function
| D30 -> 94 | D31 -> 95
let preg_to_dwarf = function
- | IR r -> int_reg_to_dwarf r
- | FR r -> float_reg_to_dwarf r
- | SP -> 31
+ | DR(IR(RR1 r)) -> int_reg_to_dwarf r
+ | DR(FR r) -> float_reg_to_dwarf r
+ | DR(IR(XSP)) -> 31
| _ -> assert false
let expand_function id fn =
diff --git a/aarch64/Asmgen.v b/aarch64/Asmgen.v
index 024c9a17..bd6b55cc 100644
--- a/aarch64/Asmgen.v
+++ b/aarch64/Asmgen.v
@@ -1,1172 +1,364 @@
-(* *********************************************************************)
-(* *)
-(* The Compcert verified compiler *)
-(* *)
-(* Xavier Leroy, Collège de France and INRIA Paris *)
-(* *)
-(* Copyright Institut National de Recherche en Informatique et en *)
-(* Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the INRIA Non-Commercial License Agreement. *)
-(* *)
-(* *********************************************************************)
-
-(** Translation from Mach to AArch64. *)
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Justus Fasse UGA, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
Require Import Recdef Coqlib Zwf Zbits.
Require Import Errors AST Integers Floats Op.
-Require Import Locations Mach Asm.
-
-Local Open Scope string_scope.
-Local Open Scope list_scope.
-Local Open Scope error_monad_scope.
-
-(** Alignment check for symbols *)
-
-Parameter symbol_is_aligned : ident -> Z -> bool.
-(** [symbol_is_aligned id sz] checks whether the symbol [id] is [sz] aligned *)
-
-(** Extracting integer or float registers. *)
-
-Definition ireg_of (r: mreg) : res ireg :=
- match preg_of r with IR mr => OK mr | _ => Error(msg "Asmgen.ireg_of") end.
-
-Definition freg_of (r: mreg) : res freg :=
- match preg_of r with FR mr => OK mr | _ => Error(msg "Asmgen.freg_of") end.
-
-(** Recognition of immediate arguments for logical integer operations.*)
-
-(** Valid immediate arguments are repetitions of a bit pattern [B]
- of length [e] = 2, 4, 8, 16, 32 or 64.
- The bit pattern [B] must be of the form [0*1*0*] or [1*0*1*]
- but must not be all zeros or all ones. *)
-
-(** The following automaton recognizes [0*1*0*|1*0*1*].
-<<
- 0 1 0
- / \ / \ / \
- \ / \ / \ /
- -0--> [B] --1--> [D] --0--> [F]
- /
- [A]
- \
- -1--> [C] --0--> [E] --1--> [G]
- / \ / \ / \
- \ / \ / \ /
- 1 0 1
->>
-*)
-
-Module Automaton.
-
-Inductive state : Type := SA | SB | SC | SD | SE | SF | SG | Sbad.
-
-Definition start := SA.
-
-Definition next (s: state) (b: bool) :=
- match s, b with
- | SA,false => SB | SA,true => SC
- | SB,false => SB | SB,true => SD
- | SC,false => SE | SC,true => SC
- | SD,false => SF | SD,true => SD
- | SE,false => SE | SE,true => SG
- | SF,false => SF | SF,true => Sbad
- | SG,false => Sbad | SG,true => SG
- | Sbad,_ => Sbad
- end.
-
-Definition accepting (s: state) :=
- match s with
- | SA | SB | SC | SD | SE | SF | SG => true
- | Sbad => false
- end.
-
-Fixpoint run (len: nat) (s: state) (x: Z) : bool :=
- match len with
- | Datatypes.O => accepting s
- | Datatypes.S len => run len (next s (Z.odd x)) (Z.div2 x)
- end.
-
-End Automaton.
-
-(** The following function determines the candidate length [e],
- ensuring that [x] is a repetition [BB...B]
- of a bit pattern [B] of length [e]. *)
-
-Definition logical_imm_length (x: Z) (sixtyfour: bool) : nat :=
- (** [test n] checks that the low [2n] bits of [x] are of the
- form [BB], that is, two occurrences of the same [n] bits *)
- let test (n: Z) : bool :=
- Z.eqb (Zzero_ext n x) (Zzero_ext n (Z.shiftr x n)) in
- (** If [test n] fails, we know that the candidate length [e] is
- at least [2n]. Hence we test with decreasing values of [n]:
- 32, 16, 8, 4, 2. *)
- if sixtyfour && negb (test 32) then 64%nat
- else if negb (test 16) then 32%nat
- else if negb (test 8) then 16%nat
- else if negb (test 4) then 8%nat
- else if negb (test 2) then 4%nat
- else 2%nat.
-
-(** A valid logical immediate is
-- neither [0] nor [-1];
-- composed of a repetition [BBBBB] of a bit-pattern [B] of length [e]
-- the low [e] bits of the number, that is, [B], match [0*1*0*] or [1*0*1*].
-*)
-
-Definition is_logical_imm32 (x: int) : bool :=
- negb (Int.eq x Int.zero) && negb (Int.eq x Int.mone) &&
- Automaton.run (logical_imm_length (Int.unsigned x) false)
- Automaton.start (Int.unsigned x).
-
-Definition is_logical_imm64 (x: int64) : bool :=
- negb (Int64.eq x Int64.zero) && negb (Int64.eq x Int64.mone) &&
- Automaton.run (logical_imm_length (Int64.unsigned x) true)
- Automaton.start (Int64.unsigned x).
-
-(** Arithmetic immediates are 12-bit unsigned numbers, possibly shifted left 12 bits *)
-
-Definition is_arith_imm32 (x: int) : bool :=
- Int.eq x (Int.zero_ext 12 x)
- || Int.eq x (Int.shl (Int.zero_ext 12 (Int.shru x (Int.repr 12))) (Int.repr 12)).
-
-Definition is_arith_imm64 (x: int64) : bool :=
- Int64.eq x (Int64.zero_ext 12 x)
- || Int64.eq x (Int64.shl (Int64.zero_ext 12 (Int64.shru x (Int64.repr 12))) (Int64.repr 12)).
-
-(** Decompose integer literals into 16-bit fragments *)
-
-Fixpoint decompose_int (N: nat) (n p: Z) {struct N} : list (Z * Z) :=
- match N with
- | Datatypes.O => nil
- | Datatypes.S N =>
- let frag := Zzero_ext 16 (Z.shiftr n p) in
- if Z.eqb frag 0 then
- decompose_int N n (p + 16)
- else
- (frag, p) :: decompose_int N (Z.ldiff n (Z.shiftl 65535 p)) (p + 16)
- end.
-
-Definition negate_decomposition (l: list (Z * Z)) :=
- List.map (fun np => (Z.lxor (fst np) 65535, snd np)) l.
-
-Definition loadimm_k (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: code) : code :=
- List.fold_right (fun np k => Pmovk sz rd (fst np) (snd np) :: k) k l.
-
-Definition loadimm_z (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: code) : code :=
- match l with
- | nil => Pmovz sz rd 0 0 :: k
- | (n1, p1) :: l => Pmovz sz rd n1 p1 :: loadimm_k sz rd l k
- end.
-
-Definition loadimm_n (sz: isize) (rd: ireg) (l: list (Z * Z)) (k: code) : code :=
- match l with
- | nil => Pmovn sz rd 0 0 :: k
- | (n1, p1) :: l => Pmovn sz rd n1 p1 :: loadimm_k sz rd (negate_decomposition l) k
- end.
-
-Definition loadimm (sz: isize) (rd: ireg) (n: Z) (k: code) : code :=
- let N := match sz with W => 2%nat | X => 4%nat end in
- let dz := decompose_int N n 0 in
- let dn := decompose_int N (Z.lnot n) 0 in
- if Nat.leb (List.length dz) (List.length dn)
- then loadimm_z sz rd dz k
- else loadimm_n sz rd dn k.
-
-Definition loadimm32 (rd: ireg) (n: int) (k: code) : code :=
- if is_logical_imm32 n
- then Porrimm W rd XZR (Int.unsigned n) :: k
- else loadimm W rd (Int.unsigned n) k.
-
-Definition loadimm64 (rd: ireg) (n: int64) (k: code) : code :=
- if is_logical_imm64 n
- then Porrimm X rd XZR (Int64.unsigned n) :: k
- else loadimm X rd (Int64.unsigned n) k.
-
-(** Add immediate *)
-
-Definition addimm_aux (insn: iregsp -> iregsp -> Z -> instruction)
- (rd r1: iregsp) (n: Z) (k: code) :=
- let nlo := Zzero_ext 12 n in
- let nhi := n - nlo in
- if Z.eqb nhi 0 then
- insn rd r1 nlo :: k
- else if Z.eqb nlo 0 then
- insn rd r1 nhi :: k
- else
- insn rd r1 nhi :: insn rd rd nlo :: k.
-
-Definition addimm32 (rd r1: ireg) (n: int) (k: code) : code :=
- let m := Int.neg n in
- if Int.eq n (Int.zero_ext 24 n) then
- addimm_aux (Paddimm W) rd r1 (Int.unsigned n) k
- else if Int.eq m (Int.zero_ext 24 m) then
- addimm_aux (Psubimm W) rd r1 (Int.unsigned m) k
- else if Int.lt n Int.zero then
- loadimm32 X16 m (Psub W rd r1 X16 SOnone :: k)
- else
- loadimm32 X16 n (Padd W rd r1 X16 SOnone :: k).
-
-Definition addimm64 (rd r1: iregsp) (n: int64) (k: code) : code :=
- let m := Int64.neg n in
- if Int64.eq n (Int64.zero_ext 24 n) then
- addimm_aux (Paddimm X) rd r1 (Int64.unsigned n) k
- else if Int64.eq m (Int64.zero_ext 24 m) then
- addimm_aux (Psubimm X) rd r1 (Int64.unsigned m) k
- else if Int64.lt n Int64.zero then
- loadimm64 X16 m (Psubext rd r1 X16 (EOuxtx Int.zero) :: k)
- else
- loadimm64 X16 n (Paddext rd r1 X16 (EOuxtx Int.zero) :: k).
+Require Import Locations Compopts.
+Require Import Mach Asm Asmblock Asmblockgen Machblockgen PseudoAsmblock PseudoAsmblockproof PostpassScheduling.
-(** Logical immediate *)
-Definition logicalimm32
- (insn1: ireg -> ireg0 -> Z -> instruction)
- (insn2: ireg -> ireg0 -> ireg -> shift_op -> instruction)
- (rd r1: ireg) (n: int) (k: code) : code :=
- if is_logical_imm32 n
- then insn1 rd r1 (Int.unsigned n) :: k
- else loadimm32 X16 n (insn2 rd r1 X16 SOnone :: k).
-
-Definition logicalimm64
- (insn1: ireg -> ireg0 -> Z -> instruction)
- (insn2: ireg -> ireg0 -> ireg -> shift_op -> instruction)
- (rd r1: ireg) (n: int64) (k: code) : code :=
- if is_logical_imm64 n
- then insn1 rd r1 (Int64.unsigned n) :: k
- else loadimm64 X16 n (insn2 rd r1 X16 SOnone :: k).
-
-(** Sign- or zero-extended arithmetic *)
-
-Definition transl_extension (ex: extension) (a: int) : extend_op :=
- match ex with Xsgn32 => EOsxtw a | Xuns32 => EOuxtw a end.
-
-Definition move_extended_base
- (rd: ireg) (r1: ireg) (ex: extension) (k: code) : code :=
- match ex with
- | Xsgn32 => Pcvtsw2x rd r1 :: k
- | Xuns32 => Pcvtuw2x rd r1 :: k
- end.
-
-Definition move_extended
- (rd: ireg) (r1: ireg) (ex: extension) (a: int) (k: code) : code :=
- if Int.eq a Int.zero then
- move_extended_base rd r1 ex k
- else
- move_extended_base rd r1 ex (Padd X rd XZR rd (SOlsl a) :: k).
-
-Definition arith_extended
- (insnX: iregsp -> iregsp -> ireg -> extend_op -> instruction)
- (insnS: ireg -> ireg0 -> ireg -> shift_op -> instruction)
- (rd r1 r2: ireg) (ex: extension) (a: int) (k: code) : code :=
- if Int.ltu a (Int.repr 5) then
- insnX rd r1 r2 (transl_extension ex a) :: k
- else
- move_extended_base X16 r2 ex (insnS rd r1 X16 (SOlsl a) :: k).
-
-(** Extended right shift *)
-
-Definition shrx32 (rd r1: ireg) (n: int) (k: code) : code :=
- if Int.eq n Int.zero then
- Pmov rd r1 :: k
- else if Int.eq n Int.one then
- Padd W X16 r1 r1 (SOlsr (Int.repr 31)) ::
- Porr W rd XZR X16 (SOasr n) :: k
- else
- Porr W X16 XZR r1 (SOasr (Int.repr 31)) ::
- Padd W X16 r1 X16 (SOlsr (Int.sub Int.iwordsize n)) ::
- Porr W rd XZR X16 (SOasr n) :: k.
-
-Definition shrx64 (rd r1: ireg) (n: int) (k: code) : code :=
- if Int.eq n Int.zero then
- Pmov rd r1 :: k
- else if Int.eq n Int.one then
- Padd X X16 r1 r1 (SOlsr (Int.repr 63)) ::
- Porr X rd XZR X16 (SOasr n) :: k
- else
- Porr X X16 XZR r1 (SOasr (Int.repr 63)) ::
- Padd X X16 r1 X16 (SOlsr (Int.sub Int64.iwordsize' n)) ::
- Porr X rd XZR X16 (SOasr n) :: k.
-
-(** Load the address [id + ofs] in [rd] *)
-
-Definition loadsymbol (rd: ireg) (id: ident) (ofs: ptrofs) (k: code) : code :=
- if Archi.pic_code tt then
- if Ptrofs.eq ofs Ptrofs.zero then
- Ploadsymbol rd id :: k
- else
- Ploadsymbol rd id :: addimm64 rd rd (Ptrofs.to_int64 ofs) k
- else
- Padrp rd id ofs :: Paddadr rd rd id ofs :: k.
-
-(** Translate a shifted operand *)
-
-Definition transl_shift (s: Op.shift) (a: int): Asm.shift_op :=
- match s with
- | Slsl => SOlsl a
- | Slsr => SOlsr a
- | Sasr => SOasr a
- | Sror => SOror a
- end.
-
-(** Translation of a condition. Prepends to [k] the instructions
- that evaluate the condition and leave its boolean result in one of
- the bits of the condition register. The bit in question is
- determined by the [crbit_for_cond] function. *)
-
-Definition transl_cond
- (cond: condition) (args: list mreg) (k: code) :=
- match cond, args with
- | (Ccomp c | Ccompu c), a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pcmp W r1 r2 SOnone :: k)
- | (Ccompshift c s a | Ccompushift c s a), a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pcmp W r1 r2 (transl_shift s a) :: k)
- | (Ccompimm c n | Ccompuimm c n), a1 :: nil =>
- do r1 <- ireg_of a1;
- OK (if is_arith_imm32 n then
- Pcmpimm W r1 (Int.unsigned n) :: k
- else if is_arith_imm32 (Int.neg n) then
- Pcmnimm W r1 (Int.unsigned (Int.neg n)) :: k
- else
- loadimm32 X16 n (Pcmp W r1 X16 SOnone :: k))
- | (Cmaskzero n | Cmasknotzero n), a1 :: nil =>
- do r1 <- ireg_of a1;
- OK (if is_logical_imm32 n then
- Ptstimm W r1 (Int.unsigned n) :: k
- else
- loadimm32 X16 n (Ptst W r1 X16 SOnone :: k))
- | (Ccompl c | Ccomplu c), a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pcmp X r1 r2 SOnone :: k)
- | (Ccomplshift c s a | Ccomplushift c s a), a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pcmp X r1 r2 (transl_shift s a) :: k)
- | (Ccomplimm c n | Ccompluimm c n), a1 :: nil =>
- do r1 <- ireg_of a1;
- OK (if is_arith_imm64 n then
- Pcmpimm X r1 (Int64.unsigned n) :: k
- else if is_arith_imm64 (Int64.neg n) then
- Pcmnimm X r1 (Int64.unsigned (Int64.neg n)) :: k
- else
- loadimm64 X16 n (Pcmp X r1 X16 SOnone :: k))
- | (Cmasklzero n | Cmasklnotzero n), a1 :: nil =>
- do r1 <- ireg_of a1;
- OK (if is_logical_imm64 n then
- Ptstimm X r1 (Int64.unsigned n) :: k
- else
- loadimm64 X16 n (Ptst X r1 X16 SOnone :: k))
- | Ccompf cmp, a1 :: a2 :: nil =>
- do r1 <- freg_of a1; do r2 <- freg_of a2;
- OK (Pfcmp D r1 r2 :: k)
- | Cnotcompf cmp, a1 :: a2 :: nil =>
- do r1 <- freg_of a1; do r2 <- freg_of a2;
- OK (Pfcmp D r1 r2 :: k)
- | Ccompfzero cmp, a1 :: nil =>
- do r1 <- freg_of a1;
- OK (Pfcmp0 D r1 :: k)
- | Cnotcompfzero cmp, a1 :: nil =>
- do r1 <- freg_of a1;
- OK (Pfcmp0 D r1 :: k)
- | Ccompfs cmp, a1 :: a2 :: nil =>
- do r1 <- freg_of a1; do r2 <- freg_of a2;
- OK (Pfcmp S r1 r2 :: k)
- | Cnotcompfs cmp, a1 :: a2 :: nil =>
- do r1 <- freg_of a1; do r2 <- freg_of a2;
- OK (Pfcmp S r1 r2 :: k)
- | Ccompfszero cmp, a1 :: nil =>
- do r1 <- freg_of a1;
- OK (Pfcmp0 S r1 :: k)
- | Cnotcompfszero cmp, a1 :: nil =>
- do r1 <- freg_of a1;
- OK (Pfcmp0 S r1 :: k)
- | _, _ =>
- Error(msg "Asmgen.transl_cond")
- end.
+Local Open Scope error_monad_scope.
-Definition cond_for_signed_cmp (cmp: comparison) :=
- match cmp with
- | Ceq => TCeq
- | Cne => TCne
- | Clt => TClt
- | Cle => TCle
- | Cgt => TCgt
- | Cge => TCge
- end.
+(** * Translation from Asmblock to assembly language
+ Inspired from the KVX backend (see kvx/Asm.v and kvx/Asmgen.v) *)
-Definition cond_for_unsigned_cmp (cmp: comparison) :=
- match cmp with
- | Ceq => TCeq
- | Cne => TCne
- | Clt => TClo
- | Cle => TCls
- | Cgt => TChi
- | Cge => TChs
- end.
+Module Asmblock_TRANSF.
+(* STUB *)
-Definition cond_for_float_cmp (cmp: comparison) :=
- match cmp with
- | Ceq => TCeq
- | Cne => TCne
- | Clt => TCmi
- | Cle => TCls
- | Cgt => TCgt
- | Cge => TCge
+Definition ireg_of_preg (p : Asm.preg) : res ireg :=
+ match p with
+ | DR (IR (RR1 r)) => OK r
+ | _ => Error (msg "Asmgen.ireg_of_preg")
end.
-Definition cond_for_float_not_cmp (cmp: comparison) :=
- match cmp with
- | Ceq => TCne
- | Cne => TCeq
- | Clt => TCpl
- | Cle => TChi
- | Cgt => TCle
- | Cge => TClt
+Definition freg_of_preg (p : Asm.preg) : res freg :=
+ match p with
+ | DR (FR r) => OK r
+ | _ => Error (msg "Asmgen.freg_of_preg")
end.
-Definition cond_for_cond (cond: condition) :=
- match cond with
- | Ccomp cmp => cond_for_signed_cmp cmp
- | Ccompu cmp => cond_for_unsigned_cmp cmp
- | Ccompshift cmp s a => cond_for_signed_cmp cmp
- | Ccompushift cmp s a => cond_for_unsigned_cmp cmp
- | Ccompimm cmp n => cond_for_signed_cmp cmp
- | Ccompuimm cmp n => cond_for_unsigned_cmp cmp
- | Cmaskzero n => TCeq
- | Cmasknotzero n => TCne
- | Ccompl cmp => cond_for_signed_cmp cmp
- | Ccomplu cmp => cond_for_unsigned_cmp cmp
- | Ccomplshift cmp s a => cond_for_signed_cmp cmp
- | Ccomplushift cmp s a => cond_for_unsigned_cmp cmp
- | Ccomplimm cmp n => cond_for_signed_cmp cmp
- | Ccompluimm cmp n => cond_for_unsigned_cmp cmp
- | Cmasklzero n => TCeq
- | Cmasklnotzero n => TCne
- | Ccompf cmp => cond_for_float_cmp cmp
- | Cnotcompf cmp => cond_for_float_not_cmp cmp
- | Ccompfzero cmp => cond_for_float_cmp cmp
- | Cnotcompfzero cmp => cond_for_float_not_cmp cmp
- | Ccompfs cmp => cond_for_float_cmp cmp
- | Cnotcompfs cmp => cond_for_float_not_cmp cmp
- | Ccompfszero cmp => cond_for_float_cmp cmp
- | Cnotcompfszero cmp => cond_for_float_not_cmp cmp
+Definition iregsp_of_preg (p : Asm.preg) : res iregsp :=
+ match p with
+ | DR (IR r) => OK r
+ | _ => Error (msg "Asmgen.iregsp_of_preg")
end.
-(** Translation of a conditional branch. Prepends to [k] the instructions
- that evaluate the condition and ranch to [lbl] if it holds.
- We recognize some conditional branches that can be implemented
- without setting then testing condition flags. *)
-
-Definition transl_cond_branch_default
- (c: condition) (args: list mreg) (lbl: label) (k: code) :=
- transl_cond c args (Pbc (cond_for_cond c) lbl :: k).
-
-Definition transl_cond_branch
- (c: condition) (args: list mreg) (lbl: label) (k: code) :=
- match args, c with
- | a1 :: nil, (Ccompimm Cne n | Ccompuimm Cne n) =>
- if Int.eq n Int.zero
- then (do r1 <- ireg_of a1; OK (Pcbnz W r1 lbl :: k))
- else transl_cond_branch_default c args lbl k
- | a1 :: nil, (Ccompimm Ceq n | Ccompuimm Ceq n) =>
- if Int.eq n Int.zero
- then (do r1 <- ireg_of a1; OK (Pcbz W r1 lbl :: k))
- else transl_cond_branch_default c args lbl k
- | a1 :: nil, (Ccomplimm Cne n | Ccompluimm Cne n) =>
- if Int64.eq n Int64.zero
- then (do r1 <- ireg_of a1; OK (Pcbnz X r1 lbl :: k))
- else transl_cond_branch_default c args lbl k
- | a1 :: nil, (Ccomplimm Ceq n | Ccompluimm Ceq n) =>
- if Int64.eq n Int64.zero
- then (do r1 <- ireg_of a1; OK (Pcbz X r1 lbl :: k))
- else transl_cond_branch_default c args lbl k
- | a1 :: nil, Cmaskzero n =>
- match Int.is_power2 n with
- | Some bit => do r1 <- ireg_of a1; OK (Ptbz W r1 bit lbl :: k)
- | None => transl_cond_branch_default c args lbl k
+Definition basic_to_instruction (b: basic) : res Asm.instruction :=
+ match b with
+ (* Aithmetic instructions *)
+ | PArith (PArithP (Padrp id ofs) rd) => do rd' <- ireg_of_preg rd;
+ OK (Asm.Padrp rd' id ofs)
+ | PArith (PArithP (Pmovz sz n pos) rd) => do rd' <- ireg_of_preg rd;
+ OK (Asm.Pmovz sz rd' n pos)
+ | PArith (PArithP (Pmovn sz n pos) rd) => do rd' <- ireg_of_preg rd;
+ OK (Asm.Pmovn sz rd' n pos)
+ | PArith (PArithP (Pfmovimms f) rd) => do rd' <- freg_of_preg rd;
+ OK (Asm.Pfmovimms rd' f)
+ | PArith (PArithP (Pfmovimmd f) rd) => do rd' <- freg_of_preg rd;
+ OK (Asm.Pfmovimmd rd' f)
+
+ | PArith (PArithPP (Pmovk sz n pos) rd rs) =>
+ if (Asm.preg_eq rd rs) then (
+ do rd' <- ireg_of_preg rd;
+ OK (Asm.Pmovk sz rd' n pos)
+ ) else
+ Error (msg "Asmgen.basic_to_instruction: Pmovk uses a single register as both source and target")
+ | PArith (PArithPP Pmov rd rs) => do rd' <- iregsp_of_preg rd;
+ do rs' <- iregsp_of_preg rs;
+ OK (Asm.Pmov rd' rs')
+ | PArith (PArithPP (Paddadr id ofs) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Paddadr rd' rs' id ofs)
+ | PArith (PArithPP (Psbfiz sz r s) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Psbfiz sz rd' rs' r s)
+ | PArith (PArithPP (Psbfx sz r s) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Psbfx sz rd' rs' r s)
+ | PArith (PArithPP (Pubfiz sz r s) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Pubfiz sz rd' rs' r s)
+ | PArith (PArithPP (Pubfx sz r s) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Pubfx sz rd' rs' r s)
+ | PArith (PArithPP Pfmov rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfmov rd' rs')
+ | PArith (PArithPP Pfcvtds rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfcvtds rd' rs')
+ | PArith (PArithPP Pfcvtsd rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfcvtsd rd' rs')
+ | PArith (PArithPP (Pfabs sz) rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfabs sz rd' rs')
+ | PArith (PArithPP (Pfneg sz) rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfneg sz rd' rs')
+ | PArith (PArithPP (Pscvtf fsz isz) rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Pscvtf fsz isz rd' rs')
+ | PArith (PArithPP (Pucvtf fsz isz) rd rs) => do rd' <- freg_of_preg rd;
+ do rs' <- ireg_of_preg rs;
+ OK (Asm.Pucvtf fsz isz rd' rs')
+ | PArith (PArithPP (Pfcvtzs isz fsz) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfcvtzs isz fsz rd' rs')
+ | PArith (PArithPP (Pfcvtzu isz fsz) rd rs) => do rd' <- ireg_of_preg rd;
+ do rs' <- freg_of_preg rs;
+ OK (Asm.Pfcvtzu isz fsz rd' rs')
+ | PArith (PArithPP (Paddimm sz n) rd rs) => do rd' <- iregsp_of_preg rd;
+ do rs' <- iregsp_of_preg rs;
+ OK (Asm.Paddimm sz rd' rs' n)
+ | PArith (PArithPP (Psubimm sz n) rd rs) => do rd' <- iregsp_of_preg rd;
+ do rs' <- iregsp_of_preg rs;
+ OK (Asm.Psubimm sz rd' rs' n)
+
+ | PArith (PArithPPP (Pasrv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Pasrv sz rd' r1' r2')
+ | PArith (PArithPPP (Plslv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Plslv sz rd' r1' r2')
+ | PArith (PArithPPP (Plsrv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Plsrv sz rd' r1' r2')
+ | PArith (PArithPPP (Prorv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Prorv sz rd' r1' r2')
+ | PArith (PArithPPP Psmulh rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Psmulh rd' r1' r2')
+ | PArith (PArithPPP Pumulh rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Pumulh rd' r1' r2')
+ | PArith (PArithPPP (Psdiv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Psdiv sz rd' r1' r2')
+ | PArith (PArithPPP (Pudiv sz) rd r1 r2) => do rd' <- ireg_of_preg rd;
+ do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Pudiv sz rd' r1' r2')
+ | PArith (PArithPPP (Paddext x) rd r1 r2) => do rd' <- iregsp_of_preg rd;
+ do r1' <- iregsp_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Paddext rd' r1' r2' x)
+ | PArith (PArithPPP (Psubext x) rd r1 r2) => do rd' <- iregsp_of_preg rd;
+ do r1' <- iregsp_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Psubext rd' r1' r2' x)
+ | PArith (PArithPPP (Pfadd sz) rd r1 r2) => do rd' <- freg_of_preg rd;
+ do r1' <- freg_of_preg r1;
+ do r2' <- freg_of_preg r2;
+ OK (Asm.Pfadd sz rd' r1' r2')
+ | PArith (PArithPPP (Pfdiv sz) rd r1 r2) => do rd' <- freg_of_preg rd;
+ do r1' <- freg_of_preg r1;
+ do r2' <- freg_of_preg r2;
+ OK (Asm.Pfdiv sz rd' r1' r2')
+ | PArith (PArithPPP (Pfmul sz) rd r1 r2) => do rd' <- freg_of_preg rd;
+ do r1' <- freg_of_preg r1;
+ do r2' <- freg_of_preg r2;
+ OK (Asm.Pfmul sz rd' r1' r2')
+ | PArith (PArithPPP (Pfsub sz) rd r1 r2) => do rd' <- freg_of_preg rd;
+ do r1' <- freg_of_preg r1;
+ do r2' <- freg_of_preg r2;
+ OK (Asm.Pfsub sz rd' r1' r2')
+
+ | PArith (PArithRR0 (Pandimm sz n) rd r1) => OK (Asm.Pandimm sz rd r1 n)
+ | PArith (PArithRR0 (Peorimm sz n) rd r1) => OK (Asm.Peorimm sz rd r1 n)
+ | PArith (PArithRR0 (Porrimm sz n) rd r1) => OK (Asm.Porrimm sz rd r1 n)
+
+
+ | PArith (PArithRR0R (Padd sz s) rd r1 r2) => OK (Asm.Padd sz rd r1 r2 s)
+ | PArith (PArithRR0R (Psub sz s) rd r1 r2) => OK (Asm.Psub sz rd r1 r2 s)
+ | PArith (PArithRR0R (Pand sz s) rd r1 r2) => OK (Asm.Pand sz rd r1 r2 s)
+ | PArith (PArithRR0R (Pbic sz s) rd r1 r2) => OK (Asm.Pbic sz rd r1 r2 s)
+ | PArith (PArithRR0R (Peon sz s) rd r1 r2) => OK (Asm.Peon sz rd r1 r2 s)
+ | PArith (PArithRR0R (Peor sz s) rd r1 r2) => OK (Asm.Peor sz rd r1 r2 s)
+ | PArith (PArithRR0R (Porr sz s) rd r1 r2) => OK (Asm.Porr sz rd r1 r2 s)
+ | PArith (PArithRR0R (Porn sz s) rd r1 r2) => OK (Asm.Porn sz rd r1 r2 s)
+
+ | PArith (PArithARRRR0 (Pmadd sz) rd r1 r2 r3) => OK (Asm.Pmadd sz rd r1 r2 r3)
+ | PArith (PArithARRRR0 (Pmsub sz) rd r1 r2 r3) => OK (Asm.Pmsub sz rd r1 r2 r3)
+
+ | PArith (PArithComparisonPP (Pcmpext x) r1 r2) => do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Pcmpext r1' r2' x)
+ | PArith (PArithComparisonPP (Pcmnext x) r1 r2) => do r1' <- ireg_of_preg r1;
+ do r2' <- ireg_of_preg r2;
+ OK (Asm.Pcmnext r1' r2' x)
+ | PArith (PArithComparisonPP (Pfcmp sz) r1 r2) => do r1' <- freg_of_preg r1;
+ do r2' <- freg_of_preg r2;
+ OK (Asm.Pfcmp sz r1' r2')
+
+ | PArith (PArithComparisonR0R (Pcmp is s) r1 r2) => OK (Asm.Pcmp is r1 r2 s)
+ | PArith (PArithComparisonR0R (Pcmn is s) r1 r2) => OK (Asm.Pcmn is r1 r2 s)
+ | PArith (PArithComparisonR0R (Ptst is s) r1 r2) => OK (Asm.Ptst is r1 r2 s)
+
+ | PArith (PArithComparisonP (Pcmpimm sz n) r1) => do r1' <- ireg_of_preg r1;
+ OK (Asm.Pcmpimm sz r1' n)
+ | PArith (PArithComparisonP (Pcmnimm sz n) r1) => do r1' <- ireg_of_preg r1;
+ OK (Asm.Pcmnimm sz r1' n)
+ | PArith (PArithComparisonP (Ptstimm sz n) r1) => do r1' <- ireg_of_preg r1;
+ OK (Asm.Ptstimm sz r1' n)
+ | PArith (PArithComparisonP (Pfcmp0 sz) r1) => do r1' <- freg_of_preg r1;
+ OK (Asm.Pfcmp0 sz r1')
+
+ | PArith (Pcset rd c) => OK (Asm.Pcset rd c)
+ | PArith (Pfmovi fsz rd r1) => OK (Asm.Pfmovi fsz rd r1)
+ | PArith (Pcsel rd r1 r2 c) =>
+ match r1, r2 with
+ | IR r1', IR r2' => do rd' <- ireg_of_preg rd;
+ do r1'' <- ireg_of_preg r1';
+ do r2'' <- ireg_of_preg r2';
+ OK (Asm.Pcsel rd' r1'' r2'' c)
+ | FR r1', FR r2' => do rd' <- freg_of_preg rd;
+ do r1'' <- freg_of_preg r1';
+ do r2'' <- freg_of_preg r2';
+ OK (Asm.Pfsel rd' r1'' r2'' c)
+ | _, _ => Error (msg "Asmgen.basic_to_instruction: Pcsel is only defind on iregs and fregs.")
end
- | a1 :: nil, Cmasknotzero n =>
- match Int.is_power2 n with
- | Some bit => do r1 <- ireg_of a1; OK (Ptbnz W r1 bit lbl :: k)
- | None => transl_cond_branch_default c args lbl k
- end
- | a1 :: nil, Cmasklzero n =>
- match Int64.is_power2' n with
- | Some bit => do r1 <- ireg_of a1; OK (Ptbz X r1 bit lbl :: k)
- | None => transl_cond_branch_default c args lbl k
- end
- | a1 :: nil, Cmasklnotzero n =>
- match Int64.is_power2' n with
- | Some bit => do r1 <- ireg_of a1; OK (Ptbnz X r1 bit lbl :: k)
- | None => transl_cond_branch_default c args lbl k
- end
- | _, _ =>
- transl_cond_branch_default c args lbl k
- end.
-
-(** Translation of the arithmetic operation [res <- op(args)].
- The corresponding instructions are prepended to [k]. *)
+ | PArith (Pfnmul fsz rd r1 r2) => OK (Asm.Pfnmul fsz rd r1 r2)
-Definition transl_op
- (op: operation) (args: list mreg) (res: mreg) (k: code) :=
- match op, args with
- | Omove, a1 :: nil =>
- match preg_of res, preg_of a1 with
- | IR r, IR a => OK (Pmov r a :: k)
- | FR r, FR a => OK (Pfmov r a :: k)
- | _ , _ => Error(msg "Asmgen.Omove")
- end
- | Ointconst n, nil =>
- do rd <- ireg_of res;
- OK (loadimm32 rd n k)
- | Olongconst n, nil =>
- do rd <- ireg_of res;
- OK (loadimm64 rd n k)
- | Ofloatconst f, nil =>
- do rd <- freg_of res;
- OK (if Float.eq_dec f Float.zero
- then Pfmovi D rd XZR :: k
- else Pfmovimmd rd f :: k)
- | Osingleconst f, nil =>
- do rd <- freg_of res;
- OK (if Float32.eq_dec f Float32.zero
- then Pfmovi S rd XZR :: k
- else Pfmovimms rd f :: k)
- | Oaddrsymbol id ofs, nil =>
- do rd <- ireg_of res;
- OK (loadsymbol rd id ofs k)
- | Oaddrstack ofs, nil =>
- do rd <- ireg_of res;
- OK (addimm64 rd XSP (Ptrofs.to_int64 ofs) k)
-(** 32-bit integer arithmetic *)
- | Oshift s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porr W rd XZR r1 (transl_shift s a) :: k)
- | Oadd, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Padd W rd r1 r2 SOnone :: k)
- | Oaddshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Padd W rd r1 r2 (transl_shift s a) :: k)
- | Oaddimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (addimm32 rd r1 n k)
- | Oneg, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psub W rd XZR r1 SOnone :: k)
- | Onegshift s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psub W rd XZR r1 (transl_shift s a) :: k)
- | Osub, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psub W rd r1 r2 SOnone :: k)
- | Osubshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psub W rd r1 r2 (transl_shift s a) :: k)
- | Omul, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pmadd W rd r1 r2 XZR :: k)
- | Omuladd, a1 :: a2 :: a3 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
- OK (Pmadd W rd r2 r3 r1 :: k)
- | Omulsub, a1 :: a2 :: a3 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
- OK (Pmsub W rd r2 r3 r1 :: k)
- | Odiv, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psdiv W rd r1 r2 :: k)
- | Odivu, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pudiv W rd r1 r2 :: k)
- | Oand, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pand W rd r1 r2 SOnone :: k)
- | Oandshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pand W rd r1 r2 (transl_shift s a) :: k)
- | Oandimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm32 (Pandimm W) (Pand W) rd r1 n k)
- | Oor, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porr W rd r1 r2 SOnone :: k)
- | Oorshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porr W rd r1 r2 (transl_shift s a) :: k)
- | Oorimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm32 (Porrimm W) (Porr W) rd r1 n k)
- | Oxor, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peor W rd r1 r2 SOnone :: k)
- | Oxorshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peor W rd r1 r2 (transl_shift s a) :: k)
- | Oxorimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm32 (Peorimm W) (Peor W) rd r1 n k)
- | Onot, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porn W rd XZR r1 SOnone :: k)
- | Onotshift s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porn W rd XZR r1 (transl_shift s a) :: k)
- | Obic, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pbic W rd r1 r2 SOnone :: k)
- | Obicshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pbic W rd r1 r2 (transl_shift s a) :: k)
- | Oorn, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porn W rd r1 r2 SOnone :: k)
- | Oornshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porn W rd r1 r2 (transl_shift s a) :: k)
- | Oeqv, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peon W rd r1 r2 SOnone :: k)
- | Oeqvshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peon W rd r1 r2 (transl_shift s a) :: k)
- | Oshl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Plslv W rd r1 r2 :: k)
- | Oshr, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pasrv W rd r1 r2 :: k)
- | Oshru, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Plsrv W rd r1 r2 :: k)
- | Oshrximm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (shrx32 rd r1 n k)
- | Ozext s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfiz W rd r1 Int.zero s :: k)
- | Osext s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfiz W rd r1 Int.zero s :: k)
- | Oshlzext s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfiz W rd r1 a (Z.min s (Int.zwordsize - Int.unsigned a)) :: k)
- | Oshlsext s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfiz W rd r1 a (Z.min s (Int.zwordsize - Int.unsigned a)) :: k)
- | Ozextshr a s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfx W rd r1 a (Z.min s (Int.zwordsize - Int.unsigned a)) :: k)
- | Osextshr a s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfx W rd r1 a (Z.min s (Int.zwordsize - Int.unsigned a)) :: k)
-(** 64-bit integer arithmetic *)
- | Oshiftl s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porr X rd XZR r1 (transl_shift s a) :: k)
- | Oextend x a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (move_extended rd r1 x a k)
- (* [Omakelong] and [Ohighlong] should not occur *)
- | Olowlong, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- assertion (ireg_eq rd r1);
- OK (Pcvtx2w rd :: k)
- | Oaddl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Padd X rd r1 r2 SOnone :: k)
- | Oaddlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Padd X rd r1 r2 (transl_shift s a) :: k)
- | Oaddlext x a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (arith_extended Paddext (Padd X) rd r1 r2 x a k)
- | Oaddlimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (addimm64 rd r1 n k)
- | Onegl, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psub X rd XZR r1 SOnone :: k)
- | Oneglshift s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psub X rd XZR r1 (transl_shift s a) :: k)
- | Osubl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psub X rd r1 r2 SOnone :: k)
- | Osublshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psub X rd r1 r2 (transl_shift s a) :: k)
- | Osublext x a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (arith_extended Psubext (Psub X) rd r1 r2 x a k)
- | Omull, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pmadd X rd r1 r2 XZR :: k)
- | Omulladd, a1 :: a2 :: a3 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
- OK (Pmadd X rd r2 r3 r1 :: k)
- | Omullsub, a1 :: a2 :: a3 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2; do r3 <- ireg_of a3;
- OK (Pmsub X rd r2 r3 r1 :: k)
- | Omullhs, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psmulh rd r1 r2 :: k)
- | Omullhu, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pumulh rd r1 r2 :: k)
- | Odivl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Psdiv X rd r1 r2 :: k)
- | Odivlu, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pudiv X rd r1 r2 :: k)
- | Oandl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pand X rd r1 r2 SOnone :: k)
- | Oandlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pand X rd r1 r2 (transl_shift s a) :: k)
- | Oandlimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm64 (Pandimm X) (Pand X) rd r1 n k)
- | Oorl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porr X rd r1 r2 SOnone :: k)
- | Oorlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porr X rd r1 r2 (transl_shift s a) :: k)
- | Oorlimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm64 (Porrimm X) (Porr X) rd r1 n k)
- | Oxorl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peor X rd r1 r2 SOnone :: k)
- | Oxorlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peor X rd r1 r2 (transl_shift s a) :: k)
- | Oxorlimm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (logicalimm64 (Peorimm X) (Peor X) rd r1 n k)
- | Onotl, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porn X rd XZR r1 SOnone :: k)
- | Onotlshift s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Porn X rd XZR r1 (transl_shift s a) :: k)
- | Obicl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pbic X rd r1 r2 SOnone :: k)
- | Obiclshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pbic X rd r1 r2 (transl_shift s a) :: k)
- | Oornl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porn X rd r1 r2 SOnone :: k)
- | Oornlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Porn X rd r1 r2 (transl_shift s a) :: k)
- | Oeqvl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peon X rd r1 r2 SOnone :: k)
- | Oeqvlshift s a, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Peon X rd r1 r2 (transl_shift s a) :: k)
- | Oshll, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Plslv X rd r1 r2 :: k)
- | Oshrl, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Pasrv X rd r1 r2 :: k)
- | Oshrlu, a1 :: a2 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (Plsrv X rd r1 r2 :: k)
- | Oshrlximm n, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (shrx64 rd r1 n k)
- | Ozextl s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfiz X rd r1 Int.zero s :: k)
- | Osextl s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfiz X rd r1 Int.zero s :: k)
- | Oshllzext s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfiz X rd r1 a (Z.min s (Int64.zwordsize - Int.unsigned a)) :: k)
- | Oshllsext s a, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfiz X rd r1 a (Z.min s (Int64.zwordsize - Int.unsigned a)) :: k)
- | Ozextshrl a s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Pubfx X rd r1 a (Z.min s (Int64.zwordsize - Int.unsigned a)) :: k)
- | Osextshrl a s, a1 :: nil =>
- do rd <- ireg_of res; do r1 <- ireg_of a1;
- OK (Psbfx X rd r1 a (Z.min s (Int64.zwordsize - Int.unsigned a)) :: k)
-(** 64-bit floating-point arithmetic *)
- | Onegf, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfneg D rd rs :: k)
- | Oabsf, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfabs D rd rs :: k)
- | Oaddf, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfadd D rd rs1 rs2 :: k)
- | Osubf, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfsub D rd rs1 rs2 :: k)
- | Omulf, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfmul D rd rs1 rs2 :: k)
- | Odivf, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfdiv D rd rs1 rs2 :: k)
-(** 32-bit floating-point arithmetic *)
- | Onegfs, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfneg S rd rs :: k)
- | Oabsfs, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfabs S rd rs :: k)
- | Oaddfs, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfadd S rd rs1 rs2 :: k)
- | Osubfs, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfsub S rd rs1 rs2 :: k)
- | Omulfs, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfmul S rd rs1 rs2 :: k)
- | Odivfs, a1 :: a2 :: nil =>
- do rd <- freg_of res; do rs1 <- freg_of a1; do rs2 <- freg_of a2;
- OK (Pfdiv S rd rs1 rs2 :: k)
- | Osingleoffloat, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfcvtsd rd rs :: k)
- | Ofloatofsingle, a1 :: nil =>
- do rd <- freg_of res; do rs <- freg_of a1;
- OK (Pfcvtds rd rs :: k)
-(** Conversions between int and float *)
- | Ointoffloat, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzs W D rd rs :: k)
- | Ointuoffloat, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzu W D rd rs :: k)
- | Ofloatofint, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pscvtf D W rd rs :: k)
- | Ofloatofintu, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pucvtf D W rd rs :: k)
- | Ointofsingle, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzs W S rd rs :: k)
- | Ointuofsingle, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzu W S rd rs :: k)
- | Osingleofint, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pscvtf S W rd rs :: k)
- | Osingleofintu, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pucvtf S W rd rs :: k)
- | Olongoffloat, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzs X D rd rs :: k)
- | Olonguoffloat, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzu X D rd rs :: k)
- | Ofloatoflong, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pscvtf D X rd rs :: k)
- | Ofloatoflongu, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pucvtf D X rd rs :: k)
- | Olongofsingle, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzs X S rd rs :: k)
- | Olonguofsingle, a1 :: nil =>
- do rd <- ireg_of res; do rs <- freg_of a1;
- OK (Pfcvtzu X S rd rs :: k)
- | Osingleoflong, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pscvtf S X rd rs :: k)
- | Osingleoflongu, a1 :: nil =>
- do rd <- freg_of res; do rs <- ireg_of a1;
- OK (Pucvtf S X rd rs :: k)
-(** Boolean tests *)
- | Ocmp c, _ =>
- do rd <- ireg_of res;
- transl_cond c args (Pcset rd (cond_for_cond c) :: k)
-(** Conditional move *)
- | Osel cmp ty, a1 :: a2 :: args =>
- match preg_of res with
- | IR r =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- transl_cond cmp args (Pcsel r r1 r2 (cond_for_cond cmp) :: k)
- | FR r =>
- do r1 <- freg_of a1; do r2 <- freg_of a2;
- transl_cond cmp args (Pfsel r r1 r2 (cond_for_cond cmp) :: k)
- | _ =>
- Error(msg "Asmgen.Osel")
- end
- | _, _ =>
- Error(msg "Asmgen.transl_op")
- end.
+ | PLoad Pldrw rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrw rd' a)
+ | PLoad Pldrw_a rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrw_a rd' a)
+ | PLoad Pldrx rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrx rd' a)
+ | PLoad Pldrx_a rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrx_a rd' a)
+ | PLoad (Pldrb sz) rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrb sz rd' a)
+ | PLoad (Pldrsb sz) rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrsb sz rd' a)
+ | PLoad (Pldrh sz) rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrh sz rd' a)
+ | PLoad (Pldrsh sz) rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrsh sz rd' a)
+ | PLoad Pldrzw rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrzw rd' a)
+ | PLoad Pldrsw rd a => do rd' <- ireg_of_preg rd; OK (Asm.Pldrsw rd' a)
-(** Translation of addressing modes *)
+ | PLoad Pldrs rd a => do rd' <- freg_of_preg rd; OK (Asm.Pldrs rd' a)
+ | PLoad Pldrd rd a => do rd' <- freg_of_preg rd; OK (Asm.Pldrd rd' a)
+ | PLoad Pldrd_a rd a => do rd' <- freg_of_preg rd; OK (Asm.Pldrd_a rd' a)
-Definition offset_representable (sz: Z) (ofs: int64) : bool :=
- let isz := Int64.repr sz in
- (** either unscaled 9-bit signed *)
- Int64.eq ofs (Int64.sign_ext 9 ofs) ||
- (** or scaled 12-bit unsigned *)
- (Int64.eq (Int64.modu ofs isz) Int64.zero
- && Int64.ltu ofs (Int64.shl isz (Int64.repr 12))).
-
-Definition transl_addressing (sz: Z) (addr: Op.addressing) (args: list mreg)
- (insn: Asm.addressing -> instruction) (k: code) : res code :=
- match addr, args with
- | Aindexed ofs, a1 :: nil =>
- do r1 <- ireg_of a1;
- if offset_representable sz ofs then
- OK (insn (ADimm r1 ofs) :: k)
- else
- OK (loadimm64 X16 ofs (insn (ADreg r1 X16) :: k))
- | Aindexed2, a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- OK (insn (ADreg r1 r2) :: k)
- | Aindexed2shift a, a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- if Int.eq a Int.zero then
- OK (insn (ADreg r1 r2) :: k)
- else if Int.eq (Int.shl Int.one a) (Int.repr sz) then
- OK (insn (ADlsl r1 r2 a) :: k)
- else
- OK (Padd X X16 r1 r2 (SOlsl a) :: insn (ADimm X16 Int64.zero) :: k)
- | Aindexed2ext x a, a1 :: a2 :: nil =>
- do r1 <- ireg_of a1; do r2 <- ireg_of a2;
- if Int.eq a Int.zero || Int.eq (Int.shl Int.one a) (Int.repr sz) then
- OK (insn (match x with Xsgn32 => ADsxt r1 r2 a
- | Xuns32 => ADuxt r1 r2 a end) :: k)
- else
- OK (arith_extended Paddext (Padd X) X16 r1 r2 x a
- (insn (ADimm X16 Int64.zero) :: k))
- | Aglobal id ofs, nil =>
- assertion (negb (Archi.pic_code tt));
- if Ptrofs.eq (Ptrofs.modu ofs (Ptrofs.repr sz)) Ptrofs.zero && symbol_is_aligned id sz
- then OK (Padrp X16 id ofs :: insn (ADadr X16 id ofs) :: k)
- else OK (loadsymbol X16 id ofs (insn (ADimm X16 Int64.zero) :: k))
- | Ainstack ofs, nil =>
- let ofs := Ptrofs.to_int64 ofs in
- if offset_representable sz ofs then
- OK (insn (ADimm XSP ofs) :: k)
- else
- OK (loadimm64 X16 ofs (insn (ADreg XSP X16) :: k))
- | _, _ =>
- Error(msg "Asmgen.transl_addressing")
- end.
+ | PStore Pstrw r a => do r' <- ireg_of_preg r; OK (Asm.Pstrw r' a)
+ | PStore Pstrw_a r a => do r' <- ireg_of_preg r; OK (Asm.Pstrw_a r' a)
+ | PStore Pstrx r a => do r' <- ireg_of_preg r; OK (Asm.Pstrx r' a)
+ | PStore Pstrx_a r a => do r' <- ireg_of_preg r; OK (Asm.Pstrx_a r' a)
+ | PStore Pstrb r a => do r' <- ireg_of_preg r; OK (Asm.Pstrb r' a)
+ | PStore Pstrh r a => do r' <- ireg_of_preg r; OK (Asm.Pstrh r' a)
-(** Translation of loads and stores *)
+ | PStore Pstrs r a => do r' <- freg_of_preg r; OK (Asm.Pstrs r' a)
+ | PStore Pstrd r a => do r' <- freg_of_preg r; OK (Asm.Pstrd r' a)
+ | PStore Pstrd_a r a => do r' <- freg_of_preg r; OK (Asm.Pstrd_a r' a)
-Definition transl_load (trap: trapping_mode)
- (chunk: memory_chunk) (addr: Op.addressing)
- (args: list mreg) (dst: mreg) (k: code) : res code :=
- match trap with
- | NOTRAP => Error (msg "Asmgen.transl_load non-trapping loads unsupported on aarch64")
- | TRAP =>
- match chunk with
- | Mint8unsigned =>
- do rd <- ireg_of dst; transl_addressing 1 addr args (Pldrb W rd) k
- | Mint8signed =>
- do rd <- ireg_of dst; transl_addressing 1 addr args (Pldrsb W rd) k
- | Mint16unsigned =>
- do rd <- ireg_of dst; transl_addressing 2 addr args (Pldrh W rd) k
- | Mint16signed =>
- do rd <- ireg_of dst; transl_addressing 2 addr args (Pldrsh W rd) k
- | Mint32 =>
- do rd <- ireg_of dst; transl_addressing 4 addr args (Pldrw rd) k
- | Mint64 =>
- do rd <- ireg_of dst; transl_addressing 8 addr args (Pldrx rd) k
- | Mfloat32 =>
- do rd <- freg_of dst; transl_addressing 4 addr args (Pldrs rd) k
- | Mfloat64 =>
- do rd <- freg_of dst; transl_addressing 8 addr args (Pldrd rd) k
- | Many32 =>
- do rd <- ireg_of dst; transl_addressing 4 addr args (Pldrw_a rd) k
- | Many64 =>
- do rd <- ireg_of dst; transl_addressing 8 addr args (Pldrx_a rd) k
- end
- end.
+ | Pallocframe sz linkofs => OK (Asm.Pallocframe sz linkofs)
+ | Pfreeframe sz linkofs => OK (Asm.Pfreeframe sz linkofs)
-Definition transl_store (chunk: memory_chunk) (addr: Op.addressing)
- (args: list mreg) (src: mreg) (k: code) : res code :=
- match chunk with
- | Mint8unsigned | Mint8signed =>
- do r1 <- ireg_of src; transl_addressing 1 addr args (Pstrb r1) k
- | Mint16unsigned | Mint16signed =>
- do r1 <- ireg_of src; transl_addressing 2 addr args (Pstrh r1) k
- | Mint32 =>
- do r1 <- ireg_of src; transl_addressing 4 addr args (Pstrw r1) k
- | Mint64 =>
- do r1 <- ireg_of src; transl_addressing 8 addr args (Pstrx r1) k
- | Mfloat32 =>
- do r1 <- freg_of src; transl_addressing 4 addr args (Pstrs r1) k
- | Mfloat64 =>
- do r1 <- freg_of src; transl_addressing 8 addr args (Pstrd r1) k
- | Many32 =>
- do r1 <- ireg_of src; transl_addressing 4 addr args (Pstrw_a r1) k
- | Many64 =>
- do r1 <- ireg_of src; transl_addressing 8 addr args (Pstrx_a r1) k
- end.
+ | Ploadsymbol rd id => OK (Asm.Ploadsymbol rd id)
-(** Register-indexed loads and stores *)
+ | Pcvtsw2x rd r1 => OK (Asm.Pcvtsw2x rd r1)
-Definition indexed_memory_access (insn: Asm.addressing -> instruction)
- (sz: Z) (base: iregsp) (ofs: ptrofs) (k: code) :=
- let ofs := Ptrofs.to_int64 ofs in
- if offset_representable sz ofs
- then insn (ADimm base ofs) :: k
- else loadimm64 X16 ofs (insn (ADreg base X16) :: k).
+ | Pcvtuw2x rd r1 => OK (Asm.Pcvtuw2x rd r1)
-Definition loadind (base: iregsp) (ofs: ptrofs) (ty: typ) (dst: mreg) (k: code) :=
- match ty, preg_of dst with
- | Tint, IR rd => OK (indexed_memory_access (Pldrw rd) 4 base ofs k)
- | Tlong, IR rd => OK (indexed_memory_access (Pldrx rd) 8 base ofs k)
- | Tsingle, FR rd => OK (indexed_memory_access (Pldrs rd) 4 base ofs k)
- | Tfloat, FR rd => OK (indexed_memory_access (Pldrd rd) 8 base ofs k)
- | Tany32, IR rd => OK (indexed_memory_access (Pldrw_a rd) 4 base ofs k)
- | Tany64, IR rd => OK (indexed_memory_access (Pldrx_a rd) 8 base ofs k)
- | Tany64, FR rd => OK (indexed_memory_access (Pldrd_a rd) 8 base ofs k)
- | _, _ => Error (msg "Asmgen.loadind")
+ | Pcvtx2w rd => OK (Asm.Pcvtx2w rd)
end.
-Definition storeind (src: mreg) (base: iregsp) (ofs: ptrofs) (ty: typ) (k: code) :=
- match ty, preg_of src with
- | Tint, IR rd => OK (indexed_memory_access (Pstrw rd) 4 base ofs k)
- | Tlong, IR rd => OK (indexed_memory_access (Pstrx rd) 8 base ofs k)
- | Tsingle, FR rd => OK (indexed_memory_access (Pstrs rd) 4 base ofs k)
- | Tfloat, FR rd => OK (indexed_memory_access (Pstrd rd) 8 base ofs k)
- | Tany32, IR rd => OK (indexed_memory_access (Pstrw_a rd) 4 base ofs k)
- | Tany64, IR rd => OK (indexed_memory_access (Pstrx_a rd) 8 base ofs k)
- | Tany64, FR rd => OK (indexed_memory_access (Pstrd_a rd) 8 base ofs k)
- | _, _ => Error (msg "Asmgen.storeind")
+Definition cf_instruction_to_instruction (cfi: cf_instruction) : Asm.instruction :=
+ match cfi with
+ | Pb l => Asm.Pb l
+ | Pbc c lbl => Asm.Pbc c lbl
+ | Pbl id sg => Asm.Pbl id sg
+ | Pbs id sg => Asm.Pbs id sg
+ | Pblr r sg => Asm.Pblr r sg
+ | Pbr r sg => Asm.Pbr r sg
+ | Pret r => Asm.Pret r
+ | Pcbnz sz r lbl => Asm.Pcbnz sz r lbl
+ | Pcbz sz r lbl => Asm.Pcbz sz r lbl
+ | Ptbnz sz r n lbl => Asm.Ptbnz sz r n lbl
+ | Ptbz sz r n lbl => Asm.Ptbz sz r n lbl
+ | Pbtbl r1 tbl => Asm.Pbtbl r1 tbl
end.
-Definition loadptr (base: iregsp) (ofs: ptrofs) (dst: ireg) (k: code) :=
- indexed_memory_access (Pldrx dst) 8 base ofs k.
-
-Definition storeptr (src: ireg) (base: iregsp) (ofs: ptrofs) (k: code) :=
- indexed_memory_access (Pstrx src) 8 base ofs k.
-
-(** Function epilogue *)
-
-Definition make_epilogue (f: Mach.function) (k: code) :=
- (* FIXME
- Cannot be used because memcpy destroys X30;
- issue being discussed with X. Leroy *)
- (* if is_leaf_function f
- then Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k
- else*) loadptr XSP f.(fn_retaddr_ofs) RA
- (Pfreeframe f.(fn_stacksize) f.(fn_link_ofs) :: k).
-
-(** Translation of a Mach instruction. *)
-
-Definition transl_instr (f: Mach.function) (i: Mach.instruction)
- (r29_is_parent: bool) (k: code) : res code :=
- match i with
- | Mgetstack ofs ty dst =>
- loadind XSP ofs ty dst k
- | Msetstack src ofs ty =>
- storeind src XSP ofs ty k
- | Mgetparam ofs ty dst =>
- (* load via the frame pointer if it is valid *)
- do c <- loadind X29 ofs ty dst k;
- OK (if r29_is_parent then c else loadptr XSP f.(fn_link_ofs) X29 c)
- | Mop op args res =>
- transl_op op args res k
- | Mload trap chunk addr args dst =>
- transl_load trap chunk addr args dst k
- | Mstore chunk addr args src =>
- transl_store chunk addr args src k
- | Mcall sig (inl r) =>
- do r1 <- ireg_of r; OK (Pblr r1 sig :: k)
- | Mcall sig (inr symb) =>
- OK (Pbl symb sig :: k)
- | Mtailcall sig (inl r) =>
- do r1 <- ireg_of r;
- OK (make_epilogue f (Pbr r1 sig :: k))
- | Mtailcall sig (inr symb) =>
- OK (make_epilogue f (Pbs symb sig :: k))
- | Mbuiltin ef args res =>
- OK (Pbuiltin ef (List.map (map_builtin_arg preg_of) args) (map_builtin_res preg_of res) :: k)
- | Mlabel lbl =>
- OK (Plabel lbl :: k)
- | Mgoto lbl =>
- OK (Pb lbl :: k)
- | Mcond cond args lbl =>
- transl_cond_branch cond args lbl k
- | Mjumptable arg tbl =>
- do r <- ireg_of arg;
- OK (Pbtbl r tbl :: k)
- | Mreturn =>
- OK (make_epilogue f (Pret RA :: k))
+Definition control_to_instruction (c: control) :=
+ match c with
+ | PCtlFlow i => cf_instruction_to_instruction i
+ | Pbuiltin ef args res => Asm.Pbuiltin ef (List.map (map_builtin_arg DR) args) (map_builtin_res DR res)
end.
-(** Translation of a code sequence *)
-
-Definition it1_is_parent (before: bool) (i: Mach.instruction) : bool :=
- match i with
- | Msetstack src ofs ty => before
- | Mgetparam ofs ty dst => negb (mreg_eq dst R29)
- | Mop op args res => before && negb (mreg_eq res R29)
- | _ => false
+Fixpoint unfold_label (ll: list label) :=
+ match ll with
+ | nil => nil
+ | l :: ll => Plabel l :: unfold_label ll
end.
-(** This is the naive definition that we no longer use because it
- is not tail-recursive. It is kept as specification. *)
-
-Fixpoint transl_code (f: Mach.function) (il: list Mach.instruction) (it1p: bool) :=
- match il with
+Fixpoint unfold_body (lb: list basic) : res Asm.code :=
+ match lb with
| nil => OK nil
- | i1 :: il' =>
- do k <- transl_code f il' (it1_is_parent it1p i1);
- transl_instr f i1 it1p k
+ | b :: lb =>
+ (* x_is: x's instructions *)
+ do b_is <- basic_to_instruction b;
+ do lb_is <- unfold_body lb;
+ OK (b_is :: lb_is)
end.
-(** This is an equivalent definition in continuation-passing style
- that runs in constant stack space. *)
-
-Fixpoint transl_code_rec (f: Mach.function) (il: list Mach.instruction)
- (it1p: bool) (k: code -> res code) :=
- match il with
- | nil => k nil
- | i1 :: il' =>
- transl_code_rec f il' (it1_is_parent it1p i1)
- (fun c1 => do c2 <- transl_instr f i1 it1p c1; k c2)
+Definition unfold_exit (oc: option control) :=
+ match oc with
+ | None => nil
+ | Some c => control_to_instruction c :: nil
end.
-Definition transl_code' (f: Mach.function) (il: list Mach.instruction) (it1p: bool) :=
- transl_code_rec f il it1p (fun c => OK c).
+Definition unfold_bblock (bb: bblock) :=
+ let lbl := unfold_label (header bb) in
+ (*
+ * With this dynamically checked assumption on a previous optimization we
+ * can show that [Asmblock.label_pos] and [Asm.label_pos] retrieve the same
+ * exact address. Maintaining this property allows us to use the simple
+ * formulation of match_states defined as equality.
+ * Otherwise we would have to deal with the case of a basic block header
+ * that has multiple labels. Asmblock.label_pos will, for all labels, point
+ * to the same location at the beginning of the basic block. Asm.label_pos
+ * on the other hand could return a position pointing into the original
+ * basic block.
+ *)
+ (*if zle (list_length_z (header bb)) 1 then*)
+ do bo_is <- unfold_body (body bb);
+ OK (lbl ++ bo_is ++ unfold_exit (exit bb)).
+ (*else*)
+ (*Error (msg "Asmgen.unfold_bblock: Multiple labels were generated.").*)
+
+Fixpoint unfold (bbs: Asmblock.bblocks) : res Asm.code :=
+ match bbs with
+ | nil => OK (nil)
+ | bb :: bbs' =>
+ do bb_is <- unfold_bblock bb;
+ do bbs'_is <- unfold bbs';
+ OK (bb_is ++ bbs'_is)
+ end.
-(** Translation of a whole function. Note that we must check
- that the generated code contains less than [2^32] instructions,
- otherwise the offset part of the [PC] code pointer could wrap
- around, leading to incorrect executions. *)
+Definition transf_function (f: Asmblock.function) : res Asm.function :=
+ do c <- unfold (Asmblock.fn_blocks f);
+ if zlt Ptrofs.max_unsigned (list_length_z c)
+ then Error (msg "Asmgen.trans_function: code size exceeded")
+ else OK {| Asm.fn_sig := Asmblock.fn_sig f; Asm.fn_code := c |}.
-Definition transl_function (f: Mach.function) :=
- do c <- transl_code' f f.(Mach.fn_code) true;
- OK (mkfunction f.(Mach.fn_sig)
- (Pallocframe f.(fn_stacksize) f.(fn_link_ofs) ::
- storeptr RA XSP f.(fn_retaddr_ofs) c)).
+Definition transf_fundef (f: Asmblock.fundef) : res Asm.fundef :=
+ transf_partial_fundef transf_function f.
-Definition transf_function (f: Mach.function) : res Asm.function :=
- do tf <- transl_function f;
- if zlt Ptrofs.max_unsigned (list_length_z tf.(fn_code))
- then Error (msg "code size exceeded")
- else OK tf.
+Definition transf_program (p: Asmblock.program) : res Asm.program :=
+ transform_partial_program transf_fundef p.
-Definition transf_fundef (f: Mach.fundef) : res Asm.fundef :=
- transf_partial_fundef transf_function f.
+End Asmblock_TRANSF.
Definition transf_program (p: Mach.program) : res Asm.program :=
- transform_partial_program transf_fundef p.
+ let mbp := Machblockgen.transf_program p in
+ do mbp' <- PseudoAsmblockproof.transf_program mbp;
+ do abp <- Asmblockgen.transf_program mbp';
+ do abp' <- (time "PostpassScheduling total oracle+verification" PostpassScheduling.transf_program) abp;
+ Asmblock_TRANSF.transf_program abp'.
diff --git a/aarch64/Asmgenproof.v b/aarch64/Asmgenproof.v
index 6831509f..d062654b 100644
--- a/aarch64/Asmgenproof.v
+++ b/aarch64/Asmgenproof.v
@@ -1,24 +1,35 @@
-(* *********************************************************************)
-(* *)
-(* The Compcert verified compiler *)
-(* *)
-(* Xavier Leroy, Collège de France and INRIA Paris *)
-(* *)
-(* Copyright Institut National de Recherche en Informatique et en *)
-(* Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the INRIA Non-Commercial License Agreement. *)
-(* *)
-(* *********************************************************************)
-
-(** Correctness proof for AArch64 code generation. *)
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* Justus Fasse UGA, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
Require Import Coqlib Errors.
Require Import Integers Floats AST Linking.
Require Import Values Memory Events Globalenvs Smallstep.
-Require Import Op Locations Mach Conventions Asm.
-Require Import Asmgen Asmgenproof0 Asmgenproof1.
+Require Import Op Locations Machblock Conventions PseudoAsmblock PseudoAsmblockproof Asm Asmblock.
+Require Machblockgenproof Asmblockgenproof PostpassSchedulingproof.
+Require Import Asmgen.
+Require Import Axioms.
+Require Import IterList.
+Require Import Ring.
-Definition match_prog (p: Mach.program) (tp: Asm.program) :=
+Module Asmblock_PRESERVATION.
+
+Import Asmblock_TRANSF.
+
+Definition match_prog (p: Asmblock.program) (tp: Asm.program) :=
match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
Lemma transf_program_match:
@@ -29,20 +40,36 @@ Qed.
Section PRESERVATION.
-Variable prog: Mach.program.
+Variable prog: Asmblock.program.
Variable tprog: Asm.program.
Hypothesis TRANSF: match_prog prog tprog.
Let ge := Genv.globalenv prog.
Let tge := Genv.globalenv tprog.
+Definition lk :aarch64_linker := {| Asmblock.symbol_low:=Asm.symbol_low tge; Asmblock.symbol_high:=Asm.symbol_high tge|}.
+
Lemma symbols_preserved:
forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
Proof (Genv.find_symbol_match TRANSF).
+Lemma symbol_addresses_preserved:
+ forall (s: ident) (ofs: ptrofs),
+ Genv.symbol_address tge s ofs = Genv.symbol_address ge s ofs.
+Proof.
+ intros; unfold Genv.symbol_address; rewrite symbols_preserved; reflexivity.
+Qed.
+
Lemma senv_preserved:
Senv.equiv ge tge.
Proof (Genv.senv_match TRANSF).
+Lemma symbol_high_low: forall (id: ident) (ofs: ptrofs),
+ Val.addl (Asmblock.symbol_high lk id ofs) (Asmblock.symbol_low lk id ofs) = Genv.symbol_address ge id ofs.
+Proof.
+ unfold lk; simpl. intros; rewrite Asm.symbol_high_low; unfold Genv.symbol_address;
+ rewrite symbols_preserved; reflexivity.
+Qed.
+
Lemma functions_translated:
forall b f,
Genv.find_funct_ptr ge b = Some f ->
@@ -50,1052 +77,2320 @@ Lemma functions_translated:
Genv.find_funct_ptr tge b = Some tf /\ transf_fundef f = OK tf.
Proof (Genv.find_funct_ptr_transf_partial TRANSF).
-Lemma functions_transl:
- forall fb f tf,
+Lemma internal_functions_translated:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some (Internal tf) /\ transf_function f = OK tf.
+Proof.
+ intros; exploit functions_translated; eauto.
+ intros (x & FIND & TRANSf).
+ apply bind_inversion in TRANSf.
+ destruct TRANSf as (tf & TRANSf & X).
+ inv X.
+ eauto.
+Qed.
+
+Lemma internal_functions_unfold:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ exists tc,
+ Genv.find_funct_ptr tge b = Some (Internal (Asm.mkfunction (fn_sig f) tc))
+ /\ unfold (fn_blocks f) = OK tc
+ /\ list_length_z tc <= Ptrofs.max_unsigned.
+Proof.
+ intros.
+ exploit internal_functions_translated; eauto.
+ intros (tf & FINDtf & TRANStf).
+ unfold transf_function in TRANStf.
+ monadInv TRANStf.
+ destruct (zlt _ _); try congruence.
+ inv EQ. inv EQ0.
+ eexists; intuition eauto.
+ omega.
+Qed.
+
+
+Inductive is_nth_inst (bb: bblock) (n:Z) (i:Asm.instruction): Prop :=
+ | is_nth_label l:
+ list_nth_z (header bb) n = Some l ->
+ i = Asm.Plabel l ->
+ is_nth_inst bb n i
+ | is_nth_basic bi:
+ list_nth_z (body bb) (n - list_length_z (header bb)) = Some bi ->
+ basic_to_instruction bi = OK i ->
+ is_nth_inst bb n i
+ | is_nth_ctlflow cfi:
+ (exit bb) = Some cfi ->
+ n = size bb - 1 ->
+ i = control_to_instruction cfi ->
+ is_nth_inst bb n i.
+
+(* Asmblock and Asm share the same definition of state *)
+Definition match_states (s1 s2 : state) := s1 = s2.
+
+Inductive match_internal: forall n, state -> state -> Prop :=
+ | match_internal_intro n rs1 m1 rs2 m2
+ (MEM: m1 = m2)
+ (AG: forall r, r <> PC -> rs1 r = rs2 r)
+ (AGPC: Val.offset_ptr (rs1 PC) (Ptrofs.repr n) = rs2 PC)
+ : match_internal n (State rs1 m1) (State rs2 m2).
+
+Lemma match_internal_set_parallel:
+ forall n rs1 m1 rs2 m2 r val,
+ match_internal n (State rs1 m1) (State rs2 m2) ->
+ r <> PC ->
+ match_internal n (State (rs1#r <- val) m1) (State (rs2#r <- val ) m2).
+Proof.
+ intros n rs1 m1 rs2 m2 r v MI.
+ inversion MI; constructor; auto.
+ - intros r' NOTPC.
+ unfold Pregmap.set; rewrite AG. reflexivity. assumption.
+ - unfold Pregmap.set; destruct (PregEq.eq PC r); congruence.
+Qed.
+
+Lemma agree_match_states:
+ forall rs1 m1 rs2 m2,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ forall r : preg, rs1#r = rs2#r.
+Proof.
+ intros.
+ unfold match_states in *.
+ assert (rs1 = rs2) as EQ. { congruence. }
+ rewrite EQ. reflexivity.
+Qed.
+
+Lemma match_states_set_parallel:
+ forall rs1 m1 rs2 m2 r v,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ match_states (State (rs1#r <- v) m1) (State (rs2#r <- v) m2).
+Proof.
+ intros; unfold match_states in *.
+ assert (rs1 = rs2) as RSEQ. { congruence. }
+ assert (m1 = m2) as MEQ. { congruence. }
+ rewrite RSEQ in *; rewrite MEQ in *; unfold Pregmap.set; reflexivity.
+Qed.
+
+(* match_internal from match_states *)
+Lemma mi_from_ms:
+ forall rs1 m1 rs2 m2 b ofs,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ rs1#PC = Vptr b ofs ->
+ match_internal 0 (State rs1 m1) (State rs2 m2).
+Proof.
+ intros rs1 m1 rs2 m2 b ofs MS PCVAL.
+ inv MS; constructor; auto; unfold Val.offset_ptr;
+ rewrite PCVAL; rewrite Ptrofs.add_zero; reflexivity.
+Qed.
+
+Lemma transf_initial_states:
+ forall s1, Asmblock.initial_state prog s1 ->
+ exists s2, Asm.initial_state tprog s2 /\ match_states s1 s2.
+Proof.
+ intros ? INIT_s1.
+ inversion INIT_s1 as (m, ?, ge0, rs). unfold ge0 in *.
+ econstructor; split.
+ - econstructor.
+ eapply (Genv.init_mem_transf_partial TRANSF); eauto.
+ - rewrite (match_program_main TRANSF); rewrite symbol_addresses_preserved.
+ unfold rs; reflexivity.
+Qed.
+
+Lemma transf_final_states:
+ forall s1 s2 r,
+ match_states s1 s2 -> Asmblock.final_state s1 r -> Asm.final_state s2 r.
+Proof.
+ intros s1 s2 r MATCH FINAL_s1.
+ inv FINAL_s1; inv MATCH; constructor; assumption.
+Qed.
+
+Definition max_pos (f : Asm.function) := list_length_z f.(Asm.fn_code).
+
+Lemma functions_bound_max_pos: forall fb f tf,
Genv.find_funct_ptr ge fb = Some (Internal f) ->
transf_function f = OK tf ->
- Genv.find_funct_ptr tge fb = Some (Internal tf).
+ max_pos tf <= Ptrofs.max_unsigned.
+Proof.
+ intros fb f tf FINDf TRANSf.
+ unfold transf_function in TRANSf.
+ apply bind_inversion in TRANSf.
+ destruct TRANSf as (c & TRANSf).
+ destruct TRANSf as (_ & TRANSf).
+ destruct (zlt _ _).
+ - inversion TRANSf.
+ - unfold max_pos.
+ assert (Asm.fn_code tf = c) as H. { inversion TRANSf as (H'); auto. }
+ rewrite H; omega.
+Qed.
+
+Lemma one_le_max_unsigned:
+ 1 <= Ptrofs.max_unsigned.
+Proof.
+ unfold Ptrofs.max_unsigned; simpl; unfold Ptrofs.wordsize;
+ unfold Wordsize_Ptrofs.wordsize; destruct Archi.ptr64; simpl; omega.
+Qed.
+
+(* NB: does not seem useful anymore, with the [exec_header_simulation] proof below
+Lemma match_internal_exec_label:
+ forall n rs1 m1 rs2 m2 l fb f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ match_internal n (State rs1 m1) (State rs2 m2) ->
+ n >= 0 ->
+ (* There is no step if n is already max_pos *)
+ n < (max_pos tf) ->
+ exists rs2' m2', Asm.exec_instr tge tf (Asm.Plabel l) rs2 m2 = Next rs2' m2'
+ /\ match_internal (n+1) (State rs1 m1) (State rs2' m2').
+Proof.
+ intros. (* XXX auto generated names *)
+ unfold Asm.exec_instr.
+ eexists; eexists; split; eauto.
+ inversion H1; constructor; auto.
+ - intros; unfold Asm.nextinstr; unfold Pregmap.set;
+ destruct (PregEq.eq r PC); auto; contradiction.
+ - unfold Asm.nextinstr; rewrite Pregmap.gss; unfold Ptrofs.one.
+ rewrite <- AGPC; rewrite Val.offset_ptr_assoc; unfold Ptrofs.add;
+ rewrite Ptrofs.unsigned_repr. rewrite Ptrofs.unsigned_repr; trivial.
+ + split.
+ * apply Z.le_0_1.
+ * apply one_le_max_unsigned.
+ + split.
+ * apply Z.ge_le; assumption.
+ * rewrite <- functions_bound_max_pos; eauto; omega.
+Qed.
+*)
+
+Lemma incrPC_agree_but_pc:
+ forall rs r ofs,
+ r <> PC ->
+ (incrPC ofs rs)#r = rs#r.
+Proof.
+ intros rs r ofs NOTPC.
+ unfold incrPC; unfold Pregmap.set; destruct (PregEq.eq r PC).
+ - contradiction.
+ - reflexivity.
+Qed.
+
+Lemma bblock_non_empty bb: body bb <> nil \/ exit bb <> None.
+Proof.
+ destruct bb. simpl.
+ unfold non_empty_bblockb in correct.
+ unfold non_empty_body, non_empty_exit, Is_true in correct.
+ destruct body, exit.
+ - right. discriminate.
+ - contradiction.
+ - right. discriminate.
+ - left. discriminate.
+Qed.
+
+Lemma list_length_z_aux_increase A (l: list A): forall acc,
+ list_length_z_aux l acc >= acc.
+Proof.
+ induction l; simpl; intros.
+ - omega.
+ - generalize (IHl (Z.succ acc)). omega.
+Qed.
+
+Lemma bblock_size_aux_pos bb: list_length_z (body bb) + Z.of_nat (length_opt (exit bb)) >= 1.
+Proof.
+ destruct (bblock_non_empty bb), (body bb) as [|hd tl], (exit bb); simpl;
+ try (congruence || omega);
+ unfold list_length_z; simpl;
+ generalize (list_length_z_aux_increase _ tl 1); omega.
+Qed.
+
+
+Lemma list_length_add_acc A (l : list A) acc:
+ list_length_z_aux l acc = (list_length_z l) + acc.
+Proof.
+ unfold list_length_z, list_length_z_aux. simpl.
+ fold list_length_z_aux.
+ rewrite (list_length_z_aux_shift l acc 0).
+ omega.
+Qed.
+
+Lemma list_length_z_cons A hd (tl : list A):
+ list_length_z (hd :: tl) = list_length_z tl + 1.
+Proof.
+ unfold list_length_z; simpl; rewrite list_length_add_acc; reflexivity.
+Qed.
+
+(*Lemma length_agree A (l : list A):*)
+ (*list_length_z l = Z.of_nat (length l).*)
+(*Proof.*)
+ (*induction l as [| ? l IH]; intros.*)
+ (*- unfold list_length_z; reflexivity.*)
+ (*- simpl; rewrite list_length_z_cons, Zpos_P_of_succ_nat; omega.*)
+(*Qed.*)
+
+Lemma bblock_size_aux bb: size bb = list_length_z (header bb) + list_length_z (body bb) + Z.of_nat (length_opt (exit bb)).
+Proof.
+ unfold size.
+ repeat (rewrite list_length_z_nat). repeat (rewrite Nat2Z.inj_add). reflexivity.
+Qed.
+
+Lemma header_size_lt_block_size bb:
+ list_length_z (header bb) < size bb.
+Proof.
+ rewrite bblock_size_aux.
+ generalize (bblock_non_empty bb); intros NEMPTY; destruct NEMPTY as [HDR|EXIT].
+ - destruct (body bb); try contradiction; rewrite list_length_z_cons;
+ repeat rewrite list_length_z_nat; omega.
+ - destruct (exit bb); try contradiction; simpl; repeat rewrite list_length_z_nat; omega.
+Qed.
+
+Lemma body_size_le_block_size bb:
+ list_length_z (body bb) <= size bb.
Proof.
- intros. exploit functions_translated; eauto. intros [tf' [A B]].
- monadInv B. rewrite H0 in EQ; inv EQ; auto.
+ rewrite bblock_size_aux; repeat rewrite list_length_z_nat; omega.
Qed.
-(** * Properties of control flow *)
-Lemma transf_function_no_overflow:
- forall f tf,
- transf_function f = OK tf -> list_length_z tf.(fn_code) <= Ptrofs.max_unsigned.
+Lemma bblock_size_pos bb: size bb >= 1.
Proof.
- intros. monadInv H. destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0.
+ rewrite (bblock_size_aux bb).
+ generalize (bblock_size_aux_pos bb).
+ generalize (list_length_z_pos (header bb)).
omega.
Qed.
-Lemma exec_straight_exec:
- forall fb f c ep tf tc c' rs m rs' m',
- transl_code_at_pc ge (rs PC) fb f c ep tf tc ->
- exec_straight tge tf tc rs m c' rs' m' ->
- plus step tge (State rs m) E0 (State rs' m').
-Proof.
- intros. inv H.
- eapply exec_straight_steps_1; eauto.
- eapply transf_function_no_overflow; eauto.
- eapply functions_transl; eauto.
-Qed.
-
-Lemma exec_straight_at:
- forall fb f c ep tf tc c' ep' tc' rs m rs' m',
- transl_code_at_pc ge (rs PC) fb f c ep tf tc ->
- transl_code f c' ep' = OK tc' ->
- exec_straight tge tf tc rs m tc' rs' m' ->
- transl_code_at_pc ge (rs' PC) fb f c' ep' tf tc'.
-Proof.
- intros. inv H.
- exploit exec_straight_steps_2; eauto.
- eapply transf_function_no_overflow; eauto.
- eapply functions_transl; eauto.
- intros [ofs' [PC' CT']].
- rewrite PC'. constructor; auto.
-Qed.
-
-(** The following lemmas show that the translation from Mach to Asm
- preserves labels, in the sense that the following diagram commutes:
-<<
- translation
- Mach code ------------------------ Asm instr sequence
- | |
- | Mach.find_label lbl find_label lbl |
- | |
- v v
- Mach code tail ------------------- Asm instr seq tail
- translation
->>
- The proof demands many boring lemmas showing that Asm constructor
- functions do not introduce new labels.
-*)
+Lemma unfold_car_cdr bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tbb tc', unfold_bblock bb = OK tbb
+ /\ unfold bbs = OK tc'
+ /\ unfold (bb :: bbs) = OK (tbb ++ tc').
+Proof.
+ intros UNFOLD.
+ assert (UF := UNFOLD).
+ unfold unfold in UNFOLD.
+ apply bind_inversion in UNFOLD. destruct UNFOLD as (? & UBB). destruct UBB as (UBB & REST).
+ apply bind_inversion in REST. destruct REST as (? & UNFOLD').
+ fold unfold in UNFOLD'. destruct UNFOLD' as (UNFOLD' & UNFOLD).
+ rewrite <- UNFOLD in UF.
+ eauto.
+Qed.
-Section TRANSL_LABEL.
+Lemma unfold_cdr bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tc', unfold bbs = OK tc'.
+Proof.
+ intros; exploit unfold_car_cdr; eauto. intros (_ & ? & _ & ? & _).
+ eexists; eauto.
+Qed.
-Remark loadimm_z_label: forall sz rd l k, tail_nolabel k (loadimm_z sz rd l k).
-Proof.
- intros; destruct l as [ | [n1 p1] l]; simpl; TailNoLabel.
- induction l as [ | [n p] l]; simpl; TailNoLabel.
+Lemma unfold_car bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tbb, unfold_bblock bb = OK tbb.
+Proof.
+ intros; exploit unfold_car_cdr; eauto. intros (? & _ & ? & _ & _).
+ eexists; eauto.
Qed.
-Remark loadimm_n_label: forall sz rd l k, tail_nolabel k (loadimm_n sz rd l k).
-Proof.
- intros; destruct l as [ | [n1 p1] l]; simpl; TailNoLabel.
- induction l as [ | [n p] l]; simpl; TailNoLabel.
+Lemma all_blocks_translated:
+ forall bbs tc,
+ unfold bbs = OK tc ->
+ forall bb, In bb bbs ->
+ exists c, unfold_bblock bb = OK c.
+Proof.
+ induction bbs as [| bb bbs IHbbs].
+ - contradiction.
+ - intros ? UNFOLD ? IN.
+ (* unfold proceeds by unfolding the basic block at the head of the list and
+ * then recurring *)
+ exploit unfold_car_cdr; eauto. intros (? & ? & ? & ? & _).
+ (* basic block is either in head or tail *)
+ inversion IN as [EQ | NEQ].
+ + rewrite <- EQ; eexists; eauto.
+ + eapply IHbbs; eauto.
Qed.
-Remark loadimm_label: forall sz rd n k, tail_nolabel k (loadimm sz rd n k).
+Lemma entire_body_translated:
+ forall lbi tc,
+ unfold_body lbi = OK tc ->
+ forall bi, In bi lbi ->
+ exists bi', basic_to_instruction bi = OK bi'.
Proof.
- unfold loadimm; intros. destruct Nat.leb; [apply loadimm_z_label|apply loadimm_n_label].
+ induction lbi as [| a lbi IHlbi].
+ - intros. contradiction.
+ - intros tc UNFOLD_BODY bi IN.
+ unfold unfold_body in UNFOLD_BODY. apply bind_inversion in UNFOLD_BODY.
+ destruct UNFOLD_BODY as (? & TRANSbi & REST).
+ apply bind_inversion in REST. destruct REST as (? & UNFOLD_BODY' & ?).
+ fold unfold_body in UNFOLD_BODY'.
+
+ inversion IN as [EQ | NEQ].
+ + rewrite <- EQ; eauto.
+ + eapply IHlbi; eauto.
Qed.
-Hint Resolve loadimm_label: labels.
-Remark loadimm32_label: forall r n k, tail_nolabel k (loadimm32 r n k).
+Lemma bblock_in_bblocks bbs bb: forall
+ tc pos
+ (UNFOLD: unfold bbs = OK tc)
+ (FINDBB: find_bblock pos bbs = Some bb),
+ In bb bbs.
Proof.
- unfold loadimm32; intros. destruct (is_logical_imm32 n); TailNoLabel.
+ induction bbs as [| b bbs IH].
+ - intros. inversion FINDBB.
+ - destruct pos.
+ + intros. inversion FINDBB as (EQ). rewrite <- EQ. apply in_eq.
+ + intros.
+ exploit unfold_cdr; eauto. intros (tc' & UNFOLD').
+ unfold find_bblock in FINDBB. simpl in FINDBB.
+ fold find_bblock in FINDBB.
+ apply in_cons. eapply IH; eauto.
+ + intros. inversion FINDBB.
Qed.
-Hint Resolve loadimm32_label: labels.
-Remark loadimm64_label: forall r n k, tail_nolabel k (loadimm64 r n k).
+Lemma blocks_translated tc pos bbs bb: forall
+ (UNFOLD: unfold bbs = OK tc)
+ (FINDBB: find_bblock pos bbs = Some bb),
+ exists tbb, unfold_bblock bb = OK tbb.
Proof.
- unfold loadimm64; intros. destruct (is_logical_imm64 n); TailNoLabel.
+ intros; exploit bblock_in_bblocks; eauto; intros;
+ eapply all_blocks_translated; eauto.
Qed.
-Hint Resolve loadimm64_label: labels.
-Remark addimm_aux: forall insn rd r1 n k,
- (forall rd r1 n, nolabel (insn rd r1 n)) ->
- tail_nolabel k (addimm_aux insn rd r1 n k).
+(*Lemma size_header b pos f bb: forall*)
+ (*(FINDF: Genv.find_funct_ptr ge b = Some (Internal f))*)
+ (*(FINDBB: find_bblock pos (fn_blocks f) = Some bb),*)
+ (*list_length_z (header bb) <= 1.*)
+(*Proof.*)
+ (*intros.*)
+ (*exploit internal_functions_unfold; eauto.*)
+ (*intros (tc & FINDtf & TRANStf & ?).*)
+ (*exploit blocks_translated; eauto. intros TBB.*)
+
+ (*unfold unfold_bblock in TBB.*)
+ (*destruct (zle (list_length_z (header bb)) 1).*)
+ (*- assumption.*)
+ (*[>- destruct TBB as (? & TBB). discriminate TBB.<]*)
+(*[>Qed.<]*)
+(*Admitted.*)
+
+Lemma list_nth_z_neg A (l: list A): forall n,
+ n < 0 -> list_nth_z l n = None.
Proof.
- unfold addimm_aux; intros.
- destruct Z.eqb. TailNoLabel. destruct Z.eqb; TailNoLabel.
+ induction l; simpl; auto.
+ intros n H; destruct (zeq _ _); (try eapply IHl); omega.
Qed.
-Remark addimm32_label: forall rd r1 n k, tail_nolabel k (addimm32 rd r1 n k).
+Lemma find_bblock_neg bbs: forall pos,
+ pos < 0 -> find_bblock pos bbs = None.
Proof.
- unfold addimm32; intros.
- destruct Int.eq. apply addimm_aux; intros; red; auto.
- destruct Int.eq. apply addimm_aux; intros; red; auto.
- destruct Int.lt; eapply tail_nolabel_trans; TailNoLabel.
+ induction bbs; simpl; auto.
+ intros. destruct (zlt pos 0). { reflexivity. }
+ destruct (zeq pos 0); contradiction.
Qed.
-Hint Resolve addimm32_label: labels.
-Remark addimm64_label: forall rd r1 n k, tail_nolabel k (addimm64 rd r1 n k).
+Lemma equal_header_size bb:
+ length (header bb) = length (unfold_label (header bb)).
Proof.
- unfold addimm64; intros.
- destruct Int64.eq. apply addimm_aux; intros; red; auto.
- destruct Int64.eq. apply addimm_aux; intros; red; auto.
- destruct Int64.lt; eapply tail_nolabel_trans; TailNoLabel.
+ induction (header bb); auto.
+ simpl. rewrite IHl. auto.
Qed.
-Hint Resolve addimm64_label: labels.
-Remark logicalimm32_label: forall insn1 insn2 rd r1 n k,
- (forall rd r1 n, nolabel (insn1 rd r1 n)) ->
- (forall rd r1 r2 s, nolabel (insn2 rd r1 r2 s)) ->
- tail_nolabel k (logicalimm32 insn1 insn2 rd r1 n k).
+Lemma equal_body_size:
+ forall bb tb,
+ unfold_body (body bb) = OK tb ->
+ length (body bb) = length tb.
Proof.
- unfold logicalimm32; intros.
- destruct (is_logical_imm32 n). TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+ intros bb. induction (body bb).
+ - simpl. intros ? H. inversion H. auto.
+ - intros tb H. simpl in H. apply bind_inversion in H. destruct H as (? & BI & TAIL).
+ apply bind_inversion in TAIL. destruct TAIL as (tb' & BODY' & CONS). inv CONS.
+ simpl. specialize (IHl tb' BODY'). rewrite IHl. reflexivity.
Qed.
-Remark logicalimm64_label: forall insn1 insn2 rd r1 n k,
- (forall rd r1 n, nolabel (insn1 rd r1 n)) ->
- (forall rd r1 r2 s, nolabel (insn2 rd r1 r2 s)) ->
- tail_nolabel k (logicalimm64 insn1 insn2 rd r1 n k).
+Lemma equal_exit_size bb:
+ length_opt (exit bb) = length (unfold_exit (exit bb)).
Proof.
- unfold logicalimm64; intros.
- destruct (is_logical_imm64 n). TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+ destruct (exit bb); trivial.
Qed.
-Remark move_extended_label: forall rd r1 ex a k, tail_nolabel k (move_extended rd r1 ex a k).
+Lemma bblock_size_preserved bb tb:
+ unfold_bblock bb = OK tb ->
+ size bb = list_length_z tb.
Proof.
- unfold move_extended, move_extended_base; intros. destruct Int.eq, ex; TailNoLabel.
+ unfold unfold_bblock. intros UNFOLD_BBLOCK.
+ (*destruct (zle (list_length_z (header bb)) 1). 2: { inversion UNFOLD_BBLOCK. }*)
+ apply bind_inversion in UNFOLD_BBLOCK. destruct UNFOLD_BBLOCK as (? & UNFOLD_BODY & CONS).
+ inversion CONS.
+ unfold size.
+ rewrite equal_header_size, equal_exit_size.
+ erewrite equal_body_size; eauto.
+ rewrite list_length_z_nat.
+ repeat (rewrite app_length).
+ rewrite plus_assoc. auto.
Qed.
-Hint Resolve move_extended_label: labels.
-Remark arith_extended_label: forall insnX insnS rd r1 r2 ex a k,
- (forall rd r1 r2 x, nolabel (insnX rd r1 r2 x)) ->
- (forall rd r1 r2 s, nolabel (insnS rd r1 r2 s)) ->
- tail_nolabel k (arith_extended insnX insnS rd r1 r2 ex a k).
+Lemma size_of_blocks_max_pos_aux:
+ forall bbs tbbs pos bb,
+ find_bblock pos bbs = Some bb ->
+ unfold bbs = OK tbbs ->
+ pos + size bb <= list_length_z tbbs.
Proof.
- unfold arith_extended; intros. destruct Int.ltu.
- TailNoLabel.
- destruct ex; simpl; TailNoLabel.
+ induction bbs as [| bb ? IHbbs].
+ - intros tbbs ? ? FINDBB; inversion FINDBB.
+ - simpl; intros tbbs pos bb' FINDBB UNFOLD.
+ apply bind_inversion in UNFOLD; destruct UNFOLD as (tbb & UNFOLD_BBLOCK & H).
+ apply bind_inversion in H; destruct H as (tbbs' & UNFOLD & CONS).
+ inv CONS.
+ destruct (zlt pos 0). { discriminate FINDBB. }
+ destruct (zeq pos 0).
+ + inv FINDBB.
+ exploit bblock_size_preserved; eauto; intros SIZE; rewrite SIZE.
+ repeat (rewrite list_length_z_nat). rewrite app_length, Nat2Z.inj_add.
+ omega.
+ + generalize (IHbbs tbbs' (pos - size bb) bb' FINDBB UNFOLD). intros IH.
+ exploit bblock_size_preserved; eauto; intros SIZE.
+ repeat (rewrite list_length_z_nat); rewrite app_length.
+ rewrite Nat2Z.inj_add; repeat (rewrite <- list_length_z_nat).
+ omega.
Qed.
-Remark loadsymbol_label: forall r id ofs k, tail_nolabel k (loadsymbol r id ofs k).
+Lemma size_of_blocks_max_pos pos f tf bi:
+ find_bblock pos (fn_blocks f) = Some bi ->
+ transf_function f = OK tf ->
+ pos + size bi <= max_pos tf.
Proof.
- intros; unfold loadsymbol.
- destruct (Archi.pic_code tt); TailNoLabel. destruct Ptrofs.eq; TailNoLabel.
-Qed.
-Hint Resolve loadsymbol_label: labels.
+ unfold transf_function, max_pos.
+ intros FINDBB UNFOLD.
+ apply bind_inversion in UNFOLD. destruct UNFOLD as (? & UNFOLD & H).
+ destruct (zlt Ptrofs.max_unsigned (list_length_z x)). { discriminate H. }
+ inv H. simpl.
+ eapply size_of_blocks_max_pos_aux; eauto.
+Qed.
-Remark transl_cond_label: forall cond args k c,
- transl_cond cond args k = OK c -> tail_nolabel k c.
+Lemma unfold_bblock_not_nil bb:
+ unfold_bblock bb = OK nil -> False.
Proof.
- unfold transl_cond; intros; destruct cond; TailNoLabel.
-- destruct is_arith_imm32; TailNoLabel. destruct is_arith_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_arith_imm32; TailNoLabel. destruct is_arith_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_logical_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_logical_imm32; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_arith_imm64; TailNoLabel. destruct is_arith_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_arith_imm64; TailNoLabel. destruct is_arith_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_logical_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
-- destruct is_logical_imm64; TailNoLabel. eapply tail_nolabel_trans; TailNoLabel.
+ intros.
+ exploit bblock_size_preserved; eauto. unfold list_length_z; simpl. intros SIZE.
+ generalize (bblock_size_pos bb). intros SIZE'. omega.
Qed.
-Remark transl_cond_branch_default_label: forall cond args lbl k c,
- transl_cond_branch_default cond args lbl k = OK c -> tail_nolabel k c.
+(* same proof as list_nth_z_range (Coqlib) *)
+Lemma find_instr_range:
+ forall c n i,
+ Asm.find_instr n c = Some i -> 0 <= n < list_length_z c.
Proof.
- unfold transl_cond_branch_default; intros.
- eapply tail_nolabel_trans; [eapply transl_cond_label;eauto|TailNoLabel].
+ induction c; simpl; intros.
+ discriminate.
+ rewrite list_length_z_cons. destruct (zeq n 0).
+ generalize (list_length_z_pos c); omega.
+ exploit IHc; eauto. omega.
Qed.
-Hint Resolve transl_cond_branch_default_label: labels.
-Remark transl_cond_branch_label: forall cond args lbl k c,
- transl_cond_branch cond args lbl k = OK c -> tail_nolabel k c.
+Lemma find_instr_tail:
+ forall tbb pos c i,
+ Asm.find_instr pos c = Some i ->
+ Asm.find_instr (pos + list_length_z tbb) (tbb ++ c) = Some i.
Proof.
- unfold transl_cond_branch; intros; destruct args; TailNoLabel; destruct cond; TailNoLabel.
-- destruct c0; TailNoLabel.
-- destruct c0; TailNoLabel.
-- destruct (Int.is_power2 n); TailNoLabel.
-- destruct (Int.is_power2 n); TailNoLabel.
-- destruct c0; TailNoLabel.
-- destruct c0; TailNoLabel.
-- destruct (Int64.is_power2' n); TailNoLabel.
-- destruct (Int64.is_power2' n); TailNoLabel.
+ induction tbb as [| ? ? IHtbb].
+ - intros. unfold list_length_z; simpl. rewrite Z.add_0_r. assumption.
+ - intros. rewrite list_length_z_cons. simpl.
+ destruct (zeq (pos + (list_length_z tbb + 1)) 0).
+ + exploit find_instr_range; eauto. intros POS_RANGE.
+ generalize (list_length_z_pos tbb). omega.
+ + replace (pos + (list_length_z tbb + 1) - 1) with (pos + list_length_z tbb) by omega.
+ eapply IHtbb; eauto.
Qed.
-Remark transl_op_label:
- forall op args r k c,
- transl_op op args r k = OK c -> tail_nolabel k c.
+Lemma size_of_blocks_bounds fb pos f bi:
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ find_bblock pos (fn_blocks f) = Some bi ->
+ pos + size bi <= Ptrofs.max_unsigned.
Proof.
- unfold transl_op; intros; destruct op; TailNoLabel.
-- destruct (preg_of r); try discriminate; destruct (preg_of m); inv H; TailNoLabel.
-- destruct (Float.eq_dec n Float.zero); TailNoLabel.
-- destruct (Float32.eq_dec n Float32.zero); TailNoLabel.
-- apply logicalimm32_label; unfold nolabel; auto.
-- apply logicalimm32_label; unfold nolabel; auto.
-- apply logicalimm32_label; unfold nolabel; auto.
-- unfold shrx32. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
-- apply arith_extended_label; unfold nolabel; auto.
-- apply arith_extended_label; unfold nolabel; auto.
-- apply logicalimm64_label; unfold nolabel; auto.
-- apply logicalimm64_label; unfold nolabel; auto.
-- apply logicalimm64_label; unfold nolabel; auto.
-- unfold shrx64. destruct (Int.eq _ _); try destruct (Int.eq _ _); TailNoLabel.
-- eapply tail_nolabel_trans. eapply transl_cond_label; eauto. TailNoLabel.
-- destruct (preg_of r); try discriminate; TailNoLabel;
- (eapply tail_nolabel_trans; [eapply transl_cond_label; eauto | TailNoLabel]).
+ intros; exploit internal_functions_translated; eauto.
+ intros (tf & _ & TRANSf).
+ assert (pos + size bi <= max_pos tf). { eapply size_of_blocks_max_pos; eauto. }
+ assert (max_pos tf <= Ptrofs.max_unsigned). { eapply functions_bound_max_pos; eauto. }
+ omega.
Qed.
-Remark transl_addressing_label:
- forall sz addr args insn k c,
- transl_addressing sz addr args insn k = OK c ->
- (forall ad, nolabel (insn ad)) ->
- tail_nolabel k c.
+Lemma find_instr_bblock_tail:
+ forall tbb bb pos c i,
+ Asm.find_instr pos c = Some i ->
+ unfold_bblock bb = OK tbb ->
+ Asm.find_instr (pos + size bb ) (tbb ++ c) = Some i.
Proof.
- unfold transl_addressing; intros; destruct addr; TailNoLabel;
- eapply tail_nolabel_trans; TailNoLabel.
- eapply tail_nolabel_trans. apply arith_extended_label; unfold nolabel; auto. TailNoLabel.
+ induction tbb.
+ - intros. exploit unfold_bblock_not_nil; eauto. intros. contradiction.
+ - intros. simpl.
+ destruct (zeq (pos + size bb) 0).
+ + (* absurd *)
+ exploit find_instr_range; eauto. intros POS_RANGE.
+ generalize (bblock_size_pos bb). intros SIZE. omega.
+ + erewrite bblock_size_preserved; eauto.
+ rewrite list_length_z_cons.
+ replace (pos + (list_length_z tbb + 1) - 1) with (pos + list_length_z tbb) by omega.
+ apply find_instr_tail; auto.
Qed.
-Remark transl_load_label:
- forall trap chunk addr args dst k c,
- transl_load trap chunk addr args dst k = OK c -> tail_nolabel k c.
+Lemma list_nth_z_find_label:
+ forall (ll : list label) il n l,
+ list_nth_z ll n = Some l ->
+ Asm.find_instr n ((unfold_label ll) ++ il) = Some (Asm.Plabel l).
Proof.
- unfold transl_load; intros; destruct trap; try discriminate; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
+ induction ll.
+ - intros. inversion H.
+ - intros. simpl.
+ destruct (zeq n 0) as [Z | NZ].
+ + inversion H as (H'). rewrite Z in H'. simpl in H'. inv H'. reflexivity.
+ + simpl in H. destruct (zeq n 0). { contradiction. }
+ apply IHll; auto.
Qed.
-Remark transl_store_label:
- forall chunk addr args src k c,
- transl_store chunk addr args src k = OK c -> tail_nolabel k c.
+Lemma list_nth_z_find_bi:
+ forall lbi bi tlbi n bi' exit,
+ list_nth_z lbi n = Some bi ->
+ unfold_body lbi = OK tlbi ->
+ basic_to_instruction bi = OK bi' ->
+ Asm.find_instr n (tlbi ++ exit) = Some bi'.
Proof.
- unfold transl_store; intros; destruct chunk; TailNoLabel; eapply transl_addressing_label; eauto; unfold nolabel; auto.
+ induction lbi.
+ - intros. inversion H.
+ - simpl. intros.
+ apply bind_inversion in H0. destruct H0 as (? & ? & ?).
+ apply bind_inversion in H2. destruct H2 as (? & ? & ?).
+ destruct (zeq n 0) as [Z | NZ].
+ + destruct n.
+ * inversion H as (BI). rewrite BI in *.
+ inversion H3. simpl. congruence.
+ * (* absurd *) congruence.
+ * (* absurd *) congruence.
+ + inv H3. simpl. destruct (zeq n 0). { contradiction. }
+ eapply IHlbi; eauto.
Qed.
-Remark indexed_memory_access_label:
- forall insn sz base ofs k,
- (forall ad, nolabel (insn ad)) ->
- tail_nolabel k (indexed_memory_access insn sz base ofs k).
+Lemma list_nth_z_find_bi_with_header:
+ forall ll lbi bi tlbi n bi' (rest : list Asm.instruction),
+ list_nth_z lbi (n - list_length_z ll) = Some bi ->
+ unfold_body lbi = OK tlbi ->
+ basic_to_instruction bi = OK bi' ->
+ Asm.find_instr n ((unfold_label ll) ++ (tlbi) ++ (rest)) = Some bi'.
Proof.
- unfold indexed_memory_access; intros. destruct offset_representable.
- TailNoLabel.
- eapply tail_nolabel_trans; TailNoLabel.
+ induction ll.
+ - unfold list_length_z. simpl. intros.
+ replace (n - 0) with n in H by omega. eapply list_nth_z_find_bi; eauto.
+ - intros. simpl. destruct (zeq n 0).
+ + rewrite list_length_z_cons in H. rewrite e in H.
+ replace (0 - (list_length_z ll + 1)) with (-1 - (list_length_z ll)) in H by omega.
+ generalize (list_length_z_pos ll). intros.
+ rewrite list_nth_z_neg in H; try omega. inversion H.
+ + rewrite list_length_z_cons in H.
+ replace (n - (list_length_z ll + 1)) with (n -1 - (list_length_z ll)) in H by omega.
+ eapply IHll; eauto.
Qed.
-Remark loadind_label:
- forall base ofs ty dst k c,
- loadind base ofs ty dst k = OK c -> tail_nolabel k c.
+(* XXX unused *)
+Lemma range_list_nth_z:
+ forall (A: Type) (l: list A) n,
+ 0 <= n < list_length_z l ->
+ exists x, list_nth_z l n = Some x.
Proof.
- unfold loadind; intros.
- destruct ty, (preg_of dst); inv H; apply indexed_memory_access_label; intros; exact I.
+ induction l.
+ - intros. unfold list_length_z in H. simpl in H. omega.
+ - intros n. destruct (zeq n 0).
+ + intros. simpl. destruct (zeq n 0). { eauto. } contradiction.
+ + intros H. rewrite list_length_z_cons in H.
+ simpl. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) by omega.
+ eapply IHl; omega.
Qed.
-Remark storeind_label:
- forall src base ofs ty k c,
- storeind src base ofs ty k = OK c -> tail_nolabel k c.
+Lemma list_nth_z_n_too_big:
+ forall (A: Type) (l: list A) n,
+ 0 <= n ->
+ list_nth_z l n = None ->
+ n >= list_length_z l.
Proof.
- unfold storeind; intros.
- destruct ty, (preg_of src); inv H; apply indexed_memory_access_label; intros; exact I.
+ induction l.
+ - intros. unfold list_length_z. simpl. omega.
+ - intros. rewrite list_length_z_cons.
+ simpl in H0.
+ destruct (zeq n 0) as [N | N].
+ + inversion H0.
+ + (* XXX there must be a more elegant way to prove this simple fact *)
+ assert (n > 0). { omega. }
+ assert (0 <= n - 1). { omega. }
+ generalize (IHl (n - 1)). intros IH.
+ assert (n - 1 >= list_length_z l). { auto. }
+ assert (n > list_length_z l); omega.
Qed.
-Remark loadptr_label:
- forall base ofs dst k, tail_nolabel k (loadptr base ofs dst k).
+Lemma find_instr_past_header:
+ forall labels n rest,
+ list_nth_z labels n = None ->
+ Asm.find_instr n (unfold_label labels ++ rest) =
+ Asm.find_instr (n - list_length_z labels) rest.
Proof.
- intros. apply indexed_memory_access_label. unfold nolabel; auto.
+ induction labels as [| label labels' IH].
+ - unfold list_length_z; simpl; intros; rewrite Z.sub_0_r; reflexivity.
+ - intros. simpl. destruct (zeq n 0) as [N | N].
+ + rewrite N in H. inversion H.
+ + rewrite list_length_z_cons.
+ replace (n - (list_length_z labels' + 1)) with (n - 1 - list_length_z labels') by omega.
+ simpl in H. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) in H by omega.
+ apply IH; auto.
Qed.
-Remark storeptr_label:
- forall src base ofs k, tail_nolabel k (storeptr src base ofs k).
+(* very similar to find_instr_past_header *)
+Lemma find_instr_past_body:
+ forall lbi n tlbi rest,
+ list_nth_z lbi n = None ->
+ unfold_body lbi = OK tlbi ->
+ Asm.find_instr n (tlbi ++ rest) =
+ Asm.find_instr (n - list_length_z lbi) rest.
Proof.
- intros. apply indexed_memory_access_label. unfold nolabel; auto.
+ induction lbi.
+ - unfold list_length_z; simpl; intros ? ? ? ? H. inv H; rewrite Z.sub_0_r; reflexivity.
+ - intros n tlib ? NTH UNFOLD_BODY.
+ unfold unfold_body in UNFOLD_BODY. apply bind_inversion in UNFOLD_BODY.
+ destruct UNFOLD_BODY as (? & BI & H).
+ apply bind_inversion in H. destruct H as (? & UNFOLD_BODY' & CONS).
+ fold unfold_body in UNFOLD_BODY'. inv CONS.
+ simpl; destruct (zeq n 0) as [N|N].
+ + rewrite N in NTH; inversion NTH.
+ + rewrite list_length_z_cons.
+ replace (n - (list_length_z lbi + 1)) with (n - 1 - list_length_z lbi) by omega.
+ simpl in NTH. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) in NTH by omega.
+ apply IHlbi; auto.
Qed.
-Remark make_epilogue_label:
- forall f k, tail_nolabel k (make_epilogue f k).
+Lemma n_beyond_body:
+ forall bb n,
+ 0 <= n < size bb ->
+ list_nth_z (header bb) n = None ->
+ list_nth_z (body bb) (n - list_length_z (header bb)) = None ->
+ n >= Z.of_nat (length (header bb) + length (body bb)).
Proof.
- unfold make_epilogue; intros.
- (* FIXME destruct is_leaf_function.
- { TailNoLabel. } *)
- eapply tail_nolabel_trans.
- apply loadptr_label.
- TailNoLabel.
+ intros.
+ assert (0 <= n). { omega. }
+ generalize (list_nth_z_n_too_big label (header bb) n H2 H0). intros.
+ generalize (list_nth_z_n_too_big _ (body bb) (n - list_length_z (header bb))). intros.
+ unfold size in H.
+
+ assert (0 <= n - list_length_z (header bb)). { omega. }
+ assert (n - list_length_z (header bb) >= list_length_z (body bb)). { apply H4; auto. }
+
+ assert (n >= list_length_z (header bb) + list_length_z (body bb)). { omega. }
+ rewrite Nat2Z.inj_add.
+ repeat (rewrite <- list_length_z_nat). assumption.
Qed.
-Lemma transl_instr_label:
- forall f i ep k c,
- transl_instr f i ep k = OK c ->
- match i with Mlabel lbl => c = Plabel lbl :: k | _ => tail_nolabel k c end.
+Lemma exec_arith_instr_dont_move_PC ai rs rs': forall
+ (BASIC: exec_arith_instr lk ai rs = rs'),
+ rs PC = rs' PC.
Proof.
- unfold transl_instr; intros; destruct i; TailNoLabel.
-- eapply loadind_label; eauto.
-- eapply storeind_label; eauto.
-- destruct ep. eapply loadind_label; eauto.
- eapply tail_nolabel_trans. apply loadptr_label. eapply loadind_label; eauto.
-- eapply transl_op_label; eauto.
-- eapply transl_load_label; eauto.
-- eapply transl_store_label; eauto.
-- destruct s0; monadInv H; TailNoLabel.
-- destruct s0; monadInv H; (eapply tail_nolabel_trans; [eapply make_epilogue_label|TailNoLabel]).
-- eapply transl_cond_branch_label; eauto.
-- eapply tail_nolabel_trans; [eapply make_epilogue_label|TailNoLabel].
+ destruct ai; simpl; intros;
+ try (rewrite <- BASIC; rewrite Pregmap.gso; auto; discriminate).
+ - destruct i; simpl in BASIC.
+ + unfold compare_long in BASIC; rewrite <- BASIC.
+ repeat rewrite Pregmap.gso; try discriminate. reflexivity.
+ + unfold compare_long in BASIC; rewrite <- BASIC.
+ repeat rewrite Pregmap.gso; try discriminate. reflexivity.
+ + destruct sz;
+ try (unfold compare_single in BASIC || unfold compare_float in BASIC);
+ destruct (rs r1), (rs r2);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct i; simpl in BASIC; destruct is;
+ try (unfold compare_int in BASIC || unfold compare_long in BASIC);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct i; simpl in BASIC; destruct sz;
+ try (unfold compare_single in BASIC || unfold compare_float in BASIC);
+ destruct (rs r1);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct fsz; rewrite <- BASIC; rewrite Pregmap.gso; try (discriminate || reflexivity).
+ - destruct fsz; rewrite <- BASIC; rewrite Pregmap.gso; try (discriminate || reflexivity).
Qed.
-Lemma transl_instr_label':
- forall lbl f i ep k c,
- transl_instr f i ep k = OK c ->
- find_label lbl c = if Mach.is_label lbl i then Some k else find_label lbl k.
+Lemma exec_basic_dont_move_PC bi rs m rs' m': forall
+ (BASIC: exec_basic lk ge bi rs m = Next rs' m'),
+ rs PC = rs' PC.
Proof.
- intros. exploit transl_instr_label; eauto.
- destruct i; try (intros [A B]; apply B).
- intros. subst c. simpl. auto.
+ destruct bi; simpl; intros.
+ - inv BASIC. exploit exec_arith_instr_dont_move_PC; eauto.
+ - unfold exec_load in BASIC.
+ destruct Mem.loadv. 2: { discriminate BASIC. }
+ inv BASIC. rewrite Pregmap.gso; try discriminate; auto.
+ - unfold exec_store in BASIC.
+ destruct Mem.storev. 2: { discriminate BASIC. }
+ inv BASIC; reflexivity.
+ - destruct Mem.alloc, Mem.store. 2: { discriminate BASIC. }
+ inv BASIC. repeat (rewrite Pregmap.gso; try discriminate). reflexivity.
+ - destruct Mem.loadv. 2: { discriminate BASIC. }
+ destruct rs, Mem.free; try discriminate BASIC.
+ inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
Qed.
-Lemma transl_code_label:
- forall lbl f c ep tc,
- transl_code f c ep = OK tc ->
- match Mach.find_label lbl c with
- | None => find_label lbl tc = None
- | Some c' => exists tc', find_label lbl tc = Some tc' /\ transl_code f c' false = OK tc'
- end.
+Lemma exec_body_dont_move_PC_aux:
+ forall bis rs m rs' m'
+ (BODY: exec_body lk ge bis rs m = Next rs' m'),
+ rs PC = rs' PC.
Proof.
- induction c; simpl; intros.
- inv H. auto.
- monadInv H. rewrite (transl_instr_label' lbl _ _ _ _ _ EQ0).
- generalize (Mach.is_label_correct lbl a).
- destruct (Mach.is_label lbl a); intros.
- subst a. simpl in EQ. exists x; auto.
- eapply IHc; eauto.
+ induction bis.
+ - intros; inv BODY; reflexivity.
+ - simpl; intros.
+ remember (exec_basic lk ge a rs m) as bi eqn:BI; destruct bi. 2: { discriminate BODY. }
+ symmetry in BI; destruct s in BODY, BI; simpl in BODY, BI.
+ exploit exec_basic_dont_move_PC; eauto; intros AGPC; rewrite AGPC.
+ eapply IHbis; eauto.
Qed.
-Lemma transl_find_label:
- forall lbl f tf,
- transf_function f = OK tf ->
- match Mach.find_label lbl f.(Mach.fn_code) with
- | None => find_label lbl tf.(fn_code) = None
- | Some c => exists tc, find_label lbl tf.(fn_code) = Some tc /\ transl_code f c false = OK tc
- end.
+Lemma exec_body_dont_move_PC bb rs m rs' m': forall
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ rs PC = rs' PC.
+Proof. apply exec_body_dont_move_PC_aux. Qed.
+
+Lemma find_instr_bblock:
+ forall n lb pos bb tlb
+ (FINDBB: find_bblock pos lb = Some bb)
+ (UNFOLD: unfold lb = OK tlb)
+ (SIZE: 0 <= n < size bb),
+ exists i, is_nth_inst bb n i /\ Asm.find_instr (pos+n) tlb = Some i.
Proof.
- intros. monadInv H. destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0.
- monadInv EQ. rewrite transl_code'_transl_code in EQ0. unfold fn_code.
- simpl. destruct (storeptr_label X30 XSP (fn_retaddr_ofs f) x) as [A B]; rewrite B.
- eapply transl_code_label; eauto.
+ induction lb as [| b lb IHlb].
+ - intros. inversion FINDBB.
+ - intros pos bb tlb FINDBB UNFOLD SIZE.
+ destruct pos.
+ + inv FINDBB. simpl.
+ exploit unfold_car_cdr; eauto. intros (tbb & tlb' & UNFOLD_BBLOCK & UNFOLD' & UNFOLD_cons).
+ rewrite UNFOLD in UNFOLD_cons. inversion UNFOLD_cons.
+ unfold unfold_bblock in UNFOLD_BBLOCK.
+ (*destruct (zle (list_length_z (header bb)) 1). 2: { inversion UNFOLD_BBLOCK. }*)
+ apply bind_inversion in UNFOLD_BBLOCK.
+ destruct UNFOLD_BBLOCK as (? & UNFOLD_BODY & H).
+ inversion H as (UNFOLD_BBLOCK).
+ remember (list_nth_z (header bb) n) as label_opt eqn:LBL. destruct label_opt.
+ * (* nth instruction is a label *)
+ eexists; split. { eapply is_nth_label; eauto. }
+ inversion UNFOLD_cons.
+ symmetry in LBL.
+ rewrite <- app_assoc.
+ apply list_nth_z_find_label; auto.
+ * remember (list_nth_z (body bb) (n - list_length_z (header bb))) as bi_opt eqn:BI.
+ destruct bi_opt.
+ -- (* nth instruction is a basic instruction *)
+ exploit list_nth_z_in; eauto. intros INBB.
+ exploit entire_body_translated; eauto. intros BI'.
+ destruct BI'.
+ eexists; split.
+ ++ eapply is_nth_basic; eauto.
+ ++ repeat (rewrite <- app_assoc). eapply list_nth_z_find_bi_with_header; eauto.
+ -- (* nth instruction is the exit instruction *)
+ generalize n_beyond_body. intros TEMP.
+ assert (n >= Z.of_nat (Datatypes.length (header bb)
+ + Datatypes.length (body bb))) as NGE. { auto. } clear TEMP.
+ remember (exit bb) as exit_opt eqn:EXIT. destruct exit_opt.
+ ++ rewrite <- app_assoc. rewrite find_instr_past_header; auto.
+ rewrite <- app_assoc. erewrite find_instr_past_body; eauto.
+ assert (SIZE' := SIZE).
+ unfold size in SIZE. rewrite <- EXIT in SIZE. simpl in SIZE.
+ destruct SIZE as (LOWER & UPPER).
+ repeat (rewrite Nat2Z.inj_add in UPPER).
+ repeat (rewrite <- list_length_z_nat in UPPER). repeat (rewrite Nat2Z.inj_add in NGE).
+ repeat (rewrite <- list_length_z_nat in NGE). simpl in UPPER.
+ assert (n = list_length_z (header bb) + list_length_z (body bb)). { omega. }
+ assert (n = size bb - 1). {
+ unfold size. rewrite <- EXIT. simpl.
+ repeat (rewrite Nat2Z.inj_add). repeat (rewrite <- list_length_z_nat). simpl. omega.
+ }
+ symmetry in EXIT.
+ eexists; split.
+ ** eapply is_nth_ctlflow; eauto.
+ ** simpl.
+ destruct (zeq (n - list_length_z (header bb) - list_length_z (body bb)) 0). { reflexivity. }
+ (* absurd *) omega.
+ ++ (* absurd *)
+ unfold size in SIZE. rewrite <- EXIT in SIZE. simpl in SIZE.
+ destruct SIZE as (? & SIZE'). rewrite Nat.add_0_r in SIZE'. omega.
+ + unfold find_bblock in FINDBB; simpl in FINDBB; fold find_bblock in FINDBB.
+ inversion UNFOLD as (UNFOLD').
+ apply bind_inversion in UNFOLD'. destruct UNFOLD' as (? & (UNFOLD_BBLOCK' & UNFOLD')).
+ apply bind_inversion in UNFOLD'. destruct UNFOLD' as (? & (UNFOLD' & TLB)).
+ inversion TLB.
+ generalize (IHlb _ _ _ FINDBB UNFOLD'). intros IH.
+ destruct IH as (? & (IH_is_nth & IH_find_instr)); eauto.
+ eexists; split.
+ * apply IH_is_nth.
+ * replace (Z.pos p + n) with (Z.pos p + n - size b + size b) by omega.
+ eapply find_instr_bblock_tail; try assumption.
+ replace (Z.pos p + n - size b) with (Z.pos p - size b + n) by omega.
+ apply IH_find_instr.
+ + (* absurd *)
+ generalize (Pos2Z.neg_is_neg p). intros. exploit (find_bblock_neg (b :: lb)); eauto.
+ rewrite FINDBB. intros CONTRA. inversion CONTRA.
Qed.
-End TRANSL_LABEL.
+Lemma exec_header_simulation b ofs f bb rs m: forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb),
+ exists s', star Asm.step tge (State rs m) E0 s'
+ /\ match_internal (list_length_z (header bb)) (State rs m) s'.
+Proof.
+Admitted.
+ (* intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+ induction (header bb) eqn:EQhead.
+ + eexists; split.
+ - eapply star_refl.
+ - split; eauto.
+ unfold list_length_z; rewrite !ATPC; simpl.
+ rewrite Ptrofs.add_zero; auto.
+ + assert (Lgen: list_length_z (header bb) < (size bb)) by eapply header_size_lt_block_size.
+ assert (Lpos: list_length_z (l) >= 0) by eapply list_length_z_pos.
+ assert (Lsmaller: list_length_z (l) < list_length_z (header bb)).
+ { rewrite EQhead. rewrite list_length_z_cons. omega. }
+
+
+
+ exploit (find_instr_bblock (list_length_z (l))); eauto.
+ { generalize (bblock_size_pos bb). rewrite EQhead in *. intros. omega. }
+ intros (i & NTH & FIND_INSTR).
+ inv NTH.
+ - eexists. split. eapply star_one. eapply Asm.exec_step_internal; eauto.
+ inv FIND_INSTR.
+ eapply list_nth_z_range in H. rewrite EQhead in H.
+ eapply Nat.lt_neq in H0.
-(** A valid branch in a piece of Mach code translates to a valid ``go to''
- transition in the generated Asm code. *)
-Lemma find_label_goto_label:
- forall f tf lbl rs m c' b ofs,
- Genv.find_funct_ptr ge b = Some (Internal f) ->
- transf_function f = OK tf ->
- rs PC = Vptr b ofs ->
- Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
- exists tc', exists rs',
- goto_label tf lbl rs m = Next rs' m
- /\ transl_code_at_pc ge (rs' PC) b f c' false tf tc'
- /\ forall r, r <> PC -> rs'#r = rs#r.
-Proof.
- intros. exploit (transl_find_label lbl f tf); eauto. rewrite H2.
- intros [tc [A B]].
- exploit label_pos_code_tail; eauto. instantiate (1 := 0).
- intros [pos' [P [Q R]]].
- exists tc; exists (rs#PC <- (Vptr b (Ptrofs.repr pos'))).
- split. unfold goto_label. rewrite P. rewrite H1. auto.
- split. rewrite Pregmap.gss. constructor; auto.
- rewrite Ptrofs.unsigned_repr. replace (pos' - 0) with pos' in Q.
- auto. omega.
- generalize (transf_function_no_overflow _ _ H0). omega.
- intros. apply Pregmap.gso; auto.
-Qed.
-
-(** Existence of return addresses *)
+
-Lemma return_address_exists:
- forall f sg ros c, is_tail (Mcall sg ros :: c) f.(Mach.fn_code) ->
- exists ra, return_address_offset f c ra.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+ (*assert (BNDhead: list_length_z (header bb) <= 1). { eapply size_header; eauto. }*)
+ destruct (header bb) as [|l[|]] eqn: EQhead.
+ + (* header nil *)
+ eexists; split.
+ - eapply star_refl.
+ - split; eauto.
+ unfold list_length_z; rewrite !ATPC; simpl.
+ rewrite Ptrofs.add_zero; auto.
+ + (* header one *)
+ assert (Lhead: list_length_z (header bb) = 1). { rewrite EQhead; unfold list_length_z; simpl. auto. }
+ exploit (find_instr_bblock 0); eauto.
+ { generalize (bblock_size_pos bb). omega. }
+ intros (i & NTH & FIND_INSTR).
+ inv NTH.
+ * rewrite EQhead in H; simpl in H. inv H.
+ cutrewrite (Ptrofs.unsigned ofs + 0 = Ptrofs.unsigned ofs) in FIND_INSTR; try omega.
+ eexists. split.
+ - eapply star_one.
+ eapply Asm.exec_step_internal; eauto.
+ simpl; eauto.
+ - unfold list_length_z; simpl. split; eauto.
+ intros r; destruct r; simpl; congruence || auto.
+ * (* absurd case *)
+ erewrite list_nth_z_neg in * |-; [ congruence | rewrite Lhead; omega].
+ * (* absurd case *)
+ rewrite bblock_size_aux, Lhead in *. generalize (bblock_size_aux_pos bb). omega.
+ + (* absurd case *)
+ assert (Lgen: list_length_z (header bb) < (size bb)) by eapply header_size_lt_block_size.
+ assert (Ll1pos: list_length_z (l1) >= 0) by eapply list_length_z_pos.
+ assert (Lpos: list_length_z (header bb) - 1 > 0).
+ { rewrite EQhead. erewrite !list_length_z_cons. omega. }
+ exploit (find_instr_bblock (list_length_z (l :: l0 :: l1))); eauto.
+ { generalize (bblock_size_pos bb). rewrite EQhead in *. intros. omega. }
+ intros (i & NTH & FIND_INSTR).
+ inv NTH.
+ (*eapply list_nth_z_range in H. rewrite EQhead in H. destruct H.*)
+ (*eapply Nat.lt_neq in H0.*)
+ * rewrite EQhead in *; simpl in H.
+ assert ((list_length_z (l :: l0 :: l1) - 1) <> 0) by omega.
+ destruct zeq.
+ - rewrite e in FIND_INSTR. cutrewrite (Ptrofs.unsigned ofs + 0 = Ptrofs.unsigned ofs) in FIND_INSTR; try omega.
+ - destruct zeq; try (rewrite <- Z.sub_1_r in e; congruence).
+ inv H. eexists; split.
+ { eapply star_one. eapply list_nth_z_find_label in H2.
+ erewrite find_instr_past_header in H2.
+ assert (Z.pred (Z.pred (list_length_z (l :: l0 :: l1))) = list_length_z l1).
+ { erewrite <- !Z.sub_1_r. erewrite !list_length_z_cons. omega. }
+ replace (Z.pred (Z.pred (list_length_z (l :: l0 :: l1))) - list_length_z l1) with (0) in H2 by omega.
+ rewrite <- FIND_INSTR in H2.
+ unfold find_instr in H2.
+ destruct tc eqn:HTC.
+ { simpl in *. inversion FIND_INSTR. }
+ { simpl in *.
+
+ destruct zeq eqn:HZEQ.
+
+ { fold find_instr in H2. assert (0 <= Ptrofs.unsigned ofs <= Ptrofs.max_unsigned) by eapply Ptrofs.unsigned_range_2. assert (list_length_z (l :: l0 :: l1) > 0) by omega.
+ assert (Ptrofs.unsigned ofs = - list_length_z (l :: l0 :: l1)) by omega.
+ assert (Ptrofs.unsigned ofs = 0) by omega.
+ assert (list_length_z (l :: l0 :: l1) = 0) by omega. congruence. }
+ { simpl in *.
+ rewrite H4 in H5.
+
+ eapply Asm.exec_step_internal; eauto.
+
+ destruct zeq.
+ - inv H. eexists. split.
+ assert (list_length_z (l :: l2 :: l1) - 1 = 1) by omega. rewrite H in *.
+ { eapply star_one. exploit (find_instr_bblock 0); eauto; try omega.
+ intros (i' & NTH' & FIND_INSTR').
+ eapply Asm.exec_step_internal; eauto.
+
+
+ inv H.
+ cutrewrite (Ptrofs.unsigned ofs + 0 = Ptrofs.unsigned ofs) in FIND_INSTR; try omega.
+ eexists. split.
+ - eapply star_one.
+ eapply Asm.exec_step_internal; eauto.
+ simpl; eauto.
+ - unfold list_length_z; simpl. split. eauto.
+ intros r; destruct r; simpl; congruence || auto.
+ * (* absurd case *)
+ erewrite list_nth_z_neg in * |-; [ congruence | rewrite Lhead; omega].
+ * (* absurd case *)
+ rewrite bblock_size_aux, Lhead in *. generalize (bblock_size_aux_pos bb). omega.
+ unfold list_length_z in BNDhead. simpl in *.
+ generalize (list_length_z_aux_increase _ l1 2); omega.
+Qed.*)
+
+Lemma eval_addressing_preserved a rs1 rs2:
+ (forall r : preg, r <> PC -> rs1 r = rs2 r) ->
+ eval_addressing lk a rs1 = Asm.eval_addressing tge a rs2.
Proof.
- intros. eapply Asmgenproof0.return_address_exists; eauto.
-- intros. exploit transl_instr_label; eauto.
- destruct i; try (intros [A B]; apply A). intros. subst c0. repeat constructor.
-- intros. monadInv H0.
- destruct (zlt Ptrofs.max_unsigned (list_length_z x.(fn_code))); inv EQ0. monadInv EQ.
- rewrite transl_code'_transl_code in EQ0.
- exists x; exists true; split; auto. unfold fn_code.
- constructor. apply (storeptr_label X30 XSP (fn_retaddr_ofs f0) x).
-- exact transf_function_no_overflow.
-Qed.
-
-(** * Proof of semantic preservation *)
-
-(** Semantic preservation is proved using simulation diagrams
- of the following form.
-<<
- st1 --------------- st2
- | |
- t| *|t
- | |
- v v
- st1'--------------- st2'
->>
- The invariant is the [match_states] predicate below, which includes:
-- The Asm code pointed by the PC register is the translation of
- the current Mach code sequence.
-- Mach register values and Asm register values agree.
-*)
+ intros EQ.
+ destruct a; simpl; try (rewrite !EQ; congruence). auto.
+Qed.
-Inductive match_states: Mach.state -> Asm.state -> Prop :=
- | match_states_intro:
- forall s fb sp c ep ms m m' rs f tf tc
- (STACKS: match_stack ge s)
- (FIND: Genv.find_funct_ptr ge fb = Some (Internal f))
- (MEXT: Mem.extends m m')
- (AT: transl_code_at_pc ge (rs PC) fb f c ep tf tc)
- (AG: agree ms sp rs)
- (DXP: ep = true -> rs#X29 = parent_sp s)
- (LEAF: is_leaf_function f = true -> rs#RA = parent_ra s),
- match_states (Mach.State s fb sp c ms m)
- (Asm.State rs m')
- | match_states_call:
- forall s fb ms m m' rs
- (STACKS: match_stack ge s)
- (MEXT: Mem.extends m m')
- (AG: agree ms (parent_sp s) rs)
- (ATPC: rs PC = Vptr fb Ptrofs.zero)
- (ATLR: rs RA = parent_ra s),
- match_states (Mach.Callstate s fb ms m)
- (Asm.State rs m')
- | match_states_return:
- forall s ms m m' rs
- (STACKS: match_stack ge s)
- (MEXT: Mem.extends m m')
- (AG: agree ms (parent_sp s) rs)
- (ATPC: rs PC = parent_ra s),
- match_states (Mach.Returnstate s ms m)
- (Asm.State rs m').
-
-Lemma exec_straight_steps:
- forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2,
- match_stack ge s ->
- Mem.extends m2 m2' ->
- Genv.find_funct_ptr ge fb = Some (Internal f) ->
- transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
- (forall k c (TR: transl_instr f i ep k = OK c),
- exists rs2,
- exec_straight tge tf c rs1 m1' k rs2 m2'
- /\ agree ms2 sp rs2
- /\ (it1_is_parent ep i = true -> rs2#X29 = parent_sp s)
- /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
- exists st',
- plus step tge (State rs1 m1') E0 st' /\
- match_states (Mach.State s fb sp c ms2 m2) st'.
-Proof.
- intros. inversion H2. subst. monadInv H7.
- exploit H3; eauto. intros [rs2 [A [B [C D]]]].
- exists (State rs2 m2'); split.
- - eapply exec_straight_exec; eauto.
- - econstructor; eauto. eapply exec_straight_at; eauto.
-Qed.
-
-Lemma exec_straight_steps_goto:
- forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2 lbl c',
- match_stack ge s ->
- Mem.extends m2 m2' ->
- Genv.find_funct_ptr ge fb = Some (Internal f) ->
- Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
- transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
- it1_is_parent ep i = false ->
- (forall k c (TR: transl_instr f i ep k = OK c),
- exists jmp, exists k', exists rs2,
- exec_straight tge tf c rs1 m1' (jmp :: k') rs2 m2'
- /\ agree ms2 sp rs2
- /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
- /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
- exists st',
- plus step tge (State rs1 m1') E0 st' /\
- match_states (Mach.State s fb sp c' ms2 m2) st'.
-Proof.
- intros. inversion H3. subst. monadInv H9.
- exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
- generalize (functions_transl _ _ _ H7 H8); intro FN.
- generalize (transf_function_no_overflow _ _ H8); intro NOOV.
- exploit exec_straight_steps_2; eauto.
- intros [ofs' [PC2 CT2]].
- exploit find_label_goto_label; eauto.
- intros [tc' [rs3 [GOTO [AT' OTH]]]].
- exists (State rs3 m2'); split.
- eapply plus_right'.
- eapply exec_straight_steps_1; eauto.
- econstructor; eauto.
- eapply find_instr_tail. eauto.
- rewrite C. eexact GOTO.
- traceEq.
- econstructor; eauto.
- apply agree_exten with rs2; auto with asmgen.
- congruence.
- rewrite OTH by congruence; auto.
-Qed.
-
-Lemma exec_straight_opt_steps_goto:
- forall s fb f rs1 i c ep tf tc m1' m2 m2' sp ms2 lbl c',
- match_stack ge s ->
- Mem.extends m2 m2' ->
- Genv.find_funct_ptr ge fb = Some (Internal f) ->
- Mach.find_label lbl f.(Mach.fn_code) = Some c' ->
- transl_code_at_pc ge (rs1 PC) fb f (i :: c) ep tf tc ->
- it1_is_parent ep i = false ->
- (forall k c (TR: transl_instr f i ep k = OK c),
- exists jmp, exists k', exists rs2,
- exec_straight_opt tge tf c rs1 m1' (jmp :: k') rs2 m2'
- /\ agree ms2 sp rs2
- /\ exec_instr tge tf jmp rs2 m2' = goto_label tf lbl rs2 m2'
- /\ (is_leaf_function f = true -> rs2#RA = parent_ra s)) ->
- exists st',
- plus step tge (State rs1 m1') E0 st' /\
- match_states (Mach.State s fb sp c' ms2 m2) st'.
-Proof.
- intros. inversion H3. subst. monadInv H9.
- exploit H5; eauto. intros [jmp [k' [rs2 [A [B [C D]]]]]].
- generalize (functions_transl _ _ _ H7 H8); intro FN.
- generalize (transf_function_no_overflow _ _ H8); intro NOOV.
- inv A.
-- exploit find_label_goto_label; eauto.
- intros [tc' [rs3 [GOTO [AT' OTH]]]].
- exists (State rs3 m2'); split.
- apply plus_one. econstructor; eauto.
- eapply find_instr_tail. eauto.
- rewrite C. eexact GOTO.
- econstructor; eauto.
- apply agree_exten with rs2; auto with asmgen.
- congruence.
- rewrite OTH by congruence; auto.
-- exploit exec_straight_steps_2; eauto.
- intros [ofs' [PC2 CT2]].
- exploit find_label_goto_label; eauto.
- intros [tc' [rs3 [GOTO [AT' OTH]]]].
- exists (State rs3 m2'); split.
- eapply plus_right'.
- eapply exec_straight_steps_1; eauto.
- econstructor; eauto.
- eapply find_instr_tail. eauto.
- rewrite C. eexact GOTO.
- traceEq.
- econstructor; eauto.
- apply agree_exten with rs2; auto with asmgen.
- congruence.
- rewrite OTH by congruence; auto.
-Qed.
-
-(** We need to show that, in the simulation diagram, we cannot
- take infinitely many Mach transitions that correspond to zero
- transitions on the Asm side. Actually, all Mach transitions
- correspond to at least one Asm transition, except the
- transition from [Machsem.Returnstate] to [Machsem.State].
- So, the following integer measure will suffice to rule out
- the unwanted behaviour. *)
-
-Definition measure (s: Mach.state) : nat :=
- match s with
- | Mach.State _ _ _ _ _ _ => 0%nat
- | Mach.Callstate _ _ _ _ => 0%nat
- | Mach.Returnstate _ _ _ => 1%nat
+Ltac next_stuck_cong := try (unfold Next, Stuck in *; congruence).
+
+Ltac inv_ok_eq :=
+ repeat match goal with
+ | [EQ: OK ?x = OK ?y |- _ ]
+ => inversion EQ; clear EQ; subst
+ end.
+
+Ltac reg_rwrt :=
+ match goal with
+ | [e: DR _ = DR _ |- _ ]
+ => rewrite e in *
end.
-Remark preg_of_not_X29: forall r, negb (mreg_eq r R29) = true -> IR X29 <> preg_of r.
-Proof.
- intros. change (IR X29) with (preg_of R29). red; intros.
- exploit preg_of_injective; eauto. intros; subst r; discriminate.
-Qed.
-
-Lemma sp_val': forall ms sp rs, agree ms sp rs -> sp = rs XSP.
-Proof.
- intros. eapply sp_val; eauto.
-Qed.
-
-(** This is the simulation diagram. We prove it by case analysis on the Mach transition. *)
-
-Theorem step_simulation:
- forall S1 t S2, Mach.step return_address_offset ge S1 t S2 ->
- forall S1' (MS: match_states S1 S1') (WF: wf_state ge S1),
- (exists S2', plus step tge S1' t S2' /\ match_states S2 S2')
- \/ (measure S2 < measure S1 /\ t = E0 /\ match_states S2 S1')%nat.
-Proof.
- induction 1; intros; inv MS.
-
-- (* Mlabel *)
- left; eapply exec_straight_steps; eauto; intros.
- monadInv TR. econstructor; split. apply exec_straight_one. simpl; eauto. auto.
- split. { apply agree_nextinstr; auto. }
- split. { simpl; congruence. }
- rewrite nextinstr_inv by congruence; assumption.
-
-- (* Mgetstack *)
- unfold load_stack in H.
- exploit Mem.loadv_extends; eauto. intros [v' [A B]].
- rewrite (sp_val _ _ _ AG) in A.
- left; eapply exec_straight_steps; eauto. intros. simpl in TR.
- exploit loadind_correct; eauto with asmgen. intros [rs' [P [Q [R S]]]].
- exists rs'; split. eauto.
- split. { eapply agree_set_mreg; eauto with asmgen. congruence. }
- split. { simpl; congruence. }
- rewrite S. assumption.
-
-- (* Msetstack *)
- unfold store_stack in H.
- assert (Val.lessdef (rs src) (rs0 (preg_of src))) by (eapply preg_val; eauto).
- exploit Mem.storev_extends; eauto. intros [m2' [A B]].
- left; eapply exec_straight_steps; eauto.
- rewrite (sp_val _ _ _ AG) in A. intros. simpl in TR.
- exploit storeind_correct; eauto with asmgen. intros [rs' [P [Q R]]].
- exists rs'; split. eauto.
- split. eapply agree_undef_regs; eauto with asmgen.
- simpl; intros.
- split. rewrite Q; auto with asmgen.
- rewrite R. assumption.
-
-- (* Mgetparam *)
- assert (f0 = f) by congruence; subst f0.
- unfold load_stack in *.
- exploit Mem.loadv_extends. eauto. eexact H0. auto.
- intros [parent' [A B]]. rewrite (sp_val' _ _ _ AG) in A.
- exploit lessdef_parent_sp; eauto. clear B; intros B; subst parent'.
- exploit Mem.loadv_extends. eauto. eexact H1. auto.
- intros [v' [C D]].
-Opaque loadind.
- left; eapply exec_straight_steps; eauto; intros. monadInv TR.
- destruct ep.
-(* X30 contains parent *)
- exploit loadind_correct. eexact EQ.
- instantiate (2 := rs0). simpl; rewrite DXP; eauto. simpl; congruence.
- intros [rs1 [P [Q [R S]]]].
- exists rs1; split. eauto.
- split. eapply agree_set_mreg. eapply agree_set_mreg; eauto. congruence. auto with asmgen.
- simpl; split; intros.
- { rewrite R; auto with asmgen.
- apply preg_of_not_X29; auto.
+Ltac destruct_reg_inv :=
+ repeat match goal with
+ | [ H : match ?reg with _ => _ end = _ |- _ ]
+ => simpl in *; destruct reg; try congruence; try inv_ok_eq; try reg_rwrt
+ end.
+
+Ltac destruct_ireg_inv :=
+ repeat match goal with
+ | [ H : match ?reg with _ => _ end = _ |- _ ]
+ => destruct reg as [[r|]|]; try congruence; try inv_ok_eq; subst
+ end.
+
+Ltac destruct_reg_size :=
+ simpl in *;
+ match goal with
+ | [ |- context [ match ?reg with _ => _ end ] ]
+ => destruct reg; try congruence
+ end.
+
+Ltac find_rwrt_ag :=
+ simpl in *;
+ match goal with
+ | [ AG: forall r, r <> ?PC -> _ r = _ r |- _ ]
+ => repeat rewrite <- AG; try congruence
+ end.
+
+Ltac inv_matchi :=
+ match goal with
+ | [ MATCHI : match_internal _ _ _ |- _ ]
+ => inversion MATCHI; subst; find_rwrt_ag
+ end.
+
+Ltac destruct_ir0_reg :=
+ match goal with
+ | [ |- context [ ir0 _ _ ?r ] ]
+ => unfold ir0 in *; destruct r; find_rwrt_ag; eauto
+ end.
+
+Ltac pc_not_sp :=
+ match goal with
+ | [ |- ?PC <> ?SP ]
+ => destruct (PregEq.eq SP PC); repeat congruence; discriminate
+ end.
+
+Ltac update_x_access_x :=
+ subst; rewrite !Pregmap.gss; auto.
+
+Ltac update_x_access_r :=
+ rewrite !Pregmap.gso; auto.
+
+Lemma nextinstr_agree_but_pc rs1 rs2: forall
+ (AG: forall r, r <> PC -> rs1 r = rs2 r),
+ forall r, r <> PC -> rs1 r = Asm.nextinstr rs2 r.
+Proof.
+ intros; unfold Asm.nextinstr in *; rewrite Pregmap.gso in *; eauto.
+Qed.
+
+Lemma ptrofs_nextinstr_agree rs1 rs2 n: forall
+ (BOUNDED : 0 <= n <= Ptrofs.max_unsigned)
+ (AGPC : Val.offset_ptr (rs1 PC) (Ptrofs.repr n) = rs2 PC),
+ Val.offset_ptr (rs1 PC) (Ptrofs.repr (n + 1)) = Asm.nextinstr rs2 PC.
+Proof.
+ intros; unfold Asm.nextinstr; rewrite Pregmap.gss.
+ rewrite <- Ptrofs.unsigned_one; rewrite <- (Ptrofs.unsigned_repr n); eauto;
+ rewrite <- Ptrofs.add_unsigned; rewrite <- Val.offset_ptr_assoc; rewrite AGPC; eauto.
+Qed.
+
+Lemma load_preserved n rs1 m1 rs1' m1' rs2 m2 rd chk f a: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (HLOAD: exec_load lk chk f a rd rs1 m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.exec_load tge chk f a rd rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold exec_load, Asm.exec_load in *.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ rewrite <- (eval_addressing_preserved a rs1 rs2); auto.
+ destruct (Mem.loadv _ _ _).
+ + inversion HLOAD; auto. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ destruct (PregEq.eq r rd); try update_x_access_x; try update_x_access_r.
+ * eapply ptrofs_nextinstr_agree; eauto.
+ + next_stuck_cong.
+Qed.
+
+Lemma store_preserved n rs1 m1 rs1' m1' rs2 m2 rd chk a: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (HSTORE: exec_store lk chk a rd rs1 m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.exec_store tge chk a rd rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold exec_store, Asm.exec_store in *.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ rewrite <- (eval_addressing_preserved a rs1 rs2); auto.
+ destruct (Mem.storev _ _ _ _).
+ + inversion HSTORE; auto. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ subst. apply EQR. auto.
+ * eapply ptrofs_nextinstr_agree; subst; eauto.
+ + next_stuck_cong.
+Qed.
+
+Lemma next_inst_preserved n rs1 m1 rs1' m1' rs2 m2 (x: dreg) v: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (NEXTI: Next rs1 # x <- v m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem),
+ Next (Asm.nextinstr rs2 # x <- v) m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ inversion NEXTI. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ destruct (PregEq.eq r x); try update_x_access_x; try update_x_access_r.
+ * eapply ptrofs_nextinstr_agree; eauto.
+Qed.
+
+Lemma match_internal_nextinstr_switch:
+ forall n s rs2 m2 r v,
+ r <> PC ->
+ match_internal n s (State ((Asm.nextinstr rs2)#r <- v) m2) ->
+ match_internal n s (State (Asm.nextinstr (rs2#r <- v)) m2).
+Proof.
+ unfold Asm.nextinstr; intros n s rs2 m2 r v NOTPC1 MI.
+ inversion MI; subst; constructor; auto.
+ - eapply nextinstr_agree_but_pc; intros.
+ rewrite AG; try congruence.
+ destruct (PregEq.eq r r0); try update_x_access_x; try update_x_access_r.
+ - rewrite !Pregmap.gss, !Pregmap.gso; try congruence.
+ rewrite AGPC.
+ rewrite Pregmap.gso, Pregmap.gss; try congruence.
+Qed.
+
+Lemma match_internal_nextinstr_set_parallel:
+ forall n rs1 m1 rs2 m2 r v1 v2,
+ r <> PC ->
+ match_internal n (State rs1 m1) (State (Asm.nextinstr rs2) m2) ->
+ v1 = v2 ->
+ match_internal n (State (rs1#r <- v1) m1) (State (Asm.nextinstr (rs2#r <- v2)) m2).
+Proof.
+ intros; subst; eapply match_internal_nextinstr_switch; eauto.
+ intros; eapply match_internal_set_parallel; eauto.
+Qed.
+
+Lemma exec_basic_simulation:
+ forall tf n rs1 m1 rs1' m1' rs2 m2 bi tbi
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (BASIC: exec_basic lk ge bi rs1 m1 = Next rs1' m1')
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (TRANSBI: basic_to_instruction bi = OK tbi),
+ exists rs2' m2', Asm.exec_instr tge tf tbi
+ rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ destruct bi.
+ { (* PArith *)
+ simpl in *; destruct i.
+ 1,2,3,4,5,6: (* PArithP, PArithPP, PArithPPP, PArithRR0R, PArithRR0, PArithARRRR0 *)
+ destruct i;
+ try (destruct sumbool_rec; try congruence);
+ try (monadInv TRANSBI);
+ try (destruct_reg_inv);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ try (repeat destruct_reg_size);
+ try (destruct_ir0_reg).
+ { (* PArithComparisonPP *)
+ destruct i;
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_inv);
+ simpl in *.
+ 1,2: (* compare_long *)
+ inversion BASIC; clear BASIC; subst;
+ eexists; eexists; split; eauto;
+ unfold compare_long;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+
+ destruct sz.
+ - (* compare_single *)
+ unfold compare_single in BASIC.
+ destruct (rs1 x), (rs1 x0);
+ inversion BASIC;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+ - (* compare_float *)
+ unfold compare_float in BASIC.
+ destruct (rs1 x), (rs1 x0);
+ inversion BASIC;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ 1,2: (* PArithComparisonR0R, PArithComparisonP *)
+ destruct i;
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_inv);
+ try (destruct_reg_size);
+ simpl in *;
+ inversion BASIC; clear BASIC; subst;
+ eexists; eexists; split; eauto;
+ unfold compare_long, compare_int, compare_float, compare_single;
+ try (destruct_reg_size);
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (destruct_ir0_reg);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+ { (* Pcset *)
+ try (monadInv TRANSBI);
+ try (inv_matchi).
+ try (exploit next_inst_preserved; eauto);
+ try (simpl in *; intros;
+ unfold if_opt_bool_val in *; unfold eval_testcond in *;
+ rewrite <- !AG; try congruence; eauto). }
+ { (* Pfmovi *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_size);
+ try (destruct_ir0_reg);
+ try (exploit next_inst_preserved; eauto). }
+ { (* Pcsel *)
+ try (destruct_reg_inv);
+ try (monadInv TRANSBI);
+ try (destruct_reg_inv);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ simpl in *; intros;
+ unfold if_opt_bool_val in *; unfold eval_testcond in *;
+ rewrite <- !AG; try congruence; eauto. }
+ { (* Pfnmul *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_size);
+ try (exploit next_inst_preserved; eauto);
+ try (find_rwrt_ag). } }
+ { (* PLoad *)
+ destruct ld; monadInv TRANSBI; try destruct_ireg_inv; exploit load_preserved; eauto;
+ intros; simpl in *; destruct sz; eauto. }
+ { (* PStore *)
+ destruct st; monadInv TRANSBI; try destruct_ireg_inv; exploit store_preserved; eauto;
+ simpl in *; inv_matchi; find_rwrt_ag. }
+ { (* Pallocframe *)
+ monadInv TRANSBI;
+ inv_matchi; try pc_not_sp;
+ destruct sz eqn:EQSZ;
+ destruct Mem.alloc eqn:EQALLOC;
+ destruct Mem.store eqn:EQSTORE; inversion BASIC; try pc_not_sp;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ try (pc_not_sp; congruence) | idtac | try (reflexivity)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ { (* Pfreeframe *)
+ monadInv TRANSBI;
+ inv_matchi; try pc_not_sp;
+ destruct sz eqn:EQSZ;
+ destruct Mem.loadv eqn:EQLOAD;
+ destruct (rs1 SP) eqn:EQRS1SP;
+ try (destruct Mem.free eqn:EQFREE);
+ inversion BASIC; try pc_not_sp;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ try (pc_not_sp; congruence) | idtac | try (reflexivity)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ 1,2,3,4: (* Ploadsymbol, Pcvtsw2x, Pcvtuw2x, Pcvtx2w *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ rewrite symbol_addresses_preserved; eauto;
+ try (find_rwrt_ag).
+Qed.
+
+Lemma find_basic_instructions b ofs f bb tc: forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (UNFOLD: unfold (fn_blocks f) = OK tc),
+ forall n,
+ (n < length (body bb))%nat ->
+ exists (i : Asm.instruction) (bi : basic),
+ list_nth_z (body bb) (Z.of_nat n) = Some bi
+ /\ basic_to_instruction bi = OK i
+ /\ Asm.find_instr (Ptrofs.unsigned ofs
+ + (list_length_z (header bb))
+ + Z.of_nat n) tc
+ = Some i.
+Proof.
+ intros until n; intros NLT.
+ exploit internal_functions_unfold; eauto.
+ intros (tc' & FINDtf & TRANStf & _).
+ assert (tc' = tc) by congruence; subst.
+ exploit (find_instr_bblock (list_length_z (header bb) + Z.of_nat n)); eauto.
+ { unfold size; split.
+ - rewrite list_length_z_nat; omega.
+ - repeat (rewrite list_length_z_nat). repeat (rewrite Nat2Z.inj_add). omega. }
+ intros (i & NTH & FIND_INSTR).
+ exists i; intros.
+ inv NTH.
+ - (* absurd *) apply list_nth_z_range in H; omega.
+ - exists bi;
+ rewrite Z.add_simpl_l in H;
+ rewrite Z.add_assoc in FIND_INSTR;
+ intuition.
+ - (* absurd *) rewrite bblock_size_aux in H0;
+ rewrite H in H0; simpl in H0; repeat rewrite list_length_z_nat in H0; omega.
+Qed.
+
+(** "is_tail" auxiliary lemma about is_tail to move in IterList ou Coqlib (déplacer aussi Machblockgenproof.is_tail_app_inv) ? *)
+
+Lemma is_tail_app_right A (l2 l1: list A): is_tail l1 (l2++l1).
+Proof.
+ intros; eapply Machblockgenproof.is_tail_app_inv; econstructor.
+Qed.
+
+Lemma is_tail_app_def A (l1 l2: list A):
+ is_tail l1 l2 -> exists l3, l2 = l3 ++ l1.
+Proof.
+ induction 1 as [|x l1 l2]; simpl.
+ - exists nil; simpl; auto.
+ - destruct IHis_tail as (l3 & EQ); rewrite EQ.
+ exists (x::l3); simpl; auto.
+Qed.
+
+Lemma is_tail_bound A (l1 l2: list A):
+ is_tail l1 l2 -> (length l1 <= length l2)%nat.
+Proof.
+ intros H; destruct (is_tail_app_def _ _ _ H) as (l3 & EQ).
+ subst; rewrite app_length.
+ omega.
+Qed.
+
+Lemma is_tail_list_nth_z A (l1 l2: list A):
+ is_tail l1 l2 -> list_nth_z l2 ((list_length_z l2) - (list_length_z l1)) = list_nth_z l1 0.
+Proof.
+ induction 1; simpl.
+ - replace (list_length_z c - list_length_z c) with 0; omega || auto.
+ - assert (X: list_length_z (i :: c2) > list_length_z c1).
+ { rewrite !list_length_z_nat, <- Nat2Z.inj_gt.
+ exploit is_tail_bound; simpl; eauto.
+ omega. }
+ destruct (zeq (list_length_z (i :: c2) - list_length_z c1) 0) as [Y|Y]; try omega.
+ replace (Z.pred (list_length_z (i :: c2) - list_length_z c1)) with (list_length_z c2 - list_length_z c1); auto.
+ rewrite list_length_z_cons.
+ omega.
+Qed.
+
+(* TODO: remplacer find_basic_instructions directement par ce lemme ? *)
+Lemma find_basic_instructions_alt b ofs f bb tc n: forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (UNFOLD: unfold (fn_blocks f) = OK tc)
+ (BOUND: 0 <= n < list_length_z (body bb)),
+ exists (i : Asm.instruction) (bi : basic),
+ list_nth_z (body bb) n = Some bi
+ /\ basic_to_instruction bi = OK i
+ /\ Asm.find_instr (Ptrofs.unsigned ofs
+ + (list_length_z (header bb))
+ + n) tc
+ = Some i.
+Proof.
+ intros; assert ((Z.to_nat n) < length (body bb))%nat.
+ { rewrite Nat2Z.inj_lt, <- list_length_z_nat, Z2Nat.id; try omega. }
+ exploit find_basic_instructions; eauto.
+ rewrite Z2Nat.id; try omega. intros (i & bi & X).
+ eexists; eexists; intuition eauto.
+Qed.
+
+Lemma header_body_tail_bound: forall (a: basic) (li: list basic) bb ofs
+ (BOUNDBB : Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ (BDYLENPOS : 0 <= list_length_z (body bb) - list_length_z (a :: li) <
+ list_length_z (body bb)),
+0 <= list_length_z (header bb) + list_length_z (body bb) - list_length_z (a :: li) <=
+Ptrofs.max_unsigned.
+Proof.
+ intros.
+ assert (HBBPOS: list_length_z (header bb) >= 0) by eapply list_length_z_pos.
+ assert (HBBSIZE: list_length_z (header bb) < size bb) by eapply header_size_lt_block_size.
+ assert (OFSBOUND: 0 <= Ptrofs.unsigned ofs <= Ptrofs.max_unsigned) by eapply Ptrofs.unsigned_range_2.
+ assert (BBSIZE: size bb <= Ptrofs.max_unsigned) by omega.
+ unfold size in BBSIZE.
+ rewrite !Nat2Z.inj_add in BBSIZE.
+ rewrite <- !list_length_z_nat in BBSIZE.
+ omega.
+Qed.
+
+(* A more general version of the exec_body_simulation_plus lemma below.
+ This generalization is necessary for the induction proof inside the body.
+*)
+Lemma exec_body_simulation_plus_gen li: forall b ofs f bb rs m s2 rs' m'
+ (BLI: is_tail li (body bb))
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_BODY: li <> nil)
+ (MATCHI: match_internal ((list_length_z (header bb)) + (list_length_z (body bb)) - (list_length_z li)) (State rs m) s2)
+ (BODY: exec_body lk ge li rs m = Next rs' m'),
+ exists s2', plus Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ induction li as [|a li]; simpl; try congruence.
+ intros.
+ assert (BDYLENPOS: 0 <= (list_length_z (body bb) - list_length_z (a::li)) < list_length_z (body bb)). {
+ assert (Z.of_nat O < list_length_z (a::li) <= list_length_z (body bb)); try omega.
+ rewrite !list_length_z_nat; split.
+ - rewrite <- Nat2Z.inj_lt. simpl. omega.
+ - rewrite <- Nat2Z.inj_le; eapply is_tail_bound; eauto.
}
- { rewrite S; auto. }
-
-(* X30 does not contain parent *)
- exploit loadptr_correct. eexact A. simpl; congruence. intros [rs1 [P [Q R]]].
- exploit loadind_correct. eexact EQ. instantiate (2 := rs1). simpl; rewrite Q. eauto. simpl; congruence.
- intros [rs2 [S [T [U V]]]].
- exists rs2; split. eapply exec_straight_trans; eauto.
- split. eapply agree_set_mreg. eapply agree_set_mreg. eauto. eauto.
- instantiate (1 := rs1#X29 <- (rs2#X29)). intros.
- rewrite Pregmap.gso; auto with asmgen.
- congruence.
- intros. unfold Pregmap.set. destruct (PregEq.eq r' X29). congruence. auto with asmgen.
- split; simpl; intros. rewrite U; auto with asmgen.
- apply preg_of_not_X29; auto.
- rewrite V. rewrite R by congruence. auto.
-
-- (* Mop *)
- assert (eval_operation tge sp op (map rs args) m = Some v).
- { rewrite <- H. apply eval_operation_preserved. exact symbols_preserved. }
- exploit eval_operation_lessdef. eapply preg_vals; eauto. eauto. eexact H0.
- intros [v' [A B]]. rewrite (sp_val _ _ _ AG) in A.
- left; eapply exec_straight_steps; eauto; intros. simpl in TR.
- exploit transl_op_correct; eauto. intros [rs2 [P [Q [R S]]]].
- exists rs2; split. eauto. split.
- apply agree_set_undef_mreg with rs0; auto.
- apply Val.lessdef_trans with v'; auto.
- split; simpl; intros. InvBooleans.
- rewrite R; auto. apply preg_of_not_X29; auto.
-Local Transparent destroyed_by_op.
- destruct op; try exact I; simpl; congruence.
- rewrite S.
- auto.
-- (* Mload *)
- destruct trap.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+ exploit find_basic_instructions_alt; eauto.
+ intros (tbi & (bi & (NTHBI & TRANSBI & FIND_INSTR))).
+ exploit is_tail_list_nth_z; eauto.
+ rewrite NTHBI; simpl.
+ intros X; inversion X; subst; clear X NTHBI.
+ destruct (exec_basic _ _ _ _ _) eqn:EXEC_BASIC; next_stuck_cong.
+ destruct s as (rs1 & m1); simpl in *.
+ destruct s2 as (rs2 & m2); simpl in *.
+ assert (BOUNDBBMAX: Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ by (eapply size_of_blocks_bounds; eauto).
+ exploit header_body_tail_bound; eauto. intros BDYTAIL.
+ exploit exec_basic_simulation; eauto.
+ intros (rs_next' & m_next' & EXEC_INSTR & MI_NEXT).
+ exploit exec_basic_dont_move_PC; eauto. intros AGPC.
+ inversion MI_NEXT as [A B C D E M_NEXT_AGREE RS_NEXT_AGREE ATPC_NEXT PC_OFS_NEXT RS RS'].
+ subst A. subst B. subst C. subst D. subst E.
+ rewrite ATPC in AGPC. symmetry in AGPC, ATPC_NEXT.
+
+ inv MATCHI. symmetry in AGPC0.
+ rewrite ATPC in AGPC0.
+ unfold Val.offset_ptr in AGPC0.
+
+ simpl in FIND_INSTR.
+ (* Execute internal step. *)
+ exploit (Asm.exec_step_internal tge b); eauto.
{
- assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
- { rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved. }
- exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
- intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
- exploit Mem.loadv_extends; eauto. intros [v' [C D]].
- left; eapply exec_straight_steps; eauto; intros. simpl in TR.
- exploit transl_load_correct; eauto. intros [rs2 [P [Q [R S]]]].
- exists rs2; split. eauto.
- split. eapply agree_set_undef_mreg; eauto. congruence.
- split. simpl; congruence.
- rewrite S. assumption.
+ rewrite Ptrofs.add_unsigned.
+ repeat (rewrite Ptrofs.unsigned_repr); try omega.
+ 2: {
+ assert (BOUNDOFS: 0 <= Ptrofs.unsigned ofs <= Ptrofs.max_unsigned) by eapply Ptrofs.unsigned_range_2.
+ assert (list_length_z (body bb) <= size bb) by eapply body_size_le_block_size.
+ assert (list_length_z (header bb) + list_length_z (body bb) <= size bb).
+ { generalize bblock_size_aux. intros. rewrite H0. generalize bblock_size_aux. intros. omega. }
+ omega. }
+ try rewrite list_length_z_nat; try split;
+ simpl; rewrite <- !list_length_z_nat;
+ replace (Ptrofs.unsigned ofs + (list_length_z (header bb) + list_length_z (body bb) -
+ list_length_z (a :: li))) with (Ptrofs.unsigned ofs + list_length_z (header bb) +
+ (list_length_z (body bb) - list_length_z (a :: li))) by omega;
+ try assumption; try omega. }
+
+ (* This is our STEP hypothesis. *)
+ intros STEP_NEXT.
+ destruct li as [|a' li]; simpl in *.
+ - (* case of a single instruction in li: this our base case in the induction *)
+ inversion BODY; subst.
+ eexists; split.
+ + apply plus_one. eauto.
+ + constructor; auto.
+ rewrite ATPC_NEXT.
+ apply f_equal.
+ apply f_equal.
+ rewrite bblock_size_aux, list_length_z_cons; simpl.
+ omega.
+ - exploit (IHli b ofs f bb rs1 m_next' (State rs_next' m_next')); congruence || eauto.
+ + exploit is_tail_app_def; eauto.
+ intros (l3 & EQ); rewrite EQ.
+ exploit (is_tail_app_right _ (l3 ++ a::nil)).
+ rewrite <- app_assoc; simpl; eauto.
+ + constructor; auto.
+ rewrite ATPC_NEXT.
+ apply f_equal.
+ apply f_equal.
+ rewrite! list_length_z_cons; simpl.
+ omega.
+ + intros (s2' & LAST_STEPS & LAST_MATCHS).
+ eexists. split; eauto.
+ eapply plus_left'; eauto.
+Qed.
+
+Lemma exec_body_simulation_plus b ofs f bb rs m s2 rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_BODY: body bb <> nil)
+ (MATCHI: match_internal (list_length_z (header bb)) (State rs m) s2)
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ exists s2', plus Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ intros.
+ exploit exec_body_simulation_plus_gen; eauto.
+ - constructor.
+ - replace (list_length_z (header bb) + list_length_z (body bb) - list_length_z (body bb)) with (list_length_z (header bb)); auto.
+ omega.
+Qed.
+
+Lemma exec_body_simulation_star b ofs f bb rs m s2 rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (MATCHI: match_internal (list_length_z (header bb)) (State rs m) s2)
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ exists s2', star Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ intros.
+ destruct (body bb) eqn: Hbb.
+ - simpl in BODY. inv BODY.
+ eexists. split.
+ eapply star_refl; eauto.
+ assert (EQ: (size bb - Z.of_nat (length_opt (exit bb))) = list_length_z (header bb)).
+ { rewrite bblock_size_aux. rewrite Hbb; unfold list_length_z; simpl. omega. }
+ rewrite EQ; eauto.
+ - exploit exec_body_simulation_plus; congruence || eauto.
+ { rewrite Hbb; eauto. }
+ intros (s2' & PLUS & MATCHI').
+ eexists; split; eauto.
+ eapply plus_star; eauto.
+Qed.
+
+Lemma list_nth_z_range_exceeded A (l : list A) n:
+ n >= list_length_z l ->
+ list_nth_z l n = None.
+Proof.
+ intros N.
+ remember (list_nth_z l n) as opt eqn:H. symmetry in H.
+ destruct opt; auto.
+ exploit list_nth_z_range; eauto. omega.
+Qed.
+
+Lemma label_in_header_list lbl a:
+ is_label lbl a = true -> list_length_z (header a) <= 1 -> header a = lbl :: nil.
+Proof.
+ intros.
+ eapply is_label_correct_true in H.
+ destruct (header a).
+ - eapply in_nil in H. contradiction.
+ - rewrite list_length_z_cons in H0.
+ assert (list_length_z l0 >= 0) by eapply list_length_z_pos.
+ assert (list_length_z l0 = 0) by omega.
+ rewrite list_length_z_nat in H2.
+ assert (Datatypes.length l0 = 0%nat) by omega.
+ eapply length_zero_iff_nil in H3. subst.
+ unfold In in H. destruct H.
+ + subst; eauto.
+ + destruct H.
+Qed.
+
+Lemma no_label_in_basic_inst: forall a lbl x,
+ basic_to_instruction a = OK x -> Asm.is_label lbl x = false.
+Proof.
+ intros.
+ destruct a; simpl in *;
+ repeat destruct i; simpl in *;
+ try (try destruct_reg_inv; monadInv H; simpl in *; reflexivity).
+Qed.
+
+Lemma label_pos_body bdy: forall c1 c2 z ex lbl
+ (HUNF : unfold_body bdy = OK c2),
+ Asm.label_pos lbl (z + Z.of_nat ((Datatypes.length bdy) + length_opt ex)) c1 = Asm.label_pos lbl (z) ((c2 ++ unfold_exit ex) ++ c1).
+Proof.
+ induction bdy.
+ - intros. inversion HUNF. simpl in *.
+ destruct ex eqn:EQEX.
+ + simpl in *. unfold Asm.is_label. destruct c; simpl; try congruence.
+ destruct i; simpl; try congruence.
+ + simpl in *. ring_simplify (z + 0). auto.
+ - intros. inversion HUNF; clear HUNF. monadInv H0. simpl in *.
+ erewrite no_label_in_basic_inst; eauto. rewrite <- IHbdy; eauto.
+ erewrite Zpos_P_of_succ_nat.
+ apply f_equal2; auto. omega.
+Qed.
+
+Lemma asm_label_pos_header: forall z a x0 x1 lbl
+ (HUNF: unfold_body (body a) = OK x1),
+ Asm.label_pos lbl (z + size a) x0 =
+ Asm.label_pos lbl (z + list_length_z (header a)) ((x1 ++ unfold_exit (exit a)) ++ x0).
+Proof.
+ intros.
+ unfold size.
+ rewrite <- plus_assoc. rewrite Nat2Z.inj_add.
+ rewrite list_length_z_nat.
+ replace (z + (Z.of_nat (Datatypes.length (header a)) + Z.of_nat (Datatypes.length (body a) + length_opt (exit a)))) with (z + Z.of_nat (Datatypes.length (header a)) + Z.of_nat (Datatypes.length (body a) + length_opt (exit a))) by omega.
+ eapply (label_pos_body (body a) x0 x1 (z + Z.of_nat (Datatypes.length (header a))) (exit a) lbl). auto.
+Qed.
+
+Lemma header_size_cons_nil: forall (l0: label) (l1: list label)
+ (HSIZE: list_length_z (l0 :: l1) <= 1),
+ l1 = nil.
+Proof.
+ intros.
+ destruct l1; try congruence. rewrite !list_length_z_cons in HSIZE.
+ assert (list_length_z l1 >= 0) by eapply list_length_z_pos.
+ assert (list_length_z l1 + 1 + 1 >= 2) by omega.
+ assert (2 <= 1) by omega. contradiction H1. omega.
+Qed.
+
+(*Lemma unfold_label_not_nil: forall a lbl*)
+ (*(HIN: In lbl (header a)),*)
+ (*unfold_label (header a) <> nil.*)
+(*Proof.*)
+ (*intros. induction (header a).*)
+ (*- contradiction.*)
+ (*- destruct (peq lbl a0);*)
+ (*simpl; unfold not; intros; generalize nil_cons; intros;*)
+ (*specialize (H0 label a0 l); unfold not in H0; congruence.*)
+(*Qed.*)
+
+(*Lemma label_pos_in a: forall lbl z*)
+ (*(EQLBL: In lbl (header a)),*)
+ (*Asm.label_pos lbl z (unfold_label (header a)) = Some z.*)
+(*Proof.*)
+ (*intros.*)
+ (*induction (Asm.label_pos _ _ _) eqn:Hind.*)
+ (*- induction (unfold_label (header a)) eqn:Hunf.*)
+ (*+ eapply unfold_label_not_nil in EQLBL. congruence.*)
+ (*+ simpl in *. *)
+ (*destruct (Asm.is_label _ _) eqn:Hlbla.*)
+ (** symmetry. assumption.*)
+ (** apply IHl.*)
+
+ (*induction (header a).*)
+ (** apply in_nil in EQLBL. contradiction.*)
+ (** simpl in *.*)
+ (*- unfold Asm.label_pos.*)
+ (*destruct (Asm.is_label) eqn:EQis; try reflexivity.*)
+ (*destruct (peq lbl (PLabel a0)).*)
+
+Lemma label_pos_preserved_gen bbs: forall lbl c z
+ (HUNF: unfold bbs = OK c),
+ label_pos lbl z bbs = Asm.label_pos lbl z c.
+Proof.
+Admitted.
+(* induction bbs.
+ - intros. simpl in *. inversion HUNF. simpl. reflexivity.
+ - intros. simpl in *. monadInv HUNF. unfold unfold_bblock in EQ.
+ (*destruct (zle _ _); try congruence.*)
+ monadInv EQ.
+ destruct (is_label _ _) eqn:EQLBL.
+ erewrite <- is_label_correct_true in EQLBL.
+ + induction (Asm.label_pos) eqn:Hind.
+ *
+ + induction (header a) eqn:Hhead.
+ * apply in_nil in EQLBL. contradiction.
+ * simpl in *. destruct peq; try reflexivity.
+ erewrite IHl.
+ erewrite label_in_header_list; eauto.
+ simpl in *. destruct (peq lbl lbl); try congruence.
+ + erewrite IHbbs; eauto.
+ rewrite (asm_label_pos_header z a x0 x1 lbl); auto.
+ unfold is_label in *.
+ destruct (header a).
+ * replace (z + list_length_z (@nil label)) with (z); eauto.
+ unfold list_length_z. simpl. omega.
+ * eapply header_size_cons_nil in l as HL1.
+ subst. simpl in *. destruct (in_dec _ _); try congruence.
+ simpl in *.
+ destruct (peq _ _); try intuition congruence.
+Qed.*)
+
+Lemma label_pos_preserved f lbl z tf: forall
+ (FINDF: transf_function f = OK tf),
+ label_pos lbl z (fn_blocks f) = Asm.label_pos lbl z (Asm.fn_code tf).
+Proof.
+ intros.
+ eapply label_pos_preserved_gen.
+ unfold transf_function in FINDF. monadInv FINDF.
+ destruct zlt; try congruence. inversion EQ0. eauto.
+Qed.
+
+Lemma goto_label_preserved bb rs1 m1 rs1' m1' rs2 m2 lbl f tf v: forall
+ (FINDF: transf_function f = OK tf)
+ (BOUNDED: size bb <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2))
+ (HGOTO: goto_label f lbl (incrPC v rs1) m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.goto_label tf lbl rs2 m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold goto_label, Asm.goto_label in *.
+ rewrite <- (label_pos_preserved f); auto.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ destruct label_pos; next_stuck_cong.
+ destruct (incrPC v rs1 PC) eqn:INCRPC; next_stuck_cong.
+ inversion HGOTO; auto. repeat (econstructor; eauto).
+ rewrite <- EQPC.
+ unfold incrPC in *.
+ rewrite !Pregmap.gss in *.
+ destruct (rs1 PC) eqn:EQRS1; simpl in *; try congruence.
+ replace (rs2 # PC <- (Vptr b0 (Ptrofs.repr z))) with ((rs1 # PC <- (Vptr b0 (Ptrofs.add i0 v))) # PC <- (Vptr b (Ptrofs.repr z))); auto.
+ eapply functional_extensionality. intros.
+ destruct (PregEq.eq x PC); subst.
+ rewrite !Pregmap.gss. congruence.
+ rewrite !Pregmap.gso; auto.
+Qed.
+
+Lemma next_inst_incr_pc_preserved bb rs1 m1 rs1' m1' rs2 m2 f tf: forall
+ (FINDF: transf_function f = OK tf)
+ (BOUNDED: size bb <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2))
+ (NEXT: Next (incrPC (Ptrofs.repr (size bb)) rs1) m2 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem),
+ Next (Asm.nextinstr rs2) m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros; simpl in *; unfold incrPC in NEXT;
+ inv_matchi;
+ assert (size bb >= 1) by eapply bblock_size_pos;
+ assert (0 <= size bb - 1 <= Ptrofs.max_unsigned) by omega;
+ inversion NEXT; subst;
+ eexists; eexists; split; eauto.
+ assert (rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))) = Asm.nextinstr rs2). {
+ unfold Pregmap.set. apply functional_extensionality.
+ intros x. destruct (PregEq.eq x PC).
+ -- unfold Asm.nextinstr. rewrite <- AGPC.
+ rewrite Val.offset_ptr_assoc. rewrite Ptrofs.add_unsigned.
+ rewrite (Ptrofs.unsigned_repr (size bb - 1)); try omega.
+ rewrite Ptrofs.unsigned_one.
+ replace (size bb - 1 + 1) with (size bb) by omega.
+ rewrite e. rewrite Pregmap.gss.
+ reflexivity.
+ -- eapply nextinstr_agree_but_pc; eauto. }
+ rewrite H1. econstructor.
+Qed.
+
+Lemma pc_reg_overwrite: forall (r: ireg) rs1 m1 rs2 m2 bb
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2)),
+ rs2 # PC <- (rs2 r) =
+ (rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb)))) # PC <-
+ (rs1 r).
+Proof.
+ intros.
+ unfold Pregmap.set; apply functional_extensionality.
+ intros x; destruct (PregEq.eq x PC) as [X | X]; try discriminate; inv_matchi.
+Qed.
+
+Lemma exec_cfi_simulation:
+ forall bb f tf rs1 m1 rs1' m1' rs2 m2 cfi
+ (SIZE: size bb <= Ptrofs.max_unsigned)
+ (FINDF: transf_function f = OK tf)
+ (* Warning: Asmblock's PC is assumed to be already pointing on the next instruction ! *)
+ (CFI: exec_cfi ge f cfi (incrPC (Ptrofs.repr (size bb)) rs1) m1 = Next rs1' m1')
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2)),
+ exists rs2' m2', Asm.exec_instr tge tf (cf_instruction_to_instruction cfi)
+ rs2 m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ assert (BBPOS: size bb >= 1) by eapply bblock_size_pos.
+ destruct cfi; inv CFI; simpl.
+ - (* Pb *)
+ exploit goto_label_preserved; eauto.
+ - (* Pbc *)
+ inv_matchi.
+ unfold eval_testcond in *. destruct c;
+ erewrite !incrPC_agree_but_pc in H0; try rewrite <- !AG; try congruence.
+ all:
+ destruct_reg_size;
+ try destruct b eqn:EQB.
+ 1,4,7,10,13,16,19,22,25,28,31,34:
+ exploit goto_label_preserved; eauto.
+ 1,3,5,7,9,11,13,15,17,19,21,23:
+ exploit next_inst_incr_pc_preserved; eauto.
+ all: repeat (econstructor; eauto).
+ - (* Pbl *)
+ eexists; eexists; split; eauto.
+ assert ( ((incrPC (Ptrofs.repr (size bb)) rs1) # X30 <- (incrPC (Ptrofs.repr (size bb)) rs1 PC))
+ # PC <- (Genv.symbol_address ge id Ptrofs.zero)
+ = (rs2 # X30 <- (Val.offset_ptr (rs2 PC) Ptrofs.one))
+ # PC <- (Genv.symbol_address tge id Ptrofs.zero)
+ ) as EQRS. {
+ unfold incrPC. unfold Pregmap.set. simpl. apply functional_extensionality.
+ intros x. destruct (PregEq.eq x PC).
+ * rewrite symbol_addresses_preserved. reflexivity.
+ * destruct (PregEq.eq x X30).
+ -- inv MATCHI. rewrite <- AGPC. rewrite Val.offset_ptr_assoc.
+ unfold Ptrofs.add, Ptrofs.one. repeat (rewrite Ptrofs.unsigned_repr); try omega.
+ replace (size bb - 1 + 1) with (size bb) by omega. reflexivity.
+ -- inv MATCHI; rewrite AG; try assumption; reflexivity.
+ } rewrite EQRS; inv MATCHI; reflexivity.
+ - (* Pbs *)
+ eexists; eexists; split; eauto.
+ assert ( (incrPC (Ptrofs.repr (size bb)) rs1) # PC <-
+ (Genv.symbol_address ge id Ptrofs.zero)
+ = rs2 # PC <- (Genv.symbol_address tge id Ptrofs.zero)
+ ) as EQRS. {
+ unfold incrPC, Pregmap.set. rewrite symbol_addresses_preserved. inv MATCHI.
+ apply functional_extensionality. intros x. destruct (PregEq.eq x PC); auto.
+ } rewrite EQRS; inv MATCHI; reflexivity.
+ - (* Pblr *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gss. rewrite Pregmap.gso; try discriminate.
+ assert ( (rs2 # X30 <- (Val.offset_ptr (rs2 PC) Ptrofs.one)) # PC <- (rs2 r)
+ = ((rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))))
+ # X30 <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))))
+ # PC <- (rs1 r)
+ ) as EQRS. {
+ unfold Pregmap.set. apply functional_extensionality.
+ intros x; destruct (PregEq.eq x PC) as [X | X].
+ - inv_matchi; rewrite AG; auto.
+ - destruct (PregEq.eq x X30) as [X' | X'].
+ + inversion MATCHI; subst. rewrite <- AGPC.
+ rewrite Val.offset_ptr_assoc. unfold Ptrofs.one.
+ rewrite Ptrofs.add_unsigned. rewrite Ptrofs.unsigned_repr; try omega. rewrite Ptrofs.unsigned_repr; try omega.
+ rewrite Z.sub_add; reflexivity.
+ + inv_matchi.
+ } rewrite EQRS. inv_matchi.
+ - (* Pbr *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gso; try discriminate.
+ rewrite (pc_reg_overwrite r rs1 m1' rs2 m2 bb); auto.
+ inv_matchi.
+ - (* Pret *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gso; try discriminate.
+ rewrite (pc_reg_overwrite r rs1 m1' rs2 m2 bb); auto.
+ inv_matchi.
+ - (* Pcbnz *)
+ inv_matchi.
+ unfold eval_neg_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testzero; next_stuck_cong.
+ destruct b.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ * exploit goto_label_preserved; eauto.
+ - (* Pcbz *)
+ inv_matchi.
+ unfold eval_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testzero; next_stuck_cong.
+ destruct b.
+ * exploit goto_label_preserved; eauto.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ - (* Ptbnbz *)
+ inv_matchi.
+ unfold eval_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testbit; next_stuck_cong.
+ destruct b.
+ * exploit goto_label_preserved; eauto.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ - (* Ptbz *)
+ inv_matchi.
+ unfold eval_neg_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testbit; next_stuck_cong.
+ destruct b.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ * exploit goto_label_preserved; eauto.
+ - (* Pbtbl *)
+ assert (rs2 # X16 <- Vundef r1 = (incrPC (Ptrofs.repr (size bb)) rs1) # X16 <- Vundef r1)
+ as EQUNDEFX16. {
+ unfold incrPC, Pregmap.set.
+ destruct (PregEq.eq r1 X16) as [X16 | X16]; auto.
+ destruct (PregEq.eq r1 PC) as [PC' | PC']; try discriminate.
+ inv MATCHI; rewrite AG; auto.
+ } rewrite <- EQUNDEFX16 in H0.
+ destruct_reg_inv; next_stuck_cong.
+ unfold goto_label, Asm.goto_label in *.
+ rewrite <- (label_pos_preserved f); auto.
+ inversion MATCHI; subst.
+ destruct label_pos; next_stuck_cong.
+ destruct (((incrPC (Ptrofs.repr (size bb)) rs1) # X16 <- Vundef) # X17 <- Vundef PC) eqn:INCRPC; next_stuck_cong.
+ inversion H0; auto. repeat (econstructor; eauto).
+ rewrite !Pregmap.gso; try congruence.
+ rewrite <- AGPC.
+ unfold incrPC in *.
+ destruct (rs1 PC) eqn:EQRS1; simpl in *; try discriminate.
+ replace (((rs2 # X16 <- Vundef) # X17 <- Vundef) # PC <- (Vptr b0 (Ptrofs.repr z))) with
+ ((((rs1 # PC <- (Vptr b0 (Ptrofs.add i1 (Ptrofs.repr (size bb))))) # X16 <-
+ Vundef) # X17 <- Vundef) # PC <- (Vptr b (Ptrofs.repr z))); auto.
+ eapply functional_extensionality; intros x.
+ destruct (PregEq.eq x PC); subst.
+ + rewrite Pregmap.gso in INCRPC; try congruence.
+ rewrite Pregmap.gso in INCRPC; try congruence.
+ rewrite Pregmap.gss in INCRPC.
+ rewrite !Pregmap.gss in *; congruence.
+ + rewrite Pregmap.gso; auto.
+ rewrite (Pregmap.gso (i := x) (j := PC)); auto.
+ destruct (PregEq.eq x X17); subst.
+ * rewrite !Pregmap.gss; auto.
+ * rewrite !(Pregmap.gso (i := x) (j:= X17)); auto. destruct (PregEq.eq x X16); subst.
+ -- rewrite !Pregmap.gss; auto.
+ -- rewrite !Pregmap.gso; auto.
+Qed.
+
+Lemma last_instruction_cannot_be_label bb:
+ list_nth_z (header bb) (size bb - 1) = None.
+Proof.
+ assert (list_length_z (header bb) <= size bb - 1). {
+ rewrite bblock_size_aux. generalize (bblock_size_aux_pos bb). omega.
}
-
- (* Mload notrap1 *)
- inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
-
-- (* Mload notrap *)
- inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
-
-- (* Mload notrap *)
- inv AT. simpl in *. unfold bind in *. destruct (transl_code _ _ _) in *; discriminate.
-
-- (* Mstore *)
- assert (Op.eval_addressing tge sp addr (map rs args) = Some a).
- { rewrite <- H. apply eval_addressing_preserved. exact symbols_preserved. }
- exploit eval_addressing_lessdef. eapply preg_vals; eauto. eexact H1.
- intros [a' [A B]]. rewrite (sp_val _ _ _ AG) in A.
- assert (Val.lessdef (rs src) (rs0 (preg_of src))) by (eapply preg_val; eauto).
- exploit Mem.storev_extends; eauto. intros [m2' [C D]].
- left; eapply exec_straight_steps; eauto.
- intros. simpl in TR. exploit transl_store_correct; eauto. intros [rs2 [P [Q R]]].
- exists rs2; split. eauto.
- split. eapply agree_undef_regs; eauto with asmgen.
- split. simpl; congruence.
- rewrite R. assumption.
-
-- (* Mcall *)
- assert (f0 = f) by congruence. subst f0.
- inv AT.
- assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
- { eapply transf_function_no_overflow; eauto. }
- destruct ros as [rf|fid]; simpl in H; monadInv H5.
-+ (* Indirect call *)
- assert (rs rf = Vptr f' Ptrofs.zero).
- { destruct (rs rf); try discriminate.
- revert H; predSpec Ptrofs.eq Ptrofs.eq_spec i Ptrofs.zero; intros; congruence. }
- assert (rs0 x0 = Vptr f' Ptrofs.zero).
- { exploit ireg_val; eauto. rewrite H5; intros LD; inv LD; auto. }
- generalize (code_tail_next_int _ _ _ _ NOOV H6). intro CT1.
- assert (TCA: transl_code_at_pc ge (Vptr fb (Ptrofs.add ofs Ptrofs.one)) fb f c false tf x).
- { econstructor; eauto. }
- exploit return_address_offset_correct; eauto. intros; subst ra.
- left; econstructor; split.
- apply plus_one. eapply exec_step_internal. Simpl. rewrite <- H2; simpl; eauto.
- eapply functions_transl; eauto. eapply find_instr_tail; eauto.
- simpl. eauto.
- econstructor; eauto.
- econstructor; eauto.
- eapply agree_sp_def; eauto.
- simpl. eapply agree_exten; eauto. intros. Simpl.
- Simpl. rewrite <- H2. auto.
-+ (* Direct call *)
- generalize (code_tail_next_int _ _ _ _ NOOV H6). intro CT1.
- assert (TCA: transl_code_at_pc ge (Vptr fb (Ptrofs.add ofs Ptrofs.one)) fb f c false tf x).
- econstructor; eauto.
- exploit return_address_offset_correct; eauto. intros; subst ra.
- left; econstructor; split.
- apply plus_one. eapply exec_step_internal. eauto.
- eapply functions_transl; eauto. eapply find_instr_tail; eauto.
- simpl. unfold Genv.symbol_address. rewrite symbols_preserved. rewrite H. eauto.
- econstructor; eauto.
- econstructor; eauto.
- eapply agree_sp_def; eauto.
- simpl. eapply agree_exten; eauto. intros. Simpl.
- Simpl. rewrite <- H2. auto.
-
-- (* Mtailcall *)
- assert (f0 = f) by congruence. subst f0.
- inversion AT; subst.
- assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
- { eapply transf_function_no_overflow; eauto. }
- exploit Mem.loadv_extends. eauto. eexact H1. auto. simpl. intros [parent' [A B]].
- destruct ros as [rf|fid]; simpl in H; monadInv H7.
-+ (* Indirect call *)
- assert (rs rf = Vptr f' Ptrofs.zero).
- { destruct (rs rf); try discriminate.
- revert H; predSpec Ptrofs.eq Ptrofs.eq_spec i Ptrofs.zero; intros; congruence. }
- assert (rs0 x0 = Vptr f' Ptrofs.zero).
- { exploit ireg_val; eauto. rewrite H7; intros LD; inv LD; auto. }
- exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
- exploit exec_straight_steps_2; eauto using functions_transl.
- intros (ofs' & P & Q).
- left; econstructor; split.
- (* execution *)
- eapply plus_right'. eapply exec_straight_exec; eauto.
- econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
- simpl. reflexivity.
- traceEq.
- (* match states *)
- econstructor; eauto.
- apply agree_set_other; auto with asmgen.
- Simpl. rewrite Z by (rewrite <- (ireg_of_eq _ _ EQ1); eauto with asmgen). assumption.
-+ (* Direct call *)
- exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
- exploit exec_straight_steps_2; eauto using functions_transl.
- intros (ofs' & P & Q).
- left; econstructor; split.
- (* execution *)
- eapply plus_right'. eapply exec_straight_exec; eauto.
- econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
- simpl. reflexivity.
- traceEq.
- (* match states *)
- econstructor; eauto.
- apply agree_set_other; auto with asmgen.
- Simpl. unfold Genv.symbol_address. rewrite symbols_preserved. rewrite H. auto.
-
-- (* Mbuiltin *)
- inv AT. monadInv H4.
- exploit functions_transl; eauto. intro FN.
- generalize (transf_function_no_overflow _ _ H3); intro NOOV.
- exploit builtin_args_match; eauto. intros [vargs' [P Q]].
- exploit external_call_mem_extends; eauto.
- intros [vres' [m2' [A [B [C D]]]]].
- left. econstructor; split. apply plus_one.
- eapply exec_step_builtin. eauto. eauto.
- eapply find_instr_tail; eauto.
- erewrite <- sp_val by eauto.
- eapply eval_builtin_args_preserved with (ge1 := ge); eauto. exact symbols_preserved.
- eapply external_call_symbols_preserved; eauto. apply senv_preserved.
- eauto.
- econstructor; eauto.
- instantiate (2 := tf); instantiate (1 := x).
- unfold nextinstr. rewrite Pregmap.gss.
- rewrite set_res_other. rewrite undef_regs_other_2.
- rewrite <- H1. simpl. econstructor; eauto.
- eapply code_tail_next_int; eauto.
- rewrite preg_notin_charact. intros. auto with asmgen.
- auto with asmgen.
- apply agree_nextinstr. eapply agree_set_res; auto.
- eapply agree_undef_regs; eauto. intros. rewrite undef_regs_other_2; auto.
- congruence.
-
- Simpl.
- rewrite set_res_other by trivial.
- rewrite undef_regs_other.
- assumption.
- intro.
- rewrite in_map_iff.
- intros (x0 & PREG & IN).
- subst r'.
- intro.
- apply (preg_of_not_RA x0).
- congruence.
-
-- (* Mgoto *)
- assert (f0 = f) by congruence. subst f0.
- inv AT. monadInv H4.
- exploit find_label_goto_label; eauto. intros [tc' [rs' [GOTO [AT2 INV]]]].
- left; exists (State rs' m'); split.
- apply plus_one. econstructor; eauto.
- eapply functions_transl; eauto.
- eapply find_instr_tail; eauto.
- simpl; eauto.
- econstructor; eauto.
- eapply agree_exten; eauto with asmgen.
- congruence.
-
- rewrite INV by congruence.
- assumption.
-
-- (* Mcond true *)
- assert (f0 = f) by congruence. subst f0.
- exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
- left; eapply exec_straight_opt_steps_goto; eauto.
- intros. simpl in TR.
- exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
- exists jmp; exists k; exists rs'.
- split. eexact A.
- split. apply agree_exten with rs0; auto with asmgen.
- split.
- exact B.
- rewrite D. exact LEAF.
-
-- (* Mcond false *)
- exploit eval_condition_lessdef. eapply preg_vals; eauto. eauto. eauto. intros EC.
- left; eapply exec_straight_steps; eauto. intros. simpl in TR.
- exploit transl_cond_branch_correct; eauto. intros (rs' & jmp & A & B & C & D).
- econstructor; split.
- eapply exec_straight_opt_right. eexact A. apply exec_straight_one. eexact B. auto.
- split. apply agree_exten with rs0; auto. intros. Simpl.
- split.
- simpl; congruence.
- Simpl. rewrite D.
- exact LEAF.
-
-- (* Mjumptable *)
- assert (f0 = f) by congruence. subst f0.
- inv AT. monadInv H6.
- exploit functions_transl; eauto. intro FN.
- generalize (transf_function_no_overflow _ _ H5); intro NOOV.
- exploit find_label_goto_label. eauto. eauto.
- instantiate (2 := rs0#X16 <- Vundef #X17 <- Vundef).
- Simpl. eauto.
- eauto.
- intros [tc' [rs' [A [B C]]]].
- exploit ireg_val; eauto. rewrite H. intros LD; inv LD.
- left; econstructor; split.
- apply plus_one. econstructor; eauto.
- eapply find_instr_tail; eauto.
- simpl. Simpl. rewrite <- H9. unfold Mach.label in H0; unfold label; rewrite H0. eexact A.
- econstructor; eauto.
- eapply agree_undef_regs; eauto.
- simpl. intros. rewrite C; auto with asmgen. Simpl.
- congruence.
-
- rewrite C by congruence.
- repeat rewrite Pregmap.gso by congruence.
- assumption.
-
-- (* Mreturn *)
- assert (f0 = f) by congruence. subst f0.
- inversion AT; subst. simpl in H6; monadInv H6.
- assert (NOOV: list_length_z tf.(fn_code) <= Ptrofs.max_unsigned).
- eapply transf_function_no_overflow; eauto.
- exploit make_epilogue_correct; eauto. intros (rs1 & m1 & U & V & W & X & Y & Z).
- exploit exec_straight_steps_2; eauto using functions_transl.
- intros (ofs' & P & Q).
- left; econstructor; split.
- (* execution *)
- eapply plus_right'. eapply exec_straight_exec; eauto.
- econstructor. eexact P. eapply functions_transl; eauto. eapply find_instr_tail. eexact Q.
- simpl. reflexivity.
- traceEq.
- (* match states *)
- econstructor; eauto.
- apply agree_set_other; auto with asmgen.
-
-- (* internal function *)
-
- exploit functions_translated; eauto. intros [tf [A B]]. monadInv B.
- generalize EQ; intros EQ'. monadInv EQ'.
- destruct (zlt Ptrofs.max_unsigned (list_length_z x0.(fn_code))); inversion EQ1. clear EQ1. subst x0.
- unfold store_stack in *.
- exploit Mem.alloc_extends. eauto. eauto. apply Z.le_refl. apply Z.le_refl.
- intros [m1' [C D]].
- exploit Mem.storev_extends. eexact D. eexact H1. eauto. eauto.
- intros [m2' [F G]].
- simpl chunk_of_type in F.
- exploit Mem.storev_extends. eexact G. eexact H2. eauto. eauto.
- intros [m3' [P Q]].
- change (chunk_of_type Tptr) with Mint64 in *.
- (* Execution of function prologue *)
- monadInv EQ0. rewrite transl_code'_transl_code in EQ1.
- set (tfbody := Pallocframe (fn_stacksize f) (fn_link_ofs f) ::
- storeptr RA XSP (fn_retaddr_ofs f) x0) in *.
- set (tf := {| fn_sig := Mach.fn_sig f; fn_code := tfbody |}) in *.
- set (rs2 := nextinstr (rs0#X29 <- (parent_sp s) #SP <- sp #X16 <- Vundef)).
- exploit (storeptr_correct tge tf XSP (fn_retaddr_ofs f) RA x0 m2' m3' rs2).
- simpl preg_of_iregsp. change (rs2 X30) with (rs0 X30). rewrite ATLR.
- change (rs2 X2) with sp. eexact P.
- simpl; congruence. congruence.
- intros (rs3 & U & V & W).
- assert (EXEC_PROLOGUE:
- exec_straight tge tf
- tf.(fn_code) rs0 m'
- x0 rs3 m3').
- { change (fn_code tf) with tfbody; unfold tfbody.
- apply exec_straight_step with rs2 m2'.
- unfold exec_instr. rewrite C. fold sp.
- rewrite <- (sp_val _ _ _ AG). rewrite F. reflexivity.
- reflexivity.
- eexact U. }
- exploit exec_straight_steps_2; eauto using functions_transl. omega. constructor.
- intros (ofs' & X & Y).
- left; exists (State rs3 m3'); split.
- eapply exec_straight_steps_1; eauto. omega. constructor.
- econstructor; eauto.
- rewrite X; econstructor; eauto.
- apply agree_exten with rs2; eauto with asmgen.
- unfold rs2.
- apply agree_nextinstr. apply agree_set_other; auto with asmgen.
- apply agree_change_sp with (parent_sp s).
- apply agree_undef_regs with rs0. auto.
-Local Transparent destroyed_at_function_entry. simpl.
- simpl; intros; Simpl.
- unfold sp; congruence.
- intros. rewrite V by auto with asmgen. reflexivity.
-
- rewrite W.
- unfold rs2.
- Simpl.
-
-- (* external function *)
- exploit functions_translated; eauto.
- intros [tf [A B]]. simpl in B. inv B.
- exploit extcall_arguments_match; eauto.
- intros [args' [C D]].
- exploit external_call_mem_extends; eauto.
- intros [res' [m2' [P [Q [R S]]]]].
- left; econstructor; split.
- apply plus_one. eapply exec_step_external; eauto.
- eapply external_call_symbols_preserved; eauto. apply senv_preserved.
- econstructor; eauto.
- unfold loc_external_result. apply agree_set_other; auto. apply agree_set_pair; auto.
- apply agree_undef_caller_save_regs; auto.
-
-- (* return *)
- inv STACKS. simpl in *.
- right. split. omega. split. auto.
- rewrite <- ATPC in H5.
- econstructor; eauto. congruence.
- inv WF.
- inv STACK.
- inv H1.
- congruence.
+ remember (list_nth_z (header bb) (size bb - 1)) as label_opt; destruct label_opt; auto;
+ exploit list_nth_z_range; eauto; omega.
Qed.
-Lemma transf_initial_states:
- forall st1, Mach.initial_state prog st1 ->
- exists st2, Asm.initial_state tprog st2 /\ match_states st1 st2.
+Lemma pc_ptr_exec_step: forall ofs bb b rs m _rs _m
+ (ATPC : rs PC = Vptr b ofs)
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |}),
+ _rs PC = Vptr b (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))).
Proof.
- intros. inversion H. unfold ge0 in *.
- econstructor; split.
- econstructor.
- eapply (Genv.init_mem_transf_partial TRANSF); eauto.
- replace (Genv.symbol_address (Genv.globalenv tprog) (prog_main tprog) Ptrofs.zero)
- with (Vptr fb Ptrofs.zero).
- econstructor; eauto.
- constructor.
- apply Mem.extends_refl.
- split. auto. simpl. unfold Vnullptr; destruct Archi.ptr64; congruence.
- intros. rewrite Regmap.gi. auto.
- unfold Genv.symbol_address.
- rewrite (match_program_main TRANSF).
- rewrite symbols_preserved.
- unfold ge; rewrite H1. auto.
+ intros; inv MATCHI. rewrite <- AGPC; rewrite ATPC; unfold Val.offset_ptr; eauto.
Qed.
-Lemma transf_final_states:
- forall st1 st2 r,
- match_states st1 st2 -> Mach.final_state st1 r -> Asm.final_state st2 r.
+Lemma find_instr_ofs_somei: forall ofs bb f tc asmi rs m _rs _m
+ (BOUNDOFS : Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ (FIND_INSTR : Asm.find_instr (Ptrofs.unsigned ofs + (size bb - 1)) tc =
+ Some (asmi))
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |}),
+ Asm.find_instr (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))))
+ (Asm.fn_code {| Asm.fn_sig := fn_sig f; Asm.fn_code := tc |}) =
+ Some (asmi).
Proof.
- intros. inv H0. inv H. constructor. assumption.
- compute in H1. inv H1.
- generalize (preg_val _ _ _ R0 AG). rewrite H2. intros LD; inv LD. auto.
+ intros; simpl.
+ replace (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))))
+ with (Ptrofs.unsigned ofs + (size bb - 1)); try assumption.
+ generalize (bblock_size_pos bb); generalize (Ptrofs.unsigned_range_2 ofs); intros.
+ unfold Ptrofs.add.
+ rewrite Ptrofs.unsigned_repr. rewrite Ptrofs.unsigned_repr; try omega.
+ rewrite Ptrofs.unsigned_repr; omega.
Qed.
-Theorem transf_program_correct:
- forward_simulation (Mach.semantics return_address_offset prog) (Asm.semantics tprog).
+Lemma eval_builtin_arg_match: forall rs _m _rs a1 b1
+ (AG : forall r : preg, r <> PC -> rs r = _rs r)
+ (EVAL : eval_builtin_arg tge (fun r : dreg => rs r) (rs SP) _m a1 b1),
+ eval_builtin_arg tge _rs (_rs SP) _m (map_builtin_arg DR a1) b1.
+Proof.
+ intros; induction EVAL; simpl in *; try rewrite AG; try rewrite AG in EVAL; try discriminate; try congruence; eauto with barg.
+ econstructor. rewrite <- AG; try discriminate; auto.
+Qed.
+
+Lemma eval_builtin_args_match: forall bb rs m _rs _m args vargs
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |})
+ (EVAL : eval_builtin_args tge (fun r : dreg => rs r) (rs SP) m args vargs),
+ eval_builtin_args tge _rs (_rs SP) _m (map (map_builtin_arg DR) args) vargs.
+Proof.
+ intros; inv MATCHI.
+ induction EVAL; subst.
+ - econstructor.
+ - econstructor.
+ + eapply eval_builtin_arg_match; eauto.
+ + eauto.
+Qed.
+
+Lemma pc_both_sides: forall (rs _rs: regset) v
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ rs # PC <- v = _rs # PC <- v.
+Proof.
+ intros; unfold Pregmap.set; apply functional_extensionality; intros y.
+ destruct (PregEq.eq y PC); try rewrite AG; eauto.
+Qed.
+
+Lemma set_buitin_res_sym res: forall vres rs _rs r
+ (NPC: r <> PC)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ set_res res vres rs r = set_res res vres _rs r.
+Proof.
+ induction res; simpl; intros; unfold Pregmap.set; try rewrite AG; eauto.
+Qed.
+
+Lemma set_builtin_res_dont_move_pc_gen res: forall vres rs _rs v1 v2
+ (HV: v1 = v2)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ (set_res res vres rs) # PC <- v1 =
+ (set_res res vres _rs) # PC <- v2.
+Proof.
+ intros. rewrite HV. generalize res vres rs _rs AG v2.
+ clear res vres rs _rs AG v1 v2 HV.
+ induction res.
+ - simpl; intros. apply pc_both_sides; intros.
+ unfold Pregmap.set; try rewrite AG; eauto.
+ - simpl; intros; apply pc_both_sides; eauto.
+ - simpl; intros.
+ erewrite IHres2; eauto; intros.
+ eapply set_buitin_res_sym; eauto.
+Qed.
+
+Lemma set_builtin_map_not_pc (res: builtin_res dreg): forall vres rs,
+ set_res (map_builtin_res DR res) vres rs PC = rs PC.
+Proof.
+ induction res.
+ - intros; simpl. unfold Pregmap.set. destruct (PregEq.eq PC x); try congruence.
+ - intros; simpl; congruence.
+ - intros; simpl in *. rewrite IHres2. rewrite IHres1. reflexivity.
+Qed.
+
+Lemma undef_reg_preserved (rl: list mreg): forall rs _rs r
+ (NPC: r <> PC)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ undef_regs (map preg_of rl) rs r = undef_regs (map preg_of rl) _rs r.
+Proof.
+ induction rl.
+ - simpl; auto.
+ - simpl; intros. erewrite IHrl; eauto.
+ intros. unfold Pregmap.set. destruct (PregEq.eq r0 (preg_of a)); try rewrite AG; eauto.
+Qed.
+
+Lemma undef_regs_other:
+ forall r rl rs,
+ (forall r', In r' rl -> r <> r') ->
+ undef_regs rl rs r = rs r.
Proof.
- eapply forward_simulation_star with (measure := measure)
- (match_states := fun S1 S2 => match_states S1 S2 /\ wf_state ge S1).
+ induction rl; simpl; intros. auto.
+ rewrite IHrl by auto. rewrite Pregmap.gso; auto.
+Qed.
+
+Fixpoint preg_notin (r: preg) (rl: list mreg) : Prop :=
+ match rl with
+ | nil => True
+ | r1 :: nil => r <> preg_of r1
+ | r1 :: rl => r <> preg_of r1 /\ preg_notin r rl
+ end.
+
+Remark preg_notin_charact:
+ forall r rl,
+ preg_notin r rl <-> (forall mr, In mr rl -> r <> preg_of mr).
+Proof.
+ induction rl; simpl; intros.
+ tauto.
+ destruct rl.
+ simpl. split. intros. intuition congruence. auto.
+ rewrite IHrl. split.
+ intros [A B]. intros. destruct H. congruence. auto.
+ auto.
+Qed.
+
+Lemma undef_regs_other_2:
+ forall r rl rs,
+ preg_notin r rl ->
+ undef_regs (map preg_of rl) rs r = rs r.
+Proof.
+ intros. apply undef_regs_other. intros.
+ exploit list_in_map_inv; eauto. intros [mr [A B]]. subst.
+ rewrite preg_notin_charact in H. auto.
+Qed.
+
+Lemma exec_exit_simulation_plus b ofs f bb s2 t rs m rs' m': forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_EXIT: exit bb <> None)
+ (MATCHI: match_internal (size bb - Z.of_nat (length_opt (exit bb))) (State rs m) s2)
+ (EXIT: exec_exit ge f (Ptrofs.repr (size bb)) rs m (exit bb) t rs' m')
+ (ATPC: rs PC = Vptr b ofs),
+ plus Asm.step tge s2 t (State rs' m').
+Proof.
+ intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+
+ exploit (find_instr_bblock (size bb - 1)); eauto.
+ { generalize (bblock_size_pos bb). omega. }
+ intros (i' & NTH & FIND_INSTR).
+
+ inv NTH.
+ + rewrite last_instruction_cannot_be_label in *. discriminate.
+ + destruct (exit bb) as [ctrl |] eqn:NEMPTY_EXIT'. 2: { contradiction. }
+ rewrite bblock_size_aux in *. rewrite NEMPTY_EXIT' in *. simpl in *.
+ (* XXX: Is there a better way to simplify this expression i.e. automatically? *)
+ replace (list_length_z (header bb) + list_length_z (body bb) + 1 - 1 -
+ list_length_z (header bb)) with (list_length_z (body bb)) in H by omega.
+ rewrite list_nth_z_range_exceeded in H; try omega. discriminate.
+ + assert (Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned). {
+ eapply size_of_blocks_bounds; eauto.
+ }
+ assert (size bb <= Ptrofs.max_unsigned). { generalize (Ptrofs.unsigned_range_2 ofs); omega. }
+ destruct cfi.
+ * (* control flow instruction *)
+ destruct s2.
+ rewrite H in EXIT. (* exit bb is a cfi *)
+ inv EXIT.
+ rewrite H in MATCHI. simpl in MATCHI.
+ exploit internal_functions_translated; eauto.
+ rewrite FINDtf.
+ intros (tf & FINDtf' & TRANSf). inversion FINDtf'; subst; clear FINDtf'.
+ exploit exec_cfi_simulation; eauto.
+ (* extract exec_cfi_simulation's conclusion as separate hypotheses *)
+ intros (rs2' & m2' & EXECI & MATCHS); rewrite MATCHS.
+ apply plus_one.
+ eapply Asm.exec_step_internal; eauto.
+ - eapply pc_ptr_exec_step; eauto.
+ - eapply find_instr_ofs_somei; eauto.
+ * (* builtin *)
+ destruct s2.
+ rewrite H in EXIT.
+ rewrite H in MATCHI. simpl in MATCHI.
+ simpl in FIND_INSTR.
+ inversion EXIT.
+ apply plus_one.
+ eapply external_call_symbols_preserved in H10; try (apply senv_preserved).
+ eapply eval_builtin_args_preserved in H6; try (apply symbols_preserved).
+ eapply Asm.exec_step_builtin; eauto.
+ - eapply pc_ptr_exec_step; eauto.
+ - eapply find_instr_ofs_somei; eauto.
+ - eapply eval_builtin_args_match; eauto.
+ - inv MATCHI; eauto.
+ - inv MATCHI.
+ unfold Asm.nextinstr, incrPC.
+ assert (HPC: Val.offset_ptr (rs PC) (Ptrofs.repr (size bb))
+ = Val.offset_ptr (_rs PC) Ptrofs.one).
+ { rewrite <- AGPC. rewrite ATPC. unfold Val.offset_ptr.
+ rewrite Ptrofs.add_assoc. unfold Ptrofs.add.
+ assert (BBPOS: size bb >= 1) by eapply bblock_size_pos.
+ rewrite (Ptrofs.unsigned_repr (size bb - 1)); try omega.
+ rewrite Ptrofs.unsigned_one.
+ replace (size bb - 1 + 1) with (size bb) by omega.
+ reflexivity. }
+ apply set_builtin_res_dont_move_pc_gen.
+ -- erewrite !set_builtin_map_not_pc.
+ erewrite !undef_regs_other_2.
+ rewrite HPC; auto. all: rewrite preg_notin_charact; intros; try discriminate.
+ -- intros. eapply undef_reg_preserved; eauto.
+Qed.
+
+Lemma exec_exit_simulation_star b ofs f bb s2 t rs m rs' m': forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (MATCHI: match_internal (size bb - Z.of_nat (length_opt (exit bb))) (State rs m) s2)
+ (EXIT: exec_exit ge f (Ptrofs.repr (size bb)) rs m (exit bb) t rs' m')
+ (ATPC: rs PC = Vptr b ofs),
+ star Asm.step tge s2 t (State rs' m').
+Proof.
+ intros.
+ destruct (exit bb) eqn: Hex.
+ - eapply plus_star.
+ eapply exec_exit_simulation_plus; try rewrite Hex; congruence || eauto.
+ - inv MATCHI.
+ inv EXIT.
+ assert (X: rs2 = incrPC (Ptrofs.repr (size bb)) rs). {
+ unfold incrPC. unfold Pregmap.set.
+ apply functional_extensionality. intros x.
+ destruct (PregEq.eq x PC) as [X|].
+ - rewrite X. rewrite <- AGPC. simpl.
+ replace (size bb - 0) with (size bb) by omega. reflexivity.
+ - rewrite AG; try assumption. reflexivity.
+ }
+ destruct X.
+ subst; eapply star_refl; eauto.
+Qed.
+
+Lemma exec_bblock_simulation b ofs f bb t rs m rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (EXECBB: exec_bblock lk ge f bb rs m t rs' m'),
+ plus Asm.step tge (State rs m) t (State rs' m').
+Proof.
+ intros; destruct EXECBB as (rs1 & m1 & BODY & CTL).
+ exploit exec_header_simulation; eauto.
+ intros (s0 & STAR & MATCH0).
+ eapply star_plus_trans; traceEq || eauto.
+ destruct (bblock_non_empty bb).
+ - (* body bb <> nil *)
+ exploit exec_body_simulation_plus; eauto.
+ intros (s1 & PLUS & MATCH1).
+ eapply plus_star_trans; traceEq || eauto.
+ eapply exec_exit_simulation_star; eauto.
+ erewrite <- exec_body_dont_move_PC; eauto.
+ - (* exit bb <> None *)
+ exploit exec_body_simulation_star; eauto.
+ intros (s1 & STAR1 & MATCH1).
+ eapply star_plus_trans; traceEq || eauto.
+ eapply exec_exit_simulation_plus; eauto.
+ erewrite <- exec_body_dont_move_PC; eauto.
+Qed.
+
+Lemma step_simulation s t s':
+ Asmblock.step lk ge s t s' -> plus Asm.step tge s t s'.
+Proof.
+ intros STEP.
+ inv STEP; simpl; exploit functions_translated; eauto;
+ intros (tf0 & FINDtf & TRANSf);
+ monadInv TRANSf.
+ - (* internal step *) eapply exec_bblock_simulation; eauto.
+ - (* external step *)
+ apply plus_one.
+ exploit external_call_symbols_preserved; eauto. apply senv_preserved.
+ intros ?.
+ eapply Asm.exec_step_external; eauto.
+Qed.
+
+Lemma transf_program_correct:
+ forward_simulation (Asmblock.semantics lk prog) (Asm.semantics tprog).
+Proof.
+ eapply forward_simulation_plus.
- apply senv_preserved.
- - simpl; intros. exploit transf_initial_states; eauto.
- intros (s2 & A & B).
- exists s2; intuition auto. apply wf_initial; auto.
- - simpl; intros. destruct H as [MS WF]. eapply transf_final_states; eauto.
- - simpl; intros. destruct H0 as [MS WF].
- exploit step_simulation; eauto. intros [ (s2' & A & B) | (A & B & C) ].
- + left; exists s2'; intuition auto. eapply wf_step; eauto.
- + right; intuition auto. eapply wf_step; eauto.
+ - eexact transf_initial_states.
+ - eexact transf_final_states.
+ - (* TODO step_simulation *)
+ unfold match_states.
+ simpl; intros; subst; eexists; split; eauto.
+ eapply step_simulation; eauto.
Qed.
End PRESERVATION.
+
+End Asmblock_PRESERVATION.
+
+
+Local Open Scope linking_scope.
+
+Definition block_passes :=
+ mkpass Machblockgenproof.match_prog
+ ::: mkpass PseudoAsmblockproof.match_prog
+ ::: mkpass Asmblockgenproof.match_prog
+ ::: mkpass PostpassSchedulingproof.match_prog
+ ::: mkpass Asmblock_PRESERVATION.match_prog
+ ::: pass_nil _.
+
+Definition match_prog := pass_match (compose_passes block_passes).
+
+Lemma transf_program_match:
+ forall p tp, Asmgen.transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros p tp H.
+ unfold Asmgen.transf_program in H. apply bind_inversion in H. destruct H.
+ inversion_clear H. apply bind_inversion in H1. destruct H1.
+ inversion_clear H. apply bind_inversion in H2. destruct H2. inversion_clear H.
+ unfold Compopts.time in *. remember (Machblockgen.transf_program p) as mbp.
+ unfold match_prog; simpl.
+ exists mbp; split. apply Machblockgenproof.transf_program_match; auto.
+ exists x; split. apply PseudoAsmblockproof.transf_program_match; auto.
+ exists x0; split. apply Asmblockgenproof.transf_program_match; auto.
+ exists x1; split. apply PostpassSchedulingproof.transf_program_match; auto.
+ exists tp; split. apply Asmblock_PRESERVATION.transf_program_match; auto. auto.
+Qed.
+
+(** Return Address Offset *)
+
+Definition return_address_offset: Mach.function -> Mach.code -> ptrofs -> Prop :=
+ Machblockgenproof.Mach_return_address_offset (PseudoAsmblockproof.rao Asmblockgenproof.next).
+
+Lemma return_address_exists:
+ forall f sg ros c, is_tail (Mach.Mcall sg ros :: c) f.(Mach.fn_code) ->
+ exists ra, return_address_offset f c ra.
+Proof.
+ intros; eapply Machblockgenproof.Mach_return_address_exists; eauto.
+Admitted.
+
+Section PRESERVATION.
+
+Variable prog: Mach.program.
+Variable tprog: Asm.program.
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Theorem transf_program_correct:
+ forward_simulation (Mach.semantics return_address_offset prog) (Asm.semantics tprog).
+Proof.
+Admitted.
+(* TODO
+ unfold match_prog in TRANSF. simpl in TRANSF.
+ inv TRANSF. inv H. inv H1. inv H. inv H2. inv H. inv H3. inv H. inv H4. inv H.
+ eapply compose_forward_simulations.
+ { exploit Machblockgenproof.transf_program_correct; eauto. }
+ eapply compose_forward_simulations.
+ + apply PseudoAsmblockproof.transf_program_correct; eauto.
+ - intros; apply Asmblockgenproof.next_progress.
+ - intros. eapply .functions_bound_max_pos; eauto.
+ { intros. eapply Asmblock_PRESERVATION.symbol_high_low. eauto. }
+ + eapply compose_forward_simulations. apply Asmblockgenproof.transf_program_correct; eauto.
+ { intros; eapply Asmblock_PRESERVATION.symbol_high_low; eauto. }
+ apply Asmblock_PRESERVATION.transf_program_correct. eauto.
+Qed.*)
+
+End PRESERVATION.
+
+Instance TransfAsm: TransfLink match_prog := pass_match_link (compose_passes block_passes).
+
+(*******************************************)
+(* Stub actually needed by driver/Compiler *)
+
+Module Asmgenproof0.
+
+Definition return_address_offset := return_address_offset.
+
+End Asmgenproof0.
diff --git a/aarch64/Asmgenproof_orig_single_label_in_header.v.stash b/aarch64/Asmgenproof_orig_single_label_in_header.v.stash
new file mode 100644
index 00000000..bff18716
--- /dev/null
+++ b/aarch64/Asmgenproof_orig_single_label_in_header.v.stash
@@ -0,0 +1,2245 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* Justus Fasse UGA, VERIMAG *)
+(* Xavier Leroy INRIA Paris-Rocquencourt *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+Require Import Coqlib Errors.
+Require Import Integers Floats AST Linking.
+Require Import Values Memory Events Globalenvs Smallstep.
+Require Import Op Locations Machblock Conventions PseudoAsmblock Asm Asmblock.
+Require Machblockgenproof Asmblockgenproof PostpassSchedulingproof.
+Require Import Asmgen.
+Require Import Axioms.
+Require Import IterList.
+Require Import Ring.
+
+Module Asmblock_PRESERVATION.
+
+Import Asmblock_TRANSF.
+
+Definition match_prog (p: Asmblock.program) (tp: Asm.program) :=
+ match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
+
+Lemma transf_program_match:
+ forall p tp, transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros. eapply match_transform_partial_program; eauto.
+Qed.
+
+Section PRESERVATION.
+
+Variable prog: Asmblock.program.
+Variable tprog: Asm.program.
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Definition lk :aarch64_linker := {| Asmblock.symbol_low:=Asm.symbol_low tge; Asmblock.symbol_high:=Asm.symbol_high tge|}.
+
+Lemma symbols_preserved:
+ forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
+Proof (Genv.find_symbol_match TRANSF).
+
+Lemma symbol_addresses_preserved:
+ forall (s: ident) (ofs: ptrofs),
+ Genv.symbol_address tge s ofs = Genv.symbol_address ge s ofs.
+Proof.
+ intros; unfold Genv.symbol_address; rewrite symbols_preserved; reflexivity.
+Qed.
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_match TRANSF).
+
+Lemma symbol_high_low: forall (id: ident) (ofs: ptrofs),
+ Val.addl (Asmblock.symbol_high lk id ofs) (Asmblock.symbol_low lk id ofs) = Genv.symbol_address ge id ofs.
+Proof.
+ unfold lk; simpl. intros; rewrite Asm.symbol_high_low; unfold Genv.symbol_address;
+ rewrite symbols_preserved; reflexivity.
+Qed.
+
+Lemma functions_translated:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some f ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some tf /\ transf_fundef f = OK tf.
+Proof (Genv.find_funct_ptr_transf_partial TRANSF).
+
+Lemma internal_functions_translated:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some (Internal tf) /\ transf_function f = OK tf.
+Proof.
+ intros; exploit functions_translated; eauto.
+ intros (x & FIND & TRANSf).
+ apply bind_inversion in TRANSf.
+ destruct TRANSf as (tf & TRANSf & X).
+ inv X.
+ eauto.
+Qed.
+
+Lemma internal_functions_unfold:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ exists tc,
+ Genv.find_funct_ptr tge b = Some (Internal (Asm.mkfunction (fn_sig f) tc))
+ /\ unfold (fn_blocks f) = OK tc
+ /\ list_length_z tc <= Ptrofs.max_unsigned.
+Proof.
+ intros.
+ exploit internal_functions_translated; eauto.
+ intros (tf & FINDtf & TRANStf).
+ unfold transf_function in TRANStf.
+ monadInv TRANStf.
+ destruct (zlt _ _); try congruence.
+ inv EQ. inv EQ0.
+ eexists; intuition eauto.
+ omega.
+Qed.
+
+
+Inductive is_nth_inst (bb: bblock) (n:Z) (i:Asm.instruction): Prop :=
+ | is_nth_label l:
+ list_nth_z (header bb) n = Some l ->
+ i = Asm.Plabel l ->
+ is_nth_inst bb n i
+ | is_nth_basic bi:
+ list_nth_z (body bb) (n - list_length_z (header bb)) = Some bi ->
+ basic_to_instruction bi = OK i ->
+ is_nth_inst bb n i
+ | is_nth_ctlflow cfi:
+ (exit bb) = Some cfi ->
+ n = size bb - 1 ->
+ i = control_to_instruction cfi ->
+ is_nth_inst bb n i.
+
+(* Asmblock and Asm share the same definition of state *)
+Definition match_states (s1 s2 : state) := s1 = s2.
+
+Inductive match_internal: forall n, state -> state -> Prop :=
+ | match_internal_intro n rs1 m1 rs2 m2
+ (MEM: m1 = m2)
+ (AG: forall r, r <> PC -> rs1 r = rs2 r)
+ (AGPC: Val.offset_ptr (rs1 PC) (Ptrofs.repr n) = rs2 PC)
+ : match_internal n (State rs1 m1) (State rs2 m2).
+
+Lemma match_internal_set_parallel:
+ forall n rs1 m1 rs2 m2 r val,
+ match_internal n (State rs1 m1) (State rs2 m2) ->
+ r <> PC ->
+ match_internal n (State (rs1#r <- val) m1) (State (rs2#r <- val ) m2).
+Proof.
+ intros n rs1 m1 rs2 m2 r v MI.
+ inversion MI; constructor; auto.
+ - intros r' NOTPC.
+ unfold Pregmap.set; rewrite AG. reflexivity. assumption.
+ - unfold Pregmap.set; destruct (PregEq.eq PC r); congruence.
+Qed.
+
+Lemma agree_match_states:
+ forall rs1 m1 rs2 m2,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ forall r : preg, rs1#r = rs2#r.
+Proof.
+ intros.
+ unfold match_states in *.
+ assert (rs1 = rs2) as EQ. { congruence. }
+ rewrite EQ. reflexivity.
+Qed.
+
+Lemma match_states_set_parallel:
+ forall rs1 m1 rs2 m2 r v,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ match_states (State (rs1#r <- v) m1) (State (rs2#r <- v) m2).
+Proof.
+ intros; unfold match_states in *.
+ assert (rs1 = rs2) as RSEQ. { congruence. }
+ assert (m1 = m2) as MEQ. { congruence. }
+ rewrite RSEQ in *; rewrite MEQ in *; unfold Pregmap.set; reflexivity.
+Qed.
+
+(* match_internal from match_states *)
+Lemma mi_from_ms:
+ forall rs1 m1 rs2 m2 b ofs,
+ match_states (State rs1 m1) (State rs2 m2) ->
+ rs1#PC = Vptr b ofs ->
+ match_internal 0 (State rs1 m1) (State rs2 m2).
+Proof.
+ intros rs1 m1 rs2 m2 b ofs MS PCVAL.
+ inv MS; constructor; auto; unfold Val.offset_ptr;
+ rewrite PCVAL; rewrite Ptrofs.add_zero; reflexivity.
+Qed.
+
+Lemma transf_initial_states:
+ forall s1, Asmblock.initial_state prog s1 ->
+ exists s2, Asm.initial_state tprog s2 /\ match_states s1 s2.
+Proof.
+ intros ? INIT_s1.
+ inversion INIT_s1 as (m, ?, ge0, rs). unfold ge0 in *.
+ econstructor; split.
+ - econstructor.
+ eapply (Genv.init_mem_transf_partial TRANSF); eauto.
+ - rewrite (match_program_main TRANSF); rewrite symbol_addresses_preserved.
+ unfold rs; reflexivity.
+Qed.
+
+Lemma transf_final_states:
+ forall s1 s2 r,
+ match_states s1 s2 -> Asmblock.final_state s1 r -> Asm.final_state s2 r.
+Proof.
+ intros s1 s2 r MATCH FINAL_s1.
+ inv FINAL_s1; inv MATCH; constructor; assumption.
+Qed.
+
+Definition max_pos (f : Asm.function) := list_length_z f.(Asm.fn_code).
+
+Lemma functions_bound_max_pos: forall fb f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ max_pos tf <= Ptrofs.max_unsigned.
+Proof.
+ intros fb f tf FINDf TRANSf.
+ unfold transf_function in TRANSf.
+ apply bind_inversion in TRANSf.
+ destruct TRANSf as (c & TRANSf).
+ destruct TRANSf as (_ & TRANSf).
+ destruct (zlt _ _).
+ - inversion TRANSf.
+ - unfold max_pos.
+ assert (Asm.fn_code tf = c) as H. { inversion TRANSf as (H'); auto. }
+ rewrite H; omega.
+Qed.
+
+Lemma one_le_max_unsigned:
+ 1 <= Ptrofs.max_unsigned.
+Proof.
+ unfold Ptrofs.max_unsigned; simpl; unfold Ptrofs.wordsize;
+ unfold Wordsize_Ptrofs.wordsize; destruct Archi.ptr64; simpl; omega.
+Qed.
+
+(* NB: does not seem useful anymore, with the [exec_header_simulation] proof below
+Lemma match_internal_exec_label:
+ forall n rs1 m1 rs2 m2 l fb f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ match_internal n (State rs1 m1) (State rs2 m2) ->
+ n >= 0 ->
+ (* There is no step if n is already max_pos *)
+ n < (max_pos tf) ->
+ exists rs2' m2', Asm.exec_instr tge tf (Asm.Plabel l) rs2 m2 = Next rs2' m2'
+ /\ match_internal (n+1) (State rs1 m1) (State rs2' m2').
+Proof.
+ intros. (* XXX auto generated names *)
+ unfold Asm.exec_instr.
+ eexists; eexists; split; eauto.
+ inversion H1; constructor; auto.
+ - intros; unfold Asm.nextinstr; unfold Pregmap.set;
+ destruct (PregEq.eq r PC); auto; contradiction.
+ - unfold Asm.nextinstr; rewrite Pregmap.gss; unfold Ptrofs.one.
+ rewrite <- AGPC; rewrite Val.offset_ptr_assoc; unfold Ptrofs.add;
+ rewrite Ptrofs.unsigned_repr. rewrite Ptrofs.unsigned_repr; trivial.
+ + split.
+ * apply Z.le_0_1.
+ * apply one_le_max_unsigned.
+ + split.
+ * apply Z.ge_le; assumption.
+ * rewrite <- functions_bound_max_pos; eauto; omega.
+Qed.
+*)
+
+Lemma incrPC_agree_but_pc:
+ forall rs r ofs,
+ r <> PC ->
+ (incrPC ofs rs)#r = rs#r.
+Proof.
+ intros rs r ofs NOTPC.
+ unfold incrPC; unfold Pregmap.set; destruct (PregEq.eq r PC).
+ - contradiction.
+ - reflexivity.
+Qed.
+
+Lemma bblock_non_empty bb: body bb <> nil \/ exit bb <> None.
+Proof.
+ destruct bb. simpl.
+ unfold non_empty_bblockb in correct.
+ unfold non_empty_body, non_empty_exit, Is_true in correct.
+ destruct body, exit.
+ - right. discriminate.
+ - contradiction.
+ - right. discriminate.
+ - left. discriminate.
+Qed.
+
+Lemma list_length_z_aux_increase A (l: list A): forall acc,
+ list_length_z_aux l acc >= acc.
+Proof.
+ induction l; simpl; intros.
+ - omega.
+ - generalize (IHl (Z.succ acc)). omega.
+Qed.
+
+Lemma bblock_size_aux_pos bb: list_length_z (body bb) + Z.of_nat (length_opt (exit bb)) >= 1.
+Proof.
+ destruct (bblock_non_empty bb), (body bb) as [|hd tl], (exit bb); simpl;
+ try (congruence || omega);
+ unfold list_length_z; simpl;
+ generalize (list_length_z_aux_increase _ tl 1); omega.
+Qed.
+
+
+Lemma list_length_add_acc A (l : list A) acc:
+ list_length_z_aux l acc = (list_length_z l) + acc.
+Proof.
+ unfold list_length_z, list_length_z_aux. simpl.
+ fold list_length_z_aux.
+ rewrite (list_length_z_aux_shift l acc 0).
+ omega.
+Qed.
+
+Lemma list_length_z_cons A hd (tl : list A):
+ list_length_z (hd :: tl) = list_length_z tl + 1.
+Proof.
+ unfold list_length_z; simpl; rewrite list_length_add_acc; reflexivity.
+Qed.
+
+(*Lemma length_agree A (l : list A):*)
+ (*list_length_z l = Z.of_nat (length l).*)
+(*Proof.*)
+ (*induction l as [| ? l IH]; intros.*)
+ (*- unfold list_length_z; reflexivity.*)
+ (*- simpl; rewrite list_length_z_cons, Zpos_P_of_succ_nat; omega.*)
+(*Qed.*)
+
+Lemma bblock_size_aux bb: size bb = list_length_z (header bb) + list_length_z (body bb) + Z.of_nat (length_opt (exit bb)).
+Proof.
+ unfold size.
+ repeat (rewrite list_length_z_nat). repeat (rewrite Nat2Z.inj_add). reflexivity.
+Qed.
+
+Lemma header_size_lt_block_size bb:
+ list_length_z (header bb) < size bb.
+Proof.
+ rewrite bblock_size_aux.
+ generalize (bblock_non_empty bb); intros NEMPTY; destruct NEMPTY as [HDR|EXIT].
+ - destruct (body bb); try contradiction; rewrite list_length_z_cons;
+ repeat rewrite list_length_z_nat; omega.
+ - destruct (exit bb); try contradiction; simpl; repeat rewrite list_length_z_nat; omega.
+Qed.
+
+Lemma body_size_le_block_size bb:
+ list_length_z (body bb) <= size bb.
+Proof.
+ rewrite bblock_size_aux; repeat rewrite list_length_z_nat; omega.
+Qed.
+
+
+Lemma bblock_size_pos bb: size bb >= 1.
+Proof.
+ rewrite (bblock_size_aux bb).
+ generalize (bblock_size_aux_pos bb).
+ generalize (list_length_z_pos (header bb)).
+ omega.
+Qed.
+
+Lemma unfold_car_cdr bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tbb tc', unfold_bblock bb = OK tbb
+ /\ unfold bbs = OK tc'
+ /\ unfold (bb :: bbs) = OK (tbb ++ tc').
+Proof.
+ intros UNFOLD.
+ assert (UF := UNFOLD).
+ unfold unfold in UNFOLD.
+ apply bind_inversion in UNFOLD. destruct UNFOLD as (? & UBB). destruct UBB as (UBB & REST).
+ apply bind_inversion in REST. destruct REST as (? & UNFOLD').
+ fold unfold in UNFOLD'. destruct UNFOLD' as (UNFOLD' & UNFOLD).
+ rewrite <- UNFOLD in UF.
+ eauto.
+Qed.
+
+Lemma unfold_cdr bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tc', unfold bbs = OK tc'.
+Proof.
+ intros; exploit unfold_car_cdr; eauto. intros (_ & ? & _ & ? & _).
+ eexists; eauto.
+Qed.
+
+Lemma unfold_car bb bbs tc:
+ unfold (bb :: bbs) = OK tc ->
+ exists tbb, unfold_bblock bb = OK tbb.
+Proof.
+ intros; exploit unfold_car_cdr; eauto. intros (? & _ & ? & _ & _).
+ eexists; eauto.
+Qed.
+
+Lemma all_blocks_translated:
+ forall bbs tc,
+ unfold bbs = OK tc ->
+ forall bb, In bb bbs ->
+ exists c, unfold_bblock bb = OK c.
+Proof.
+ induction bbs as [| bb bbs IHbbs].
+ - contradiction.
+ - intros ? UNFOLD ? IN.
+ (* unfold proceeds by unfolding the basic block at the head of the list and
+ * then recurring *)
+ exploit unfold_car_cdr; eauto. intros (? & ? & ? & ? & _).
+ (* basic block is either in head or tail *)
+ inversion IN as [EQ | NEQ].
+ + rewrite <- EQ; eexists; eauto.
+ + eapply IHbbs; eauto.
+Qed.
+
+Lemma entire_body_translated:
+ forall lbi tc,
+ unfold_body lbi = OK tc ->
+ forall bi, In bi lbi ->
+ exists bi', basic_to_instruction bi = OK bi'.
+Proof.
+ induction lbi as [| a lbi IHlbi].
+ - intros. contradiction.
+ - intros tc UNFOLD_BODY bi IN.
+ unfold unfold_body in UNFOLD_BODY. apply bind_inversion in UNFOLD_BODY.
+ destruct UNFOLD_BODY as (? & TRANSbi & REST).
+ apply bind_inversion in REST. destruct REST as (? & UNFOLD_BODY' & ?).
+ fold unfold_body in UNFOLD_BODY'.
+
+ inversion IN as [EQ | NEQ].
+ + rewrite <- EQ; eauto.
+ + eapply IHlbi; eauto.
+Qed.
+
+Lemma bblock_in_bblocks bbs bb: forall
+ tc pos
+ (UNFOLD: unfold bbs = OK tc)
+ (FINDBB: find_bblock pos bbs = Some bb),
+ In bb bbs.
+Proof.
+ induction bbs as [| b bbs IH].
+ - intros. inversion FINDBB.
+ - destruct pos.
+ + intros. inversion FINDBB as (EQ). rewrite <- EQ. apply in_eq.
+ + intros.
+ exploit unfold_cdr; eauto. intros (tc' & UNFOLD').
+ unfold find_bblock in FINDBB. simpl in FINDBB.
+ fold find_bblock in FINDBB.
+ apply in_cons. eapply IH; eauto.
+ + intros. inversion FINDBB.
+Qed.
+
+Lemma blocks_translated tc pos bbs bb: forall
+ (UNFOLD: unfold bbs = OK tc)
+ (FINDBB: find_bblock pos bbs = Some bb),
+ exists tbb, unfold_bblock bb = OK tbb.
+Proof.
+ intros; exploit bblock_in_bblocks; eauto; intros;
+ eapply all_blocks_translated; eauto.
+Qed.
+
+Lemma size_header b pos f bb: forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock pos (fn_blocks f) = Some bb),
+ list_length_z (header bb) <= 1.
+Proof.
+ intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & ?).
+ exploit blocks_translated; eauto. intros TBB.
+
+ unfold unfold_bblock in TBB.
+ destruct (zle (list_length_z (header bb)) 1).
+ - assumption.
+ - destruct TBB as (? & TBB). discriminate TBB.
+Qed.
+
+Lemma list_nth_z_neg A (l: list A): forall n,
+ n < 0 -> list_nth_z l n = None.
+Proof.
+ induction l; simpl; auto.
+ intros n H; destruct (zeq _ _); (try eapply IHl); omega.
+Qed.
+
+Lemma find_bblock_neg bbs: forall pos,
+ pos < 0 -> find_bblock pos bbs = None.
+Proof.
+ induction bbs; simpl; auto.
+ intros. destruct (zlt pos 0). { reflexivity. }
+ destruct (zeq pos 0); contradiction.
+Qed.
+
+Lemma equal_header_size bb:
+ length (header bb) = length (unfold_label (header bb)).
+Proof.
+ induction (header bb); auto.
+ simpl. rewrite IHl. auto.
+Qed.
+
+Lemma equal_body_size:
+ forall bb tb,
+ unfold_body (body bb) = OK tb ->
+ length (body bb) = length tb.
+Proof.
+ intros bb. induction (body bb).
+ - simpl. intros ? H. inversion H. auto.
+ - intros tb H. simpl in H. apply bind_inversion in H. destruct H as (? & BI & TAIL).
+ apply bind_inversion in TAIL. destruct TAIL as (tb' & BODY' & CONS). inv CONS.
+ simpl. specialize (IHl tb' BODY'). rewrite IHl. reflexivity.
+Qed.
+
+Lemma equal_exit_size bb:
+ length_opt (exit bb) = length (unfold_exit (exit bb)).
+Proof.
+ destruct (exit bb); trivial.
+Qed.
+
+Lemma bblock_size_preserved bb tb:
+ unfold_bblock bb = OK tb ->
+ size bb = list_length_z tb.
+Proof.
+ unfold unfold_bblock. intros UNFOLD_BBLOCK.
+ destruct (zle (list_length_z (header bb)) 1). 2: { inversion UNFOLD_BBLOCK. }
+ apply bind_inversion in UNFOLD_BBLOCK. destruct UNFOLD_BBLOCK as (? & UNFOLD_BODY & CONS).
+ inversion CONS.
+ unfold size.
+ rewrite equal_header_size, equal_exit_size.
+ erewrite equal_body_size; eauto.
+ rewrite list_length_z_nat.
+ repeat (rewrite app_length).
+ rewrite plus_assoc. auto.
+Qed.
+
+Lemma size_of_blocks_max_pos_aux:
+ forall bbs tbbs pos bb,
+ find_bblock pos bbs = Some bb ->
+ unfold bbs = OK tbbs ->
+ pos + size bb <= list_length_z tbbs.
+Proof.
+ induction bbs as [| bb ? IHbbs].
+ - intros tbbs ? ? FINDBB; inversion FINDBB.
+ - simpl; intros tbbs pos bb' FINDBB UNFOLD.
+ apply bind_inversion in UNFOLD; destruct UNFOLD as (tbb & UNFOLD_BBLOCK & H).
+ apply bind_inversion in H; destruct H as (tbbs' & UNFOLD & CONS).
+ inv CONS.
+ destruct (zlt pos 0). { discriminate FINDBB. }
+ destruct (zeq pos 0).
+ + inv FINDBB.
+ exploit bblock_size_preserved; eauto; intros SIZE; rewrite SIZE.
+ repeat (rewrite list_length_z_nat). rewrite app_length, Nat2Z.inj_add.
+ omega.
+ + generalize (IHbbs tbbs' (pos - size bb) bb' FINDBB UNFOLD). intros IH.
+ exploit bblock_size_preserved; eauto; intros SIZE.
+ repeat (rewrite list_length_z_nat); rewrite app_length.
+ rewrite Nat2Z.inj_add; repeat (rewrite <- list_length_z_nat).
+ omega.
+Qed.
+
+Lemma size_of_blocks_max_pos pos f tf bi:
+ find_bblock pos (fn_blocks f) = Some bi ->
+ transf_function f = OK tf ->
+ pos + size bi <= max_pos tf.
+Proof.
+ unfold transf_function, max_pos.
+ intros FINDBB UNFOLD.
+ apply bind_inversion in UNFOLD. destruct UNFOLD as (? & UNFOLD & H).
+ destruct (zlt Ptrofs.max_unsigned (list_length_z x)). { discriminate H. }
+ inv H. simpl.
+ eapply size_of_blocks_max_pos_aux; eauto.
+Qed.
+
+Lemma unfold_bblock_not_nil bb:
+ unfold_bblock bb = OK nil -> False.
+Proof.
+ intros.
+ exploit bblock_size_preserved; eauto. unfold list_length_z; simpl. intros SIZE.
+ generalize (bblock_size_pos bb). intros SIZE'. omega.
+Qed.
+
+(* same proof as list_nth_z_range (Coqlib) *)
+Lemma find_instr_range:
+ forall c n i,
+ Asm.find_instr n c = Some i -> 0 <= n < list_length_z c.
+Proof.
+ induction c; simpl; intros.
+ discriminate.
+ rewrite list_length_z_cons. destruct (zeq n 0).
+ generalize (list_length_z_pos c); omega.
+ exploit IHc; eauto. omega.
+Qed.
+
+Lemma find_instr_tail:
+ forall tbb pos c i,
+ Asm.find_instr pos c = Some i ->
+ Asm.find_instr (pos + list_length_z tbb) (tbb ++ c) = Some i.
+Proof.
+ induction tbb as [| ? ? IHtbb].
+ - intros. unfold list_length_z; simpl. rewrite Z.add_0_r. assumption.
+ - intros. rewrite list_length_z_cons. simpl.
+ destruct (zeq (pos + (list_length_z tbb + 1)) 0).
+ + exploit find_instr_range; eauto. intros POS_RANGE.
+ generalize (list_length_z_pos tbb). omega.
+ + replace (pos + (list_length_z tbb + 1) - 1) with (pos + list_length_z tbb) by omega.
+ eapply IHtbb; eauto.
+Qed.
+
+Lemma size_of_blocks_bounds fb pos f bi:
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ find_bblock pos (fn_blocks f) = Some bi ->
+ pos + size bi <= Ptrofs.max_unsigned.
+Proof.
+ intros; exploit internal_functions_translated; eauto.
+ intros (tf & _ & TRANSf).
+ assert (pos + size bi <= max_pos tf). { eapply size_of_blocks_max_pos; eauto. }
+ assert (max_pos tf <= Ptrofs.max_unsigned). { eapply functions_bound_max_pos; eauto. }
+ omega.
+Qed.
+
+Lemma find_instr_bblock_tail:
+ forall tbb bb pos c i,
+ Asm.find_instr pos c = Some i ->
+ unfold_bblock bb = OK tbb ->
+ Asm.find_instr (pos + size bb ) (tbb ++ c) = Some i.
+Proof.
+ induction tbb.
+ - intros. exploit unfold_bblock_not_nil; eauto. intros. contradiction.
+ - intros. simpl.
+ destruct (zeq (pos + size bb) 0).
+ + (* absurd *)
+ exploit find_instr_range; eauto. intros POS_RANGE.
+ generalize (bblock_size_pos bb). intros SIZE. omega.
+ + erewrite bblock_size_preserved; eauto.
+ rewrite list_length_z_cons.
+ replace (pos + (list_length_z tbb + 1) - 1) with (pos + list_length_z tbb) by omega.
+ apply find_instr_tail; auto.
+Qed.
+
+Lemma list_nth_z_find_label:
+ forall (ll : list label) il n l,
+ list_nth_z ll n = Some l ->
+ Asm.find_instr n ((unfold_label ll) ++ il) = Some (Asm.Plabel l).
+Proof.
+ induction ll.
+ - intros. inversion H.
+ - intros. simpl.
+ destruct (zeq n 0) as [Z | NZ].
+ + inversion H as (H'). rewrite Z in H'. simpl in H'. inv H'. reflexivity.
+ + simpl in H. destruct (zeq n 0). { contradiction. }
+ apply IHll; auto.
+Qed.
+
+Lemma list_nth_z_find_bi:
+ forall lbi bi tlbi n bi' exit,
+ list_nth_z lbi n = Some bi ->
+ unfold_body lbi = OK tlbi ->
+ basic_to_instruction bi = OK bi' ->
+ Asm.find_instr n (tlbi ++ exit) = Some bi'.
+Proof.
+ induction lbi.
+ - intros. inversion H.
+ - simpl. intros.
+ apply bind_inversion in H0. destruct H0 as (? & ? & ?).
+ apply bind_inversion in H2. destruct H2 as (? & ? & ?).
+ destruct (zeq n 0) as [Z | NZ].
+ + destruct n.
+ * inversion H as (BI). rewrite BI in *.
+ inversion H3. simpl. congruence.
+ * (* absurd *) congruence.
+ * (* absurd *) congruence.
+ + inv H3. simpl. destruct (zeq n 0). { contradiction. }
+ eapply IHlbi; eauto.
+Qed.
+
+Lemma list_nth_z_find_bi_with_header:
+ forall ll lbi bi tlbi n bi' (rest : list Asm.instruction),
+ list_nth_z lbi (n - list_length_z ll) = Some bi ->
+ unfold_body lbi = OK tlbi ->
+ basic_to_instruction bi = OK bi' ->
+ Asm.find_instr n ((unfold_label ll) ++ (tlbi) ++ (rest)) = Some bi'.
+Proof.
+ induction ll.
+ - unfold list_length_z. simpl. intros.
+ replace (n - 0) with n in H by omega. eapply list_nth_z_find_bi; eauto.
+ - intros. simpl. destruct (zeq n 0).
+ + rewrite list_length_z_cons in H. rewrite e in H.
+ replace (0 - (list_length_z ll + 1)) with (-1 - (list_length_z ll)) in H by omega.
+ generalize (list_length_z_pos ll). intros.
+ rewrite list_nth_z_neg in H; try omega. inversion H.
+ + rewrite list_length_z_cons in H.
+ replace (n - (list_length_z ll + 1)) with (n -1 - (list_length_z ll)) in H by omega.
+ eapply IHll; eauto.
+Qed.
+
+(* XXX unused *)
+Lemma range_list_nth_z:
+ forall (A: Type) (l: list A) n,
+ 0 <= n < list_length_z l ->
+ exists x, list_nth_z l n = Some x.
+Proof.
+ induction l.
+ - intros. unfold list_length_z in H. simpl in H. omega.
+ - intros n. destruct (zeq n 0).
+ + intros. simpl. destruct (zeq n 0). { eauto. } contradiction.
+ + intros H. rewrite list_length_z_cons in H.
+ simpl. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) by omega.
+ eapply IHl; omega.
+Qed.
+
+Lemma list_nth_z_n_too_big:
+ forall (A: Type) (l: list A) n,
+ 0 <= n ->
+ list_nth_z l n = None ->
+ n >= list_length_z l.
+Proof.
+ induction l.
+ - intros. unfold list_length_z. simpl. omega.
+ - intros. rewrite list_length_z_cons.
+ simpl in H0.
+ destruct (zeq n 0) as [N | N].
+ + inversion H0.
+ + (* XXX there must be a more elegant way to prove this simple fact *)
+ assert (n > 0). { omega. }
+ assert (0 <= n - 1). { omega. }
+ generalize (IHl (n - 1)). intros IH.
+ assert (n - 1 >= list_length_z l). { auto. }
+ assert (n > list_length_z l); omega.
+Qed.
+
+Lemma find_instr_past_header:
+ forall labels n rest,
+ list_nth_z labels n = None ->
+ Asm.find_instr n (unfold_label labels ++ rest) =
+ Asm.find_instr (n - list_length_z labels) rest.
+Proof.
+ induction labels as [| label labels' IH].
+ - unfold list_length_z; simpl; intros; rewrite Z.sub_0_r; reflexivity.
+ - intros. simpl. destruct (zeq n 0) as [N | N].
+ + rewrite N in H. inversion H.
+ + rewrite list_length_z_cons.
+ replace (n - (list_length_z labels' + 1)) with (n - 1 - list_length_z labels') by omega.
+ simpl in H. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) in H by omega.
+ apply IH; auto.
+Qed.
+
+(* very similar to find_instr_past_header *)
+Lemma find_instr_past_body:
+ forall lbi n tlbi rest,
+ list_nth_z lbi n = None ->
+ unfold_body lbi = OK tlbi ->
+ Asm.find_instr n (tlbi ++ rest) =
+ Asm.find_instr (n - list_length_z lbi) rest.
+Proof.
+ induction lbi.
+ - unfold list_length_z; simpl; intros ? ? ? ? H. inv H; rewrite Z.sub_0_r; reflexivity.
+ - intros n tlib ? NTH UNFOLD_BODY.
+ unfold unfold_body in UNFOLD_BODY. apply bind_inversion in UNFOLD_BODY.
+ destruct UNFOLD_BODY as (? & BI & H).
+ apply bind_inversion in H. destruct H as (? & UNFOLD_BODY' & CONS).
+ fold unfold_body in UNFOLD_BODY'. inv CONS.
+ simpl; destruct (zeq n 0) as [N|N].
+ + rewrite N in NTH; inversion NTH.
+ + rewrite list_length_z_cons.
+ replace (n - (list_length_z lbi + 1)) with (n - 1 - list_length_z lbi) by omega.
+ simpl in NTH. destruct (zeq n 0). { contradiction. }
+ replace (Z.pred n) with (n - 1) in NTH by omega.
+ apply IHlbi; auto.
+Qed.
+
+Lemma n_beyond_body:
+ forall bb n,
+ 0 <= n < size bb ->
+ list_nth_z (header bb) n = None ->
+ list_nth_z (body bb) (n - list_length_z (header bb)) = None ->
+ n >= Z.of_nat (length (header bb) + length (body bb)).
+Proof.
+ intros.
+ assert (0 <= n). { omega. }
+ generalize (list_nth_z_n_too_big label (header bb) n H2 H0). intros.
+ generalize (list_nth_z_n_too_big _ (body bb) (n - list_length_z (header bb))). intros.
+ unfold size in H.
+
+ assert (0 <= n - list_length_z (header bb)). { omega. }
+ assert (n - list_length_z (header bb) >= list_length_z (body bb)). { apply H4; auto. }
+
+ assert (n >= list_length_z (header bb) + list_length_z (body bb)). { omega. }
+ rewrite Nat2Z.inj_add.
+ repeat (rewrite <- list_length_z_nat). assumption.
+Qed.
+
+Lemma exec_arith_instr_dont_move_PC ai rs rs': forall
+ (BASIC: exec_arith_instr lk ai rs = rs'),
+ rs PC = rs' PC.
+Proof.
+ destruct ai; simpl; intros;
+ try (rewrite <- BASIC; rewrite Pregmap.gso; auto; discriminate).
+ - destruct i; simpl in BASIC.
+ + unfold compare_long in BASIC; rewrite <- BASIC.
+ repeat rewrite Pregmap.gso; try discriminate. reflexivity.
+ + unfold compare_long in BASIC; rewrite <- BASIC.
+ repeat rewrite Pregmap.gso; try discriminate. reflexivity.
+ + destruct sz;
+ try (unfold compare_single in BASIC || unfold compare_float in BASIC);
+ destruct (rs r1), (rs r2);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct i; simpl in BASIC; destruct is;
+ try (unfold compare_int in BASIC || unfold compare_long in BASIC);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct i; simpl in BASIC; destruct sz;
+ try (unfold compare_single in BASIC || unfold compare_float in BASIC);
+ destruct (rs r1);
+ try (rewrite <- BASIC; repeat rewrite Pregmap.gso; try (discriminate || reflexivity)).
+ - destruct fsz; rewrite <- BASIC; rewrite Pregmap.gso; try (discriminate || reflexivity).
+ - destruct fsz; rewrite <- BASIC; rewrite Pregmap.gso; try (discriminate || reflexivity).
+Qed.
+
+Lemma exec_basic_dont_move_PC bi rs m rs' m': forall
+ (BASIC: exec_basic lk ge bi rs m = Next rs' m'),
+ rs PC = rs' PC.
+Proof.
+ destruct bi; simpl; intros.
+ - inv BASIC. exploit exec_arith_instr_dont_move_PC; eauto.
+ - unfold exec_load in BASIC.
+ destruct Mem.loadv. 2: { discriminate BASIC. }
+ inv BASIC. rewrite Pregmap.gso; try discriminate; auto.
+ - unfold exec_store in BASIC.
+ destruct Mem.storev. 2: { discriminate BASIC. }
+ inv BASIC; reflexivity.
+ - destruct Mem.alloc, Mem.store. 2: { discriminate BASIC. }
+ inv BASIC. repeat (rewrite Pregmap.gso; try discriminate). reflexivity.
+ - destruct Mem.loadv. 2: { discriminate BASIC. }
+ destruct rs, Mem.free; try discriminate BASIC.
+ inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+ - inv BASIC; rewrite Pregmap.gso; try discriminate; auto.
+Qed.
+
+Lemma exec_body_dont_move_PC_aux:
+ forall bis rs m rs' m'
+ (BODY: exec_body lk ge bis rs m = Next rs' m'),
+ rs PC = rs' PC.
+Proof.
+ induction bis.
+ - intros; inv BODY; reflexivity.
+ - simpl; intros.
+ remember (exec_basic lk ge a rs m) as bi eqn:BI; destruct bi. 2: { discriminate BODY. }
+ symmetry in BI; destruct s in BODY, BI; simpl in BODY, BI.
+ exploit exec_basic_dont_move_PC; eauto; intros AGPC; rewrite AGPC.
+ eapply IHbis; eauto.
+Qed.
+
+Lemma exec_body_dont_move_PC bb rs m rs' m': forall
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ rs PC = rs' PC.
+Proof. apply exec_body_dont_move_PC_aux. Qed.
+
+Lemma find_instr_bblock:
+ forall n lb pos bb tlb
+ (FINDBB: find_bblock pos lb = Some bb)
+ (UNFOLD: unfold lb = OK tlb)
+ (SIZE: 0 <= n < size bb),
+ exists i, is_nth_inst bb n i /\ Asm.find_instr (pos+n) tlb = Some i.
+Proof.
+ induction lb as [| b lb IHlb].
+ - intros. inversion FINDBB.
+ - intros pos bb tlb FINDBB UNFOLD SIZE.
+ destruct pos.
+ + inv FINDBB. simpl.
+ exploit unfold_car_cdr; eauto. intros (tbb & tlb' & UNFOLD_BBLOCK & UNFOLD' & UNFOLD_cons).
+ rewrite UNFOLD in UNFOLD_cons. inversion UNFOLD_cons.
+ unfold unfold_bblock in UNFOLD_BBLOCK.
+ destruct (zle (list_length_z (header bb)) 1). 2: { inversion UNFOLD_BBLOCK. }
+ apply bind_inversion in UNFOLD_BBLOCK.
+ destruct UNFOLD_BBLOCK as (? & UNFOLD_BODY & H).
+ inversion H as (UNFOLD_BBLOCK).
+ remember (list_nth_z (header bb) n) as label_opt eqn:LBL. destruct label_opt.
+ * (* nth instruction is a label *)
+ eexists; split. { eapply is_nth_label; eauto. }
+ inversion UNFOLD_cons.
+ symmetry in LBL.
+ rewrite <- app_assoc.
+ apply list_nth_z_find_label; auto.
+ * remember (list_nth_z (body bb) (n - list_length_z (header bb))) as bi_opt eqn:BI.
+ destruct bi_opt.
+ -- (* nth instruction is a basic instruction *)
+ exploit list_nth_z_in; eauto. intros INBB.
+ exploit entire_body_translated; eauto. intros BI'.
+ destruct BI'.
+ eexists; split.
+ ++ eapply is_nth_basic; eauto.
+ ++ repeat (rewrite <- app_assoc). eapply list_nth_z_find_bi_with_header; eauto.
+ -- (* nth instruction is the exit instruction *)
+ generalize n_beyond_body. intros TEMP.
+ assert (n >= Z.of_nat (Datatypes.length (header bb)
+ + Datatypes.length (body bb))) as NGE. { auto. } clear TEMP.
+ remember (exit bb) as exit_opt eqn:EXIT. destruct exit_opt.
+ ++ rewrite <- app_assoc. rewrite find_instr_past_header; auto.
+ rewrite <- app_assoc. erewrite find_instr_past_body; eauto.
+ assert (SIZE' := SIZE).
+ unfold size in SIZE. rewrite <- EXIT in SIZE. simpl in SIZE.
+ destruct SIZE as (LOWER & UPPER).
+ repeat (rewrite Nat2Z.inj_add in UPPER).
+ repeat (rewrite <- list_length_z_nat in UPPER). repeat (rewrite Nat2Z.inj_add in NGE).
+ repeat (rewrite <- list_length_z_nat in NGE). simpl in UPPER.
+ assert (n = list_length_z (header bb) + list_length_z (body bb)). { omega. }
+ assert (n = size bb - 1). {
+ unfold size. rewrite <- EXIT. simpl.
+ repeat (rewrite Nat2Z.inj_add). repeat (rewrite <- list_length_z_nat). simpl. omega.
+ }
+ symmetry in EXIT.
+ eexists; split.
+ ** eapply is_nth_ctlflow; eauto.
+ ** simpl.
+ destruct (zeq (n - list_length_z (header bb) - list_length_z (body bb)) 0). { reflexivity. }
+ (* absurd *) omega.
+ ++ (* absurd *)
+ unfold size in SIZE. rewrite <- EXIT in SIZE. simpl in SIZE.
+ destruct SIZE as (? & SIZE'). rewrite Nat.add_0_r in SIZE'. omega.
+ + unfold find_bblock in FINDBB; simpl in FINDBB; fold find_bblock in FINDBB.
+ inversion UNFOLD as (UNFOLD').
+ apply bind_inversion in UNFOLD'. destruct UNFOLD' as (? & (UNFOLD_BBLOCK' & UNFOLD')).
+ apply bind_inversion in UNFOLD'. destruct UNFOLD' as (? & (UNFOLD' & TLB)).
+ inversion TLB.
+ generalize (IHlb _ _ _ FINDBB UNFOLD'). intros IH.
+ destruct IH as (? & (IH_is_nth & IH_find_instr)); eauto.
+ eexists; split.
+ * apply IH_is_nth.
+ * replace (Z.pos p + n) with (Z.pos p + n - size b + size b) by omega.
+ eapply find_instr_bblock_tail; try assumption.
+ replace (Z.pos p + n - size b) with (Z.pos p - size b + n) by omega.
+ apply IH_find_instr.
+ + (* absurd *)
+ generalize (Pos2Z.neg_is_neg p). intros. exploit (find_bblock_neg (b :: lb)); eauto.
+ rewrite FINDBB. intros CONTRA. inversion CONTRA.
+Qed.
+
+Lemma exec_header_simulation b ofs f bb rs m: forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb),
+ exists s', star Asm.step tge (State rs m) E0 s'
+ /\ match_internal (list_length_z (header bb)) (State rs m) s'.
+Proof.
+ intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+ assert (BNDhead: list_length_z (header bb) <= 1). { eapply size_header; eauto. }
+ destruct (header bb) as [|l[|]] eqn: EQhead.
+ + (* header nil *)
+ eexists; split.
+ - eapply star_refl.
+ - split; eauto.
+ unfold list_length_z; rewrite !ATPC; simpl.
+ rewrite Ptrofs.add_zero; auto.
+ + (* header one *)
+ assert (Lhead: list_length_z (header bb) = 1). { rewrite EQhead; unfold list_length_z; simpl. auto. }
+ exploit (find_instr_bblock 0); eauto.
+ { generalize (bblock_size_pos bb). omega. }
+ intros (i & NTH & FIND_INSTR).
+ inv NTH.
+ * rewrite EQhead in H; simpl in H. inv H.
+ cutrewrite (Ptrofs.unsigned ofs + 0 = Ptrofs.unsigned ofs) in FIND_INSTR; try omega.
+ eexists. split.
+ - eapply star_one.
+ eapply Asm.exec_step_internal; eauto.
+ simpl; eauto.
+ - unfold list_length_z; simpl. split; eauto.
+ intros r; destruct r; simpl; congruence || auto.
+ * (* absurd case *)
+ erewrite list_nth_z_neg in * |-; [ congruence | rewrite Lhead; omega].
+ * (* absurd case *)
+ rewrite bblock_size_aux, Lhead in *. generalize (bblock_size_aux_pos bb). omega.
+ + (* absurd case *)
+ unfold list_length_z in BNDhead. simpl in *.
+ generalize (list_length_z_aux_increase _ l1 2); omega.
+Qed.
+
+Lemma eval_addressing_preserved a rs1 rs2:
+ (forall r : preg, r <> PC -> rs1 r = rs2 r) ->
+ eval_addressing lk a rs1 = Asm.eval_addressing tge a rs2.
+Proof.
+ intros EQ.
+ destruct a; simpl; try (rewrite !EQ; congruence). auto.
+Qed.
+
+Ltac next_stuck_cong := try (unfold Next, Stuck in *; congruence).
+
+Ltac inv_ok_eq :=
+ repeat match goal with
+ | [EQ: OK ?x = OK ?y |- _ ]
+ => inversion EQ; clear EQ; subst
+ end.
+
+Ltac reg_rwrt :=
+ match goal with
+ | [e: DR _ = DR _ |- _ ]
+ => rewrite e in *
+ end.
+
+Ltac destruct_reg_inv :=
+ repeat match goal with
+ | [ H : match ?reg with _ => _ end = _ |- _ ]
+ => simpl in *; destruct reg; try congruence; try inv_ok_eq; try reg_rwrt
+ end.
+
+Ltac destruct_ireg_inv :=
+ repeat match goal with
+ | [ H : match ?reg with _ => _ end = _ |- _ ]
+ => destruct reg as [[r|]|]; try congruence; try inv_ok_eq; subst
+ end.
+
+Ltac destruct_reg_size :=
+ simpl in *;
+ match goal with
+ | [ |- context [ match ?reg with _ => _ end ] ]
+ => destruct reg; try congruence
+ end.
+
+Ltac find_rwrt_ag :=
+ simpl in *;
+ match goal with
+ | [ AG: forall r, r <> ?PC -> _ r = _ r |- _ ]
+ => repeat rewrite <- AG; try congruence
+ end.
+
+Ltac inv_matchi :=
+ match goal with
+ | [ MATCHI : match_internal _ _ _ |- _ ]
+ => inversion MATCHI; subst; find_rwrt_ag
+ end.
+
+Ltac destruct_ir0_reg :=
+ match goal with
+ | [ |- context [ ir0 _ _ ?r ] ]
+ => unfold ir0 in *; destruct r; find_rwrt_ag; eauto
+ end.
+
+Ltac pc_not_sp :=
+ match goal with
+ | [ |- ?PC <> ?SP ]
+ => destruct (PregEq.eq SP PC); repeat congruence; discriminate
+ end.
+
+Ltac update_x_access_x :=
+ subst; rewrite !Pregmap.gss; auto.
+
+Ltac update_x_access_r :=
+ rewrite !Pregmap.gso; auto.
+
+Lemma nextinstr_agree_but_pc rs1 rs2: forall
+ (AG: forall r, r <> PC -> rs1 r = rs2 r),
+ forall r, r <> PC -> rs1 r = Asm.nextinstr rs2 r.
+Proof.
+ intros; unfold Asm.nextinstr in *; rewrite Pregmap.gso in *; eauto.
+Qed.
+
+Lemma ptrofs_nextinstr_agree rs1 rs2 n: forall
+ (BOUNDED : 0 <= n <= Ptrofs.max_unsigned)
+ (AGPC : Val.offset_ptr (rs1 PC) (Ptrofs.repr n) = rs2 PC),
+ Val.offset_ptr (rs1 PC) (Ptrofs.repr (n + 1)) = Asm.nextinstr rs2 PC.
+Proof.
+ intros; unfold Asm.nextinstr; rewrite Pregmap.gss.
+ rewrite <- Ptrofs.unsigned_one; rewrite <- (Ptrofs.unsigned_repr n); eauto;
+ rewrite <- Ptrofs.add_unsigned; rewrite <- Val.offset_ptr_assoc; rewrite AGPC; eauto.
+Qed.
+
+Lemma load_preserved n rs1 m1 rs1' m1' rs2 m2 rd chk f a: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (HLOAD: exec_load lk chk f a rd rs1 m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.exec_load tge chk f a rd rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold exec_load, Asm.exec_load in *.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ rewrite <- (eval_addressing_preserved a rs1 rs2); auto.
+ destruct (Mem.loadv _ _ _).
+ + inversion HLOAD; auto. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ destruct (PregEq.eq r rd); try update_x_access_x; try update_x_access_r.
+ * eapply ptrofs_nextinstr_agree; eauto.
+ + next_stuck_cong.
+Qed.
+
+Lemma store_preserved n rs1 m1 rs1' m1' rs2 m2 rd chk a: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (HSTORE: exec_store lk chk a rd rs1 m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.exec_store tge chk a rd rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold exec_store, Asm.exec_store in *.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ rewrite <- (eval_addressing_preserved a rs1 rs2); auto.
+ destruct (Mem.storev _ _ _ _).
+ + inversion HSTORE; auto. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ subst. apply EQR. auto.
+ * eapply ptrofs_nextinstr_agree; subst; eauto.
+ + next_stuck_cong.
+Qed.
+
+Lemma next_inst_preserved n rs1 m1 rs1' m1' rs2 m2 (x: dreg) v: forall
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (NEXTI: Next rs1 # x <- v m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem),
+ Next (Asm.nextinstr rs2 # x <- v) m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ inversion NEXTI. repeat (econstructor; eauto).
+ * eapply nextinstr_agree_but_pc; intros.
+ destruct (PregEq.eq r x); try update_x_access_x; try update_x_access_r.
+ * eapply ptrofs_nextinstr_agree; eauto.
+Qed.
+
+Lemma match_internal_nextinstr_switch:
+ forall n s rs2 m2 r v,
+ r <> PC ->
+ match_internal n s (State ((Asm.nextinstr rs2)#r <- v) m2) ->
+ match_internal n s (State (Asm.nextinstr (rs2#r <- v)) m2).
+Proof.
+ unfold Asm.nextinstr; intros n s rs2 m2 r v NOTPC1 MI.
+ inversion MI; subst; constructor; auto.
+ - eapply nextinstr_agree_but_pc; intros.
+ rewrite AG; try congruence.
+ destruct (PregEq.eq r r0); try update_x_access_x; try update_x_access_r.
+ - rewrite !Pregmap.gss, !Pregmap.gso; try congruence.
+ rewrite AGPC.
+ rewrite Pregmap.gso, Pregmap.gss; try congruence.
+Qed.
+
+Lemma match_internal_nextinstr_set_parallel:
+ forall n rs1 m1 rs2 m2 r v1 v2,
+ r <> PC ->
+ match_internal n (State rs1 m1) (State (Asm.nextinstr rs2) m2) ->
+ v1 = v2 ->
+ match_internal n (State (rs1#r <- v1) m1) (State (Asm.nextinstr (rs2#r <- v2)) m2).
+Proof.
+ intros; subst; eapply match_internal_nextinstr_switch; eauto.
+ intros; eapply match_internal_set_parallel; eauto.
+Qed.
+
+Lemma exec_basic_simulation:
+ forall tf n rs1 m1 rs1' m1' rs2 m2 bi tbi
+ (BOUNDED: 0 <= n <= Ptrofs.max_unsigned)
+ (BASIC: exec_basic lk ge bi rs1 m1 = Next rs1' m1')
+ (MATCHI: match_internal n (State rs1 m1) (State rs2 m2))
+ (TRANSBI: basic_to_instruction bi = OK tbi),
+ exists rs2' m2', Asm.exec_instr tge tf tbi
+ rs2 m2 = Next rs2' m2'
+ /\ match_internal (n + 1) (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ destruct bi.
+ { (* PArith *)
+ simpl in *; destruct i.
+ 1,2,3,4,5,6: (* PArithP, PArithPP, PArithPPP, PArithRR0R, PArithRR0, PArithARRRR0 *)
+ destruct i;
+ try (destruct sumbool_rec; try congruence);
+ try (monadInv TRANSBI);
+ try (destruct_reg_inv);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ try (repeat destruct_reg_size);
+ try (destruct_ir0_reg).
+ { (* PArithComparisonPP *)
+ destruct i;
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_inv);
+ simpl in *.
+ 1,2: (* compare_long *)
+ inversion BASIC; clear BASIC; subst;
+ eexists; eexists; split; eauto;
+ unfold compare_long;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+
+ destruct sz.
+ - (* compare_single *)
+ unfold compare_single in BASIC.
+ destruct (rs1 x), (rs1 x0);
+ inversion BASIC;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+ - (* compare_float *)
+ unfold compare_float in BASIC.
+ destruct (rs1 x), (rs1 x0);
+ inversion BASIC;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ 1,2: (* PArithComparisonR0R, PArithComparisonP *)
+ destruct i;
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_inv);
+ try (destruct_reg_size);
+ simpl in *;
+ inversion BASIC; clear BASIC; subst;
+ eexists; eexists; split; eauto;
+ unfold compare_long, compare_int, compare_float, compare_single;
+ try (destruct_reg_size);
+ repeat (eapply match_internal_nextinstr_set_parallel; [ congruence | idtac | try (rewrite !AG; congruence)]);
+ try (econstructor; eauto);
+ try (destruct_ir0_reg);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto).
+ { (* Pcset *)
+ try (monadInv TRANSBI);
+ try (inv_matchi).
+ try (exploit next_inst_preserved; eauto);
+ try (simpl in *; intros;
+ unfold if_opt_bool_val in *; unfold eval_testcond in *;
+ rewrite <- !AG; try congruence; eauto). }
+ { (* Pfmovi *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_size);
+ try (destruct_ir0_reg);
+ try (exploit next_inst_preserved; eauto). }
+ { (* Pcsel *)
+ try (destruct_reg_inv);
+ try (monadInv TRANSBI);
+ try (destruct_reg_inv);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ simpl in *; intros;
+ unfold if_opt_bool_val in *; unfold eval_testcond in *;
+ rewrite <- !AG; try congruence; eauto. }
+ { (* Pfnmul *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (destruct_reg_size);
+ try (exploit next_inst_preserved; eauto);
+ try (find_rwrt_ag). } }
+ { (* PLoad *)
+ destruct ld; monadInv TRANSBI; try destruct_ireg_inv; exploit load_preserved; eauto;
+ intros; simpl in *; destruct sz; eauto. }
+ { (* PStore *)
+ destruct st; monadInv TRANSBI; try destruct_ireg_inv; exploit store_preserved; eauto;
+ simpl in *; inv_matchi; find_rwrt_ag. }
+ { (* Pallocframe *)
+ monadInv TRANSBI;
+ inv_matchi; try pc_not_sp;
+ destruct sz eqn:EQSZ;
+ destruct Mem.alloc eqn:EQALLOC;
+ destruct Mem.store eqn:EQSTORE; inversion BASIC; try pc_not_sp;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ try (pc_not_sp; congruence) | idtac | try (reflexivity)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ { (* Pfreeframe *)
+ monadInv TRANSBI;
+ inv_matchi; try pc_not_sp;
+ destruct sz eqn:EQSZ;
+ destruct Mem.loadv eqn:EQLOAD;
+ destruct (rs1 SP) eqn:EQRS1SP;
+ try (destruct Mem.free eqn:EQFREE);
+ inversion BASIC; try pc_not_sp;
+ eexists; eexists; split; eauto;
+ repeat (eapply match_internal_nextinstr_set_parallel; [ try (pc_not_sp; congruence) | idtac | try (reflexivity)]);
+ try (econstructor; eauto);
+ try (eapply nextinstr_agree_but_pc; eauto);
+ try (eapply ptrofs_nextinstr_agree; eauto). }
+ 1,2,3,4: (* Ploadsymbol, Pcvtsw2x, Pcvtuw2x, Pcvtx2w *)
+ try (monadInv TRANSBI);
+ try (inv_matchi);
+ try (exploit next_inst_preserved; eauto);
+ rewrite symbol_addresses_preserved; eauto;
+ try (find_rwrt_ag).
+Qed.
+
+Lemma find_basic_instructions b ofs f bb tc: forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (UNFOLD: unfold (fn_blocks f) = OK tc),
+ forall n,
+ (n < length (body bb))%nat ->
+ exists (i : Asm.instruction) (bi : basic),
+ list_nth_z (body bb) (Z.of_nat n) = Some bi
+ /\ basic_to_instruction bi = OK i
+ /\ Asm.find_instr (Ptrofs.unsigned ofs
+ + (list_length_z (header bb))
+ + Z.of_nat n) tc
+ = Some i.
+Proof.
+ intros until n; intros NLT.
+ exploit internal_functions_unfold; eauto.
+ intros (tc' & FINDtf & TRANStf & _).
+ assert (tc' = tc) by congruence; subst.
+ exploit (find_instr_bblock (list_length_z (header bb) + Z.of_nat n)); eauto.
+ { unfold size; split.
+ - rewrite list_length_z_nat; omega.
+ - repeat (rewrite list_length_z_nat). repeat (rewrite Nat2Z.inj_add). omega. }
+ intros (i & NTH & FIND_INSTR).
+ exists i; intros.
+ inv NTH.
+ - (* absurd *) apply list_nth_z_range in H; omega.
+ - exists bi;
+ rewrite Z.add_simpl_l in H;
+ rewrite Z.add_assoc in FIND_INSTR;
+ intuition.
+ - (* absurd *) rewrite bblock_size_aux in H0;
+ rewrite H in H0; simpl in H0; repeat rewrite list_length_z_nat in H0; omega.
+Qed.
+
+(** "is_tail" auxiliary lemma about is_tail to move in IterList ou Coqlib (déplacer aussi Machblockgenproof.is_tail_app_inv) ? *)
+
+Lemma is_tail_app_right A (l2 l1: list A): is_tail l1 (l2++l1).
+Proof.
+ intros; eapply Machblockgenproof.is_tail_app_inv; econstructor.
+Qed.
+
+Lemma is_tail_app_def A (l1 l2: list A):
+ is_tail l1 l2 -> exists l3, l2 = l3 ++ l1.
+Proof.
+ induction 1 as [|x l1 l2]; simpl.
+ - exists nil; simpl; auto.
+ - destruct IHis_tail as (l3 & EQ); rewrite EQ.
+ exists (x::l3); simpl; auto.
+Qed.
+
+Lemma is_tail_bound A (l1 l2: list A):
+ is_tail l1 l2 -> (length l1 <= length l2)%nat.
+Proof.
+ intros H; destruct (is_tail_app_def _ _ _ H) as (l3 & EQ).
+ subst; rewrite app_length.
+ omega.
+Qed.
+
+Lemma is_tail_list_nth_z A (l1 l2: list A):
+ is_tail l1 l2 -> list_nth_z l2 ((list_length_z l2) - (list_length_z l1)) = list_nth_z l1 0.
+Proof.
+ induction 1; simpl.
+ - replace (list_length_z c - list_length_z c) with 0; omega || auto.
+ - assert (X: list_length_z (i :: c2) > list_length_z c1).
+ { rewrite !list_length_z_nat, <- Nat2Z.inj_gt.
+ exploit is_tail_bound; simpl; eauto.
+ omega. }
+ destruct (zeq (list_length_z (i :: c2) - list_length_z c1) 0) as [Y|Y]; try omega.
+ replace (Z.pred (list_length_z (i :: c2) - list_length_z c1)) with (list_length_z c2 - list_length_z c1); auto.
+ rewrite list_length_z_cons.
+ omega.
+Qed.
+
+(* TODO: remplacer find_basic_instructions directement par ce lemme ? *)
+Lemma find_basic_instructions_alt b ofs f bb tc n: forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (UNFOLD: unfold (fn_blocks f) = OK tc)
+ (BOUND: 0 <= n < list_length_z (body bb)),
+ exists (i : Asm.instruction) (bi : basic),
+ list_nth_z (body bb) n = Some bi
+ /\ basic_to_instruction bi = OK i
+ /\ Asm.find_instr (Ptrofs.unsigned ofs
+ + (list_length_z (header bb))
+ + n) tc
+ = Some i.
+Proof.
+ intros; assert ((Z.to_nat n) < length (body bb))%nat.
+ { rewrite Nat2Z.inj_lt, <- list_length_z_nat, Z2Nat.id; try omega. }
+ exploit find_basic_instructions; eauto.
+ rewrite Z2Nat.id; try omega. intros (i & bi & X).
+ eexists; eexists; intuition eauto.
+Qed.
+
+Lemma header_body_tail_bound: forall (a: basic) (li: list basic) bb ofs
+ (BOUNDBB : Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ (BDYLENPOS : 0 <= list_length_z (body bb) - list_length_z (a :: li) <
+ list_length_z (body bb)),
+0 <= list_length_z (header bb) + list_length_z (body bb) - list_length_z (a :: li) <=
+Ptrofs.max_unsigned.
+Proof.
+ intros.
+ assert (HBBPOS: list_length_z (header bb) >= 0) by eapply list_length_z_pos.
+ assert (HBBSIZE: list_length_z (header bb) < size bb) by eapply header_size_lt_block_size.
+ assert (OFSBOUND: 0 <= Ptrofs.unsigned ofs <= Ptrofs.max_unsigned) by eapply Ptrofs.unsigned_range_2.
+ assert (BBSIZE: size bb <= Ptrofs.max_unsigned) by omega.
+ unfold size in BBSIZE.
+ rewrite !Nat2Z.inj_add in BBSIZE.
+ rewrite <- !list_length_z_nat in BBSIZE.
+ omega.
+Qed.
+
+(* A more general version of the exec_body_simulation_plus lemma below.
+ This generalization is necessary for the induction proof inside the body.
+*)
+Lemma exec_body_simulation_plus_gen li: forall b ofs f bb rs m s2 rs' m'
+ (BLI: is_tail li (body bb))
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_BODY: li <> nil)
+ (MATCHI: match_internal ((list_length_z (header bb)) + (list_length_z (body bb)) - (list_length_z li)) (State rs m) s2)
+ (BODY: exec_body lk ge li rs m = Next rs' m'),
+ exists s2', plus Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ induction li as [|a li]; simpl; try congruence.
+ intros.
+ assert (BDYLENPOS: 0 <= (list_length_z (body bb) - list_length_z (a::li)) < list_length_z (body bb)). {
+ assert (Z.of_nat O < list_length_z (a::li) <= list_length_z (body bb)); try omega.
+ rewrite !list_length_z_nat; split.
+ - rewrite <- Nat2Z.inj_lt. simpl. omega.
+ - rewrite <- Nat2Z.inj_le; eapply is_tail_bound; eauto.
+ }
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+ exploit find_basic_instructions_alt; eauto.
+ intros (tbi & (bi & (NTHBI & TRANSBI & FIND_INSTR))).
+ exploit is_tail_list_nth_z; eauto.
+ rewrite NTHBI; simpl.
+ intros X; inversion X; subst; clear X NTHBI.
+ destruct (exec_basic _ _ _ _ _) eqn:EXEC_BASIC; next_stuck_cong.
+ destruct s as (rs1 & m1); simpl in *.
+ destruct s2 as (rs2 & m2); simpl in *.
+ assert (BOUNDBBMAX: Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ by (eapply size_of_blocks_bounds; eauto).
+ exploit header_body_tail_bound; eauto. intros BDYTAIL.
+ exploit exec_basic_simulation; eauto.
+ intros (rs_next' & m_next' & EXEC_INSTR & MI_NEXT).
+ exploit exec_basic_dont_move_PC; eauto. intros AGPC.
+ inversion MI_NEXT as [A B C D E M_NEXT_AGREE RS_NEXT_AGREE ATPC_NEXT PC_OFS_NEXT RS RS'].
+ subst A. subst B. subst C. subst D. subst E.
+ rewrite ATPC in AGPC. symmetry in AGPC, ATPC_NEXT.
+
+ inv MATCHI. symmetry in AGPC0.
+ rewrite ATPC in AGPC0.
+ unfold Val.offset_ptr in AGPC0.
+
+ simpl in FIND_INSTR.
+ (* Execute internal step. *)
+ exploit (Asm.exec_step_internal tge b); eauto.
+ {
+ rewrite Ptrofs.add_unsigned.
+ repeat (rewrite Ptrofs.unsigned_repr); try omega.
+ 2: {
+ assert (BOUNDOFS: 0 <= Ptrofs.unsigned ofs <= Ptrofs.max_unsigned) by eapply Ptrofs.unsigned_range_2.
+ assert (list_length_z (body bb) <= size bb) by eapply body_size_le_block_size.
+ assert (list_length_z (header bb) <= 1). { eapply size_header; eauto. }
+ omega. }
+ try rewrite list_length_z_nat; try split;
+ simpl; rewrite <- !list_length_z_nat;
+ replace (Ptrofs.unsigned ofs + (list_length_z (header bb) + list_length_z (body bb) -
+ list_length_z (a :: li))) with (Ptrofs.unsigned ofs + list_length_z (header bb) +
+ (list_length_z (body bb) - list_length_z (a :: li))) by omega;
+ try assumption; try omega. }
+
+ (* This is our STEP hypothesis. *)
+ intros STEP_NEXT.
+ destruct li as [|a' li]; simpl in *.
+ - (* case of a single instruction in li: this our base case in the induction *)
+ inversion BODY; subst.
+ eexists; split.
+ + apply plus_one. eauto.
+ + constructor; auto.
+ rewrite ATPC_NEXT.
+ apply f_equal.
+ apply f_equal.
+ rewrite bblock_size_aux, list_length_z_cons; simpl.
+ omega.
+ - exploit (IHli b ofs f bb rs1 m_next' (State rs_next' m_next')); congruence || eauto.
+ + exploit is_tail_app_def; eauto.
+ intros (l3 & EQ); rewrite EQ.
+ exploit (is_tail_app_right _ (l3 ++ a::nil)).
+ rewrite <- app_assoc; simpl; eauto.
+ + constructor; auto.
+ rewrite ATPC_NEXT.
+ apply f_equal.
+ apply f_equal.
+ rewrite! list_length_z_cons; simpl.
+ omega.
+ + intros (s2' & LAST_STEPS & LAST_MATCHS).
+ eexists. split; eauto.
+ eapply plus_left'; eauto.
+Qed.
+
+Lemma exec_body_simulation_plus b ofs f bb rs m s2 rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_BODY: body bb <> nil)
+ (MATCHI: match_internal (list_length_z (header bb)) (State rs m) s2)
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ exists s2', plus Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ intros.
+ exploit exec_body_simulation_plus_gen; eauto.
+ - constructor.
+ - replace (list_length_z (header bb) + list_length_z (body bb) - list_length_z (body bb)) with (list_length_z (header bb)); auto.
+ omega.
+Qed.
+
+Lemma exec_body_simulation_star b ofs f bb rs m s2 rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (MATCHI: match_internal (list_length_z (header bb)) (State rs m) s2)
+ (BODY: exec_body lk ge (body bb) rs m = Next rs' m'),
+ exists s2', star Asm.step tge s2 E0 s2'
+ /\ match_internal (size bb - (Z.of_nat (length_opt (exit bb)))) (State rs' m') s2'.
+Proof.
+ intros.
+ destruct (body bb) eqn: Hbb.
+ - simpl in BODY. inv BODY.
+ eexists. split.
+ eapply star_refl; eauto.
+ assert (EQ: (size bb - Z.of_nat (length_opt (exit bb))) = list_length_z (header bb)).
+ { rewrite bblock_size_aux. rewrite Hbb; unfold list_length_z; simpl. omega. }
+ rewrite EQ; eauto.
+ - exploit exec_body_simulation_plus; congruence || eauto.
+ { rewrite Hbb; eauto. }
+ intros (s2' & PLUS & MATCHI').
+ eexists; split; eauto.
+ eapply plus_star; eauto.
+Qed.
+
+Lemma list_nth_z_range_exceeded A (l : list A) n:
+ n >= list_length_z l ->
+ list_nth_z l n = None.
+Proof.
+ intros N.
+ remember (list_nth_z l n) as opt eqn:H. symmetry in H.
+ destruct opt; auto.
+ exploit list_nth_z_range; eauto. omega.
+Qed.
+
+Lemma label_in_header_list lbl a:
+ is_label lbl a = true -> list_length_z (header a) <= 1 -> header a = lbl :: nil.
+Proof.
+ intros.
+ eapply is_label_correct_true in H.
+ destruct (header a).
+ - eapply in_nil in H. contradiction.
+ - rewrite list_length_z_cons in H0.
+ assert (list_length_z l0 >= 0) by eapply list_length_z_pos.
+ assert (list_length_z l0 = 0) by omega.
+ rewrite list_length_z_nat in H2.
+ assert (Datatypes.length l0 = 0%nat) by omega.
+ eapply length_zero_iff_nil in H3. subst.
+ unfold In in H. destruct H.
+ + subst; eauto.
+ + destruct H.
+Qed.
+
+Lemma no_label_in_basic_inst: forall a lbl x,
+ basic_to_instruction a = OK x -> Asm.is_label lbl x = false.
+Proof.
+ intros.
+ destruct a; simpl in *;
+ repeat destruct i; simpl in *;
+ try (try destruct_reg_inv; monadInv H; simpl in *; reflexivity).
+Qed.
+
+Lemma label_pos_body bdy: forall c1 c2 z ex lbl
+ (HUNF : unfold_body bdy = OK c2),
+ Asm.label_pos lbl (z + Z.of_nat ((Datatypes.length bdy) + length_opt ex)) c1 = Asm.label_pos lbl (z) ((c2 ++ unfold_exit ex) ++ c1).
+Proof.
+ induction bdy.
+ - intros. inversion HUNF. simpl in *.
+ destruct ex eqn:EQEX.
+ + simpl in *. unfold Asm.is_label. destruct c; simpl; try congruence.
+ destruct i; simpl; try congruence.
+ + simpl in *. ring_simplify (z + 0). auto.
+ - intros. inversion HUNF; clear HUNF. monadInv H0. simpl in *.
+ erewrite no_label_in_basic_inst; eauto. rewrite <- IHbdy; eauto.
+ erewrite Zpos_P_of_succ_nat.
+ apply f_equal2; auto. omega.
+Qed.
+
+Lemma asm_label_pos_header: forall z a x0 x1 lbl
+ (HUNF: unfold_body (body a) = OK x1),
+ Asm.label_pos lbl (z + size a) x0 =
+ Asm.label_pos lbl (z + list_length_z (header a)) ((x1 ++ unfold_exit (exit a)) ++ x0).
+Proof.
+ intros.
+ unfold size.
+ rewrite <- plus_assoc. rewrite Nat2Z.inj_add.
+ rewrite list_length_z_nat.
+ replace (z + (Z.of_nat (Datatypes.length (header a)) + Z.of_nat (Datatypes.length (body a) + length_opt (exit a)))) with (z + Z.of_nat (Datatypes.length (header a)) + Z.of_nat (Datatypes.length (body a) + length_opt (exit a))) by omega.
+ eapply (label_pos_body (body a) x0 x1 (z + Z.of_nat (Datatypes.length (header a))) (exit a) lbl). auto.
+Qed.
+
+Lemma header_size_cons_nil: forall (l0: label) (l1: list label)
+ (HSIZE: list_length_z (l0 :: l1) <= 1),
+ l1 = nil.
+Proof.
+ intros.
+ destruct l1; try congruence. rewrite !list_length_z_cons in HSIZE.
+ assert (list_length_z l1 >= 0) by eapply list_length_z_pos.
+ assert (list_length_z l1 + 1 + 1 >= 2) by omega.
+ assert (2 <= 1) by omega. contradiction H1. omega.
+Qed.
+
+Lemma label_pos_preserved_gen bbs: forall lbl c z
+ (HUNF: unfold bbs = OK c),
+ label_pos lbl z bbs = Asm.label_pos lbl z c.
+Proof.
+ induction bbs.
+ - intros. simpl in *. inversion HUNF. simpl. reflexivity.
+ - intros. simpl in *. monadInv HUNF. unfold unfold_bblock in EQ.
+ destruct (zle _ _); try congruence. monadInv EQ.
+ destruct (is_label _ _) eqn:EQLBL.
+ + erewrite label_in_header_list; eauto.
+ simpl in *. destruct (peq lbl lbl); try congruence.
+ + erewrite IHbbs; eauto.
+ rewrite (asm_label_pos_header z a x0 x1 lbl); auto.
+ unfold is_label in *.
+ destruct (header a).
+ * replace (z + list_length_z (@nil label)) with (z); eauto.
+ unfold list_length_z. simpl. omega.
+ * eapply header_size_cons_nil in l as HL1.
+ subst. simpl in *. destruct (in_dec _ _); try congruence.
+ simpl in *.
+ destruct (peq _ _); try intuition congruence.
+Qed.
+
+Lemma label_pos_preserved f lbl z tf: forall
+ (FINDF: transf_function f = OK tf),
+ label_pos lbl z (fn_blocks f) = Asm.label_pos lbl z (Asm.fn_code tf).
+Proof.
+ intros.
+ eapply label_pos_preserved_gen.
+ unfold transf_function in FINDF. monadInv FINDF.
+ destruct zlt; try congruence. inversion EQ0. eauto.
+Qed.
+
+Lemma goto_label_preserved bb rs1 m1 rs1' m1' rs2 m2 lbl f tf v: forall
+ (FINDF: transf_function f = OK tf)
+ (BOUNDED: size bb <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2))
+ (HGOTO: goto_label f lbl (incrPC v rs1) m1 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem), Asm.goto_label tf lbl rs2 m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ unfold goto_label, Asm.goto_label in *.
+ rewrite <- (label_pos_preserved f); auto.
+ inversion MATCHI as [n0 r1 mx1 r2 mx2 EQM EQR EQPC]; subst.
+ destruct label_pos; next_stuck_cong.
+ destruct (incrPC v rs1 PC) eqn:INCRPC; next_stuck_cong.
+ inversion HGOTO; auto. repeat (econstructor; eauto).
+ rewrite <- EQPC.
+ unfold incrPC in *.
+ rewrite !Pregmap.gss in *.
+ destruct (rs1 PC) eqn:EQRS1; simpl in *; try congruence.
+ replace (rs2 # PC <- (Vptr b0 (Ptrofs.repr z))) with ((rs1 # PC <- (Vptr b0 (Ptrofs.add i0 v))) # PC <- (Vptr b (Ptrofs.repr z))); auto.
+ eapply functional_extensionality. intros.
+ destruct (PregEq.eq x PC); subst.
+ rewrite !Pregmap.gss. congruence.
+ rewrite !Pregmap.gso; auto.
+Qed.
+
+Lemma next_inst_incr_pc_preserved bb rs1 m1 rs1' m1' rs2 m2 f tf: forall
+ (FINDF: transf_function f = OK tf)
+ (BOUNDED: size bb <= Ptrofs.max_unsigned)
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2))
+ (NEXT: Next (incrPC (Ptrofs.repr (size bb)) rs1) m2 = Next rs1' m1'),
+ exists (rs2' : regset) (m2' : mem),
+ Next (Asm.nextinstr rs2) m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros; simpl in *; unfold incrPC in NEXT;
+ inv_matchi;
+ assert (size bb >= 1) by eapply bblock_size_pos;
+ assert (0 <= size bb - 1 <= Ptrofs.max_unsigned) by omega;
+ inversion NEXT; subst;
+ eexists; eexists; split; eauto.
+ assert (rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))) = Asm.nextinstr rs2). {
+ unfold Pregmap.set. apply functional_extensionality.
+ intros x. destruct (PregEq.eq x PC).
+ -- unfold Asm.nextinstr. rewrite <- AGPC.
+ rewrite Val.offset_ptr_assoc. rewrite Ptrofs.add_unsigned.
+ rewrite (Ptrofs.unsigned_repr (size bb - 1)); try omega.
+ rewrite Ptrofs.unsigned_one.
+ replace (size bb - 1 + 1) with (size bb) by omega.
+ rewrite e. rewrite Pregmap.gss.
+ reflexivity.
+ -- eapply nextinstr_agree_but_pc; eauto. }
+ rewrite H1. econstructor.
+Qed.
+
+Lemma pc_reg_overwrite: forall (r: ireg) rs1 m1 rs2 m2 bb
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2)),
+ rs2 # PC <- (rs2 r) =
+ (rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb)))) # PC <-
+ (rs1 r).
+Proof.
+ intros.
+ unfold Pregmap.set; apply functional_extensionality.
+ intros x; destruct (PregEq.eq x PC) as [X | X]; try discriminate; inv_matchi.
+Qed.
+
+Lemma exec_cfi_simulation:
+ forall bb f tf rs1 m1 rs1' m1' rs2 m2 cfi
+ (SIZE: size bb <= Ptrofs.max_unsigned)
+ (FINDF: transf_function f = OK tf)
+ (* Warning: Asmblock's PC is assumed to be already pointing on the next instruction ! *)
+ (CFI: exec_cfi ge f cfi (incrPC (Ptrofs.repr (size bb)) rs1) m1 = Next rs1' m1')
+ (MATCHI: match_internal (size bb - 1) (State rs1 m1) (State rs2 m2)),
+ exists rs2' m2', Asm.exec_instr tge tf (cf_instruction_to_instruction cfi)
+ rs2 m2 = Next rs2' m2'
+ /\ match_states (State rs1' m1') (State rs2' m2').
+Proof.
+ intros.
+ assert (BBPOS: size bb >= 1) by eapply bblock_size_pos.
+ destruct cfi; inv CFI; simpl.
+ - (* Pb *)
+ exploit goto_label_preserved; eauto.
+ - (* Pbc *)
+ inv_matchi.
+ unfold eval_testcond in *. destruct c;
+ erewrite !incrPC_agree_but_pc in H0; try rewrite <- !AG; try congruence.
+ all:
+ destruct_reg_size;
+ try destruct b eqn:EQB.
+ 1,4,7,10,13,16,19,22,25,28,31,34:
+ exploit goto_label_preserved; eauto.
+ 1,3,5,7,9,11,13,15,17,19,21,23:
+ exploit next_inst_incr_pc_preserved; eauto.
+ all: repeat (econstructor; eauto).
+ - (* Pbl *)
+ eexists; eexists; split; eauto.
+ assert ( ((incrPC (Ptrofs.repr (size bb)) rs1) # X30 <- (incrPC (Ptrofs.repr (size bb)) rs1 PC))
+ # PC <- (Genv.symbol_address ge id Ptrofs.zero)
+ = (rs2 # X30 <- (Val.offset_ptr (rs2 PC) Ptrofs.one))
+ # PC <- (Genv.symbol_address tge id Ptrofs.zero)
+ ) as EQRS. {
+ unfold incrPC. unfold Pregmap.set. simpl. apply functional_extensionality.
+ intros x. destruct (PregEq.eq x PC).
+ * rewrite symbol_addresses_preserved. reflexivity.
+ * destruct (PregEq.eq x X30).
+ -- inv MATCHI. rewrite <- AGPC. rewrite Val.offset_ptr_assoc.
+ unfold Ptrofs.add, Ptrofs.one. repeat (rewrite Ptrofs.unsigned_repr); try omega.
+ replace (size bb - 1 + 1) with (size bb) by omega. reflexivity.
+ -- inv MATCHI; rewrite AG; try assumption; reflexivity.
+ } rewrite EQRS; inv MATCHI; reflexivity.
+ - (* Pbs *)
+ eexists; eexists; split; eauto.
+ assert ( (incrPC (Ptrofs.repr (size bb)) rs1) # PC <-
+ (Genv.symbol_address ge id Ptrofs.zero)
+ = rs2 # PC <- (Genv.symbol_address tge id Ptrofs.zero)
+ ) as EQRS. {
+ unfold incrPC, Pregmap.set. rewrite symbol_addresses_preserved. inv MATCHI.
+ apply functional_extensionality. intros x. destruct (PregEq.eq x PC); auto.
+ } rewrite EQRS; inv MATCHI; reflexivity.
+ - (* Pblr *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gss. rewrite Pregmap.gso; try discriminate.
+ assert ( (rs2 # X30 <- (Val.offset_ptr (rs2 PC) Ptrofs.one)) # PC <- (rs2 r)
+ = ((rs1 # PC <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))))
+ # X30 <- (Val.offset_ptr (rs1 PC) (Ptrofs.repr (size bb))))
+ # PC <- (rs1 r)
+ ) as EQRS. {
+ unfold Pregmap.set. apply functional_extensionality.
+ intros x; destruct (PregEq.eq x PC) as [X | X].
+ - inv_matchi; rewrite AG; auto.
+ - destruct (PregEq.eq x X30) as [X' | X'].
+ + inversion MATCHI; subst. rewrite <- AGPC.
+ rewrite Val.offset_ptr_assoc. unfold Ptrofs.one.
+ rewrite Ptrofs.add_unsigned. rewrite Ptrofs.unsigned_repr; try omega. rewrite Ptrofs.unsigned_repr; try omega.
+ rewrite Z.sub_add; reflexivity.
+ + inv_matchi.
+ } rewrite EQRS. inv_matchi.
+ - (* Pbr *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gso; try discriminate.
+ rewrite (pc_reg_overwrite r rs1 m1' rs2 m2 bb); auto.
+ inv_matchi.
+ - (* Pret *)
+ eexists; eexists; split; eauto.
+ unfold incrPC. rewrite Pregmap.gso; try discriminate.
+ rewrite (pc_reg_overwrite r rs1 m1' rs2 m2 bb); auto.
+ inv_matchi.
+ - (* Pcbnz *)
+ inv_matchi.
+ unfold eval_neg_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testzero; next_stuck_cong.
+ destruct b.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ * exploit goto_label_preserved; eauto.
+ - (* Pcbz *)
+ inv_matchi.
+ unfold eval_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testzero; next_stuck_cong.
+ destruct b.
+ * exploit goto_label_preserved; eauto.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ - (* Ptbnbz *)
+ inv_matchi.
+ unfold eval_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testbit; next_stuck_cong.
+ destruct b.
+ * exploit goto_label_preserved; eauto.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ - (* Ptbz *)
+ inv_matchi.
+ unfold eval_neg_branch in *.
+ erewrite incrPC_agree_but_pc in H0; try congruence.
+ destruct eval_testbit; next_stuck_cong.
+ destruct b.
+ * exploit next_inst_incr_pc_preserved; eauto.
+ * exploit goto_label_preserved; eauto.
+ - (* Pbtbl *)
+ assert (rs2 # X16 <- Vundef r1 = (incrPC (Ptrofs.repr (size bb)) rs1) # X16 <- Vundef r1)
+ as EQUNDEFX16. {
+ unfold incrPC, Pregmap.set.
+ destruct (PregEq.eq r1 X16) as [X16 | X16]; auto.
+ destruct (PregEq.eq r1 PC) as [PC' | PC']; try discriminate.
+ inv MATCHI; rewrite AG; auto.
+ } rewrite <- EQUNDEFX16 in H0.
+ destruct_reg_inv; next_stuck_cong.
+ unfold goto_label, Asm.goto_label in *.
+ rewrite <- (label_pos_preserved f); auto.
+ inversion MATCHI; subst.
+ destruct label_pos; next_stuck_cong.
+ destruct (((incrPC (Ptrofs.repr (size bb)) rs1) # X16 <- Vundef) # X17 <- Vundef PC) eqn:INCRPC; next_stuck_cong.
+ inversion H0; auto. repeat (econstructor; eauto).
+ rewrite !Pregmap.gso; try congruence.
+ rewrite <- AGPC.
+ unfold incrPC in *.
+ destruct (rs1 PC) eqn:EQRS1; simpl in *; try discriminate.
+ replace (((rs2 # X16 <- Vundef) # X17 <- Vundef) # PC <- (Vptr b0 (Ptrofs.repr z))) with
+ ((((rs1 # PC <- (Vptr b0 (Ptrofs.add i1 (Ptrofs.repr (size bb))))) # X16 <-
+ Vundef) # X17 <- Vundef) # PC <- (Vptr b (Ptrofs.repr z))); auto.
+ eapply functional_extensionality; intros x.
+ destruct (PregEq.eq x PC); subst.
+ + rewrite Pregmap.gso in INCRPC; try congruence.
+ rewrite Pregmap.gso in INCRPC; try congruence.
+ rewrite Pregmap.gss in INCRPC.
+ rewrite !Pregmap.gss in *; congruence.
+ + rewrite Pregmap.gso; auto.
+ rewrite (Pregmap.gso (i := x) (j := PC)); auto.
+ destruct (PregEq.eq x X17); subst.
+ * rewrite !Pregmap.gss; auto.
+ * rewrite !(Pregmap.gso (i := x) (j:= X17)); auto. destruct (PregEq.eq x X16); subst.
+ -- rewrite !Pregmap.gss; auto.
+ -- rewrite !Pregmap.gso; auto.
+Qed.
+
+Lemma last_instruction_cannot_be_label bb:
+ list_nth_z (header bb) (size bb - 1) = None.
+Proof.
+ assert (list_length_z (header bb) <= size bb - 1). {
+ rewrite bblock_size_aux. generalize (bblock_size_aux_pos bb). omega.
+ }
+ remember (list_nth_z (header bb) (size bb - 1)) as label_opt; destruct label_opt; auto;
+ exploit list_nth_z_range; eauto; omega.
+Qed.
+
+Lemma pc_ptr_exec_step: forall ofs bb b rs m _rs _m
+ (ATPC : rs PC = Vptr b ofs)
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |}),
+ _rs PC = Vptr b (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))).
+Proof.
+ intros; inv MATCHI. rewrite <- AGPC; rewrite ATPC; unfold Val.offset_ptr; eauto.
+Qed.
+
+Lemma find_instr_ofs_somei: forall ofs bb f tc asmi rs m _rs _m
+ (BOUNDOFS : Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned)
+ (FIND_INSTR : Asm.find_instr (Ptrofs.unsigned ofs + (size bb - 1)) tc =
+ Some (asmi))
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |}),
+ Asm.find_instr (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))))
+ (Asm.fn_code {| Asm.fn_sig := fn_sig f; Asm.fn_code := tc |}) =
+ Some (asmi).
+Proof.
+ intros; simpl.
+ replace (Ptrofs.unsigned (Ptrofs.add ofs (Ptrofs.repr (size bb - 1))))
+ with (Ptrofs.unsigned ofs + (size bb - 1)); try assumption.
+ generalize (bblock_size_pos bb); generalize (Ptrofs.unsigned_range_2 ofs); intros.
+ unfold Ptrofs.add.
+ rewrite Ptrofs.unsigned_repr. rewrite Ptrofs.unsigned_repr; try omega.
+ rewrite Ptrofs.unsigned_repr; omega.
+Qed.
+
+Lemma eval_builtin_arg_match: forall rs _m _rs a1 b1
+ (AG : forall r : preg, r <> PC -> rs r = _rs r)
+ (EVAL : eval_builtin_arg tge (fun r : dreg => rs r) (rs SP) _m a1 b1),
+ eval_builtin_arg tge _rs (_rs SP) _m (map_builtin_arg DR a1) b1.
+Proof.
+ intros; induction EVAL; simpl in *; try rewrite AG; try rewrite AG in EVAL; try discriminate; try congruence; eauto with barg.
+ econstructor. rewrite <- AG; try discriminate; auto.
+Qed.
+
+Lemma eval_builtin_args_match: forall bb rs m _rs _m args vargs
+ (MATCHI : match_internal (size bb - 1)
+ {| _rs := rs; _m := m |}
+ {| _rs := _rs; _m := _m |})
+ (EVAL : eval_builtin_args tge (fun r : dreg => rs r) (rs SP) m args vargs),
+ eval_builtin_args tge _rs (_rs SP) _m (map (map_builtin_arg DR) args) vargs.
+Proof.
+ intros; inv MATCHI.
+ induction EVAL; subst.
+ - econstructor.
+ - econstructor.
+ + eapply eval_builtin_arg_match; eauto.
+ + eauto.
+Qed.
+
+Lemma pc_both_sides: forall (rs _rs: regset) v
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ rs # PC <- v = _rs # PC <- v.
+Proof.
+ intros; unfold Pregmap.set; apply functional_extensionality; intros y.
+ destruct (PregEq.eq y PC); try rewrite AG; eauto.
+Qed.
+
+Lemma set_buitin_res_sym res: forall vres rs _rs r
+ (NPC: r <> PC)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ set_res res vres rs r = set_res res vres _rs r.
+Proof.
+ induction res; simpl; intros; unfold Pregmap.set; try rewrite AG; eauto.
+Qed.
+
+Lemma set_builtin_res_dont_move_pc_gen res: forall vres rs _rs v1 v2
+ (HV: v1 = v2)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ (set_res res vres rs) # PC <- v1 =
+ (set_res res vres _rs) # PC <- v2.
+Proof.
+ intros. rewrite HV. generalize res vres rs _rs AG v2.
+ clear res vres rs _rs AG v1 v2 HV.
+ induction res.
+ - simpl; intros. apply pc_both_sides; intros.
+ unfold Pregmap.set; try rewrite AG; eauto.
+ - simpl; intros; apply pc_both_sides; eauto.
+ - simpl; intros.
+ erewrite IHres2; eauto; intros.
+ eapply set_buitin_res_sym; eauto.
+Qed.
+
+Lemma set_builtin_map_not_pc (res: builtin_res dreg): forall vres rs,
+ set_res (map_builtin_res DR res) vres rs PC = rs PC.
+Proof.
+ induction res.
+ - intros; simpl. unfold Pregmap.set. destruct (PregEq.eq PC x); try congruence.
+ - intros; simpl; congruence.
+ - intros; simpl in *. rewrite IHres2. rewrite IHres1. reflexivity.
+Qed.
+
+Lemma undef_reg_preserved (rl: list mreg): forall rs _rs r
+ (NPC: r <> PC)
+ (AG : forall r : preg, r <> PC -> rs r = _rs r),
+ undef_regs (map preg_of rl) rs r = undef_regs (map preg_of rl) _rs r.
+Proof.
+ induction rl.
+ - simpl; auto.
+ - simpl; intros. erewrite IHrl; eauto.
+ intros. unfold Pregmap.set. destruct (PregEq.eq r0 (preg_of a)); try rewrite AG; eauto.
+Qed.
+
+Lemma undef_regs_other:
+ forall r rl rs,
+ (forall r', In r' rl -> r <> r') ->
+ undef_regs rl rs r = rs r.
+Proof.
+ induction rl; simpl; intros. auto.
+ rewrite IHrl by auto. rewrite Pregmap.gso; auto.
+Qed.
+
+Fixpoint preg_notin (r: preg) (rl: list mreg) : Prop :=
+ match rl with
+ | nil => True
+ | r1 :: nil => r <> preg_of r1
+ | r1 :: rl => r <> preg_of r1 /\ preg_notin r rl
+ end.
+
+Remark preg_notin_charact:
+ forall r rl,
+ preg_notin r rl <-> (forall mr, In mr rl -> r <> preg_of mr).
+Proof.
+ induction rl; simpl; intros.
+ tauto.
+ destruct rl.
+ simpl. split. intros. intuition congruence. auto.
+ rewrite IHrl. split.
+ intros [A B]. intros. destruct H. congruence. auto.
+ auto.
+Qed.
+
+Lemma undef_regs_other_2:
+ forall r rl rs,
+ preg_notin r rl ->
+ undef_regs (map preg_of rl) rs r = rs r.
+Proof.
+ intros. apply undef_regs_other. intros.
+ exploit list_in_map_inv; eauto. intros [mr [A B]]. subst.
+ rewrite preg_notin_charact in H. auto.
+Qed.
+
+Lemma exec_exit_simulation_plus b ofs f bb s2 t rs m rs' m': forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (NEMPTY_EXIT: exit bb <> None)
+ (MATCHI: match_internal (size bb - Z.of_nat (length_opt (exit bb))) (State rs m) s2)
+ (EXIT: exec_exit ge f (Ptrofs.repr (size bb)) rs m (exit bb) t rs' m')
+ (ATPC: rs PC = Vptr b ofs),
+ plus Asm.step tge s2 t (State rs' m').
+Proof.
+ intros.
+ exploit internal_functions_unfold; eauto.
+ intros (tc & FINDtf & TRANStf & _).
+
+ exploit (find_instr_bblock (size bb - 1)); eauto.
+ { generalize (bblock_size_pos bb). omega. }
+ intros (i' & NTH & FIND_INSTR).
+
+ inv NTH.
+ + rewrite last_instruction_cannot_be_label in *. discriminate.
+ + destruct (exit bb) as [ctrl |] eqn:NEMPTY_EXIT'. 2: { contradiction. }
+ rewrite bblock_size_aux in *. rewrite NEMPTY_EXIT' in *. simpl in *.
+ (* XXX: Is there a better way to simplify this expression i.e. automatically? *)
+ replace (list_length_z (header bb) + list_length_z (body bb) + 1 - 1 -
+ list_length_z (header bb)) with (list_length_z (body bb)) in H by omega.
+ rewrite list_nth_z_range_exceeded in H; try omega. discriminate.
+ + assert (Ptrofs.unsigned ofs + size bb <= Ptrofs.max_unsigned). {
+ eapply size_of_blocks_bounds; eauto.
+ }
+ assert (size bb <= Ptrofs.max_unsigned). { generalize (Ptrofs.unsigned_range_2 ofs); omega. }
+ destruct cfi.
+ * (* control flow instruction *)
+ destruct s2.
+ rewrite H in EXIT. (* exit bb is a cfi *)
+ inv EXIT.
+ rewrite H in MATCHI. simpl in MATCHI.
+ exploit internal_functions_translated; eauto.
+ rewrite FINDtf.
+ intros (tf & FINDtf' & TRANSf). inversion FINDtf'; subst; clear FINDtf'.
+ exploit exec_cfi_simulation; eauto.
+ (* extract exec_cfi_simulation's conclusion as separate hypotheses *)
+ intros (rs2' & m2' & EXECI & MATCHS); rewrite MATCHS.
+ apply plus_one.
+ eapply Asm.exec_step_internal; eauto.
+ - eapply pc_ptr_exec_step; eauto.
+ - eapply find_instr_ofs_somei; eauto.
+ * (* builtin *)
+ destruct s2.
+ rewrite H in EXIT.
+ rewrite H in MATCHI. simpl in MATCHI.
+ simpl in FIND_INSTR.
+ inversion EXIT.
+ apply plus_one.
+ eapply external_call_symbols_preserved in H10; try (apply senv_preserved).
+ eapply eval_builtin_args_preserved in H6; try (apply symbols_preserved).
+ eapply Asm.exec_step_builtin; eauto.
+ - eapply pc_ptr_exec_step; eauto.
+ - eapply find_instr_ofs_somei; eauto.
+ - eapply eval_builtin_args_match; eauto.
+ - inv MATCHI; eauto.
+ - inv MATCHI.
+ unfold Asm.nextinstr, incrPC.
+ assert (HPC: Val.offset_ptr (rs PC) (Ptrofs.repr (size bb))
+ = Val.offset_ptr (_rs PC) Ptrofs.one).
+ { rewrite <- AGPC. rewrite ATPC. unfold Val.offset_ptr.
+ rewrite Ptrofs.add_assoc. unfold Ptrofs.add.
+ assert (BBPOS: size bb >= 1) by eapply bblock_size_pos.
+ rewrite (Ptrofs.unsigned_repr (size bb - 1)); try omega.
+ rewrite Ptrofs.unsigned_one.
+ replace (size bb - 1 + 1) with (size bb) by omega.
+ reflexivity. }
+ apply set_builtin_res_dont_move_pc_gen.
+ -- erewrite !set_builtin_map_not_pc.
+ erewrite !undef_regs_other_2.
+ rewrite HPC; auto. all: rewrite preg_notin_charact; intros; try discriminate.
+ -- intros. eapply undef_reg_preserved; eauto.
+Qed.
+
+Lemma exec_exit_simulation_star b ofs f bb s2 t rs m rs' m': forall
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (MATCHI: match_internal (size bb - Z.of_nat (length_opt (exit bb))) (State rs m) s2)
+ (EXIT: exec_exit ge f (Ptrofs.repr (size bb)) rs m (exit bb) t rs' m')
+ (ATPC: rs PC = Vptr b ofs),
+ star Asm.step tge s2 t (State rs' m').
+Proof.
+ intros.
+ destruct (exit bb) eqn: Hex.
+ - eapply plus_star.
+ eapply exec_exit_simulation_plus; try rewrite Hex; congruence || eauto.
+ - inv MATCHI.
+ inv EXIT.
+ assert (X: rs2 = incrPC (Ptrofs.repr (size bb)) rs). {
+ unfold incrPC. unfold Pregmap.set.
+ apply functional_extensionality. intros x.
+ destruct (PregEq.eq x PC) as [X|].
+ - rewrite X. rewrite <- AGPC. simpl.
+ replace (size bb - 0) with (size bb) by omega. reflexivity.
+ - rewrite AG; try assumption. reflexivity.
+ }
+ destruct X.
+ subst; eapply star_refl; eauto.
+Qed.
+
+Lemma exec_bblock_simulation b ofs f bb t rs m rs' m': forall
+ (ATPC: rs PC = Vptr b ofs)
+ (FINDF: Genv.find_funct_ptr ge b = Some (Internal f))
+ (FINDBB: find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb)
+ (EXECBB: exec_bblock lk ge f bb rs m t rs' m'),
+ plus Asm.step tge (State rs m) t (State rs' m').
+Proof.
+ intros; destruct EXECBB as (rs1 & m1 & BODY & CTL).
+ exploit exec_header_simulation; eauto.
+ intros (s0 & STAR & MATCH0).
+ eapply star_plus_trans; traceEq || eauto.
+ destruct (bblock_non_empty bb).
+ - (* body bb <> nil *)
+ exploit exec_body_simulation_plus; eauto.
+ intros (s1 & PLUS & MATCH1).
+ eapply plus_star_trans; traceEq || eauto.
+ eapply exec_exit_simulation_star; eauto.
+ erewrite <- exec_body_dont_move_PC; eauto.
+ - (* exit bb <> None *)
+ exploit exec_body_simulation_star; eauto.
+ intros (s1 & STAR1 & MATCH1).
+ eapply star_plus_trans; traceEq || eauto.
+ eapply exec_exit_simulation_plus; eauto.
+ erewrite <- exec_body_dont_move_PC; eauto.
+Qed.
+
+Lemma step_simulation s t s':
+ Asmblock.step lk ge s t s' -> plus Asm.step tge s t s'.
+Proof.
+ intros STEP.
+ inv STEP; simpl; exploit functions_translated; eauto;
+ intros (tf0 & FINDtf & TRANSf);
+ monadInv TRANSf.
+ - (* internal step *) eapply exec_bblock_simulation; eauto.
+ - (* external step *)
+ apply plus_one.
+ exploit external_call_symbols_preserved; eauto. apply senv_preserved.
+ intros ?.
+ eapply Asm.exec_step_external; eauto.
+Qed.
+
+Lemma transf_program_correct:
+ forward_simulation (Asmblock.semantics lk prog) (Asm.semantics tprog).
+Proof.
+ eapply forward_simulation_plus.
+ - apply senv_preserved.
+ - eexact transf_initial_states.
+ - eexact transf_final_states.
+ - (* TODO step_simulation *)
+ unfold match_states.
+ simpl; intros; subst; eexists; split; eauto.
+ eapply step_simulation; eauto.
+Qed.
+
+End PRESERVATION.
+
+End Asmblock_PRESERVATION.
+
+
+Local Open Scope linking_scope.
+
+Definition block_passes :=
+ mkpass Machblockgenproof.match_prog
+ ::: mkpass PseudoAsmblockproof.match_prog
+ ::: mkpass Asmblockgenproof.match_prog
+ (*::: mkpass PostpassSchedulingproof.match_prog*)
+ ::: mkpass Asmblock_PRESERVATION.match_prog
+ ::: pass_nil _.
+
+Definition match_prog := pass_match (compose_passes block_passes).
+
+Lemma transf_program_match:
+ forall p tp, Asmgen.transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros p tp H.
+ unfold Asmgen.transf_program in H. apply bind_inversion in H. destruct H.
+ inversion_clear H. apply bind_inversion in H1. destruct H1.
+ inversion_clear H. inversion H2. remember (Machblockgen.transf_program p) as mbp.
+ unfold match_prog; simpl.
+ exists mbp; split. apply Machblockgenproof.transf_program_match; auto.
+ exists x; split. apply PseudoAsmblockproof.transf_program_match; auto.
+ exists x0; split. apply Asmblockgenproof.transf_program_match; auto.
+ exists tp; split. apply Asmblock_PRESERVATION.transf_program_match; auto. auto.
+Qed.
+
+(** Return Address Offset *)
+
+Definition return_address_offset: Mach.function -> Mach.code -> ptrofs -> Prop :=
+ Machblockgenproof.Mach_return_address_offset (PseudoAsmblockproof.rao Asmblockgenproof.next).
+
+Lemma return_address_exists:
+ forall f sg ros c, is_tail (Mach.Mcall sg ros :: c) f.(Mach.fn_code) ->
+ exists ra, return_address_offset f c ra.
+Proof.
+ intros; eapply Machblockgenproof.Mach_return_address_exists; eauto.
+Admitted.
+
+Section PRESERVATION.
+
+Variable prog: Mach.program.
+Variable tprog: Asm.program.
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Theorem transf_program_correct:
+ forward_simulation (Mach.semantics return_address_offset prog) (Asm.semantics tprog).
+Proof.
+ unfold match_prog in TRANSF. simpl in TRANSF.
+ inv TRANSF. inv H. inv H1. inv H. inv H2. inv H. inv H3. inv H.
+ eapply compose_forward_simulations.
+ { exploit Machblockgenproof.transf_program_correct; eauto. }
+ eapply compose_forward_simulations.
+ + apply PseudoAsmblockproof.transf_program_correct; eauto.
+ - intros; apply Asmblockgenproof.next_progress.
+ - intros; eapply Asmblockgenproof.functions_bound_max_pos; eauto.
+ { intros; eapply Asmblock_PRESERVATION.symbol_high_low; eauto. }
+ + eapply compose_forward_simulations. apply Asmblockgenproof.transf_program_correct; eauto.
+ { intros; eapply Asmblock_PRESERVATION.symbol_high_low; eauto. }
+ apply Asmblock_PRESERVATION.transf_program_correct. eauto.
+Qed.
+
+End PRESERVATION.
+
+Instance TransfAsm: TransfLink match_prog := pass_match_link (compose_passes block_passes).
+
+(*******************************************)
+(* Stub actually needed by driver/Compiler *)
+
+Module Asmgenproof0.
+
+Definition return_address_offset := return_address_offset.
+
+End Asmgenproof0.
diff --git a/aarch64/InstructionScheduler.ml b/aarch64/InstructionScheduler.ml
new file mode 100644
index 00000000..eab0b21a
--- /dev/null
+++ b/aarch64/InstructionScheduler.ml
@@ -0,0 +1,1263 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+let with_destructor dtor stuff f =
+ try let ret = f stuff in
+ dtor stuff;
+ ret
+ with exn -> dtor stuff;
+ raise exn;;
+
+let with_out_channel chan f = with_destructor close_out chan f;;
+let with_in_channel chan f = with_destructor close_in chan f;;
+
+(** Schedule instructions on a synchronized pipeline
+@author David Monniaux, CNRS, VERIMAG *)
+
+type latency_constraint = {
+ instr_from : int;
+ instr_to : int;
+ latency : int };;
+
+type problem = {
+ max_latency : int;
+ resource_bounds : int array;
+ instruction_usages : int array array;
+ latency_constraints : latency_constraint list;
+ };;
+
+let print_problem channel problem =
+ (if problem.max_latency >= 0
+ then Printf.fprintf channel "max makespan: %d\n" problem.max_latency);
+ output_string channel "resource bounds:";
+ (Array.iter (fun b -> Printf.fprintf channel " %d" b) problem.resource_bounds);
+ output_string channel ";\n";
+ (Array.iteri (fun i v ->
+ Printf.fprintf channel "instr%d:" i;
+ (Array.iter (fun b -> Printf.fprintf channel " %d" b) v);
+ output_string channel ";\n") problem.instruction_usages);
+ List.iter (fun instr ->
+ Printf.printf "t%d - t%d >= %d;\n"
+ instr.instr_to instr.instr_from instr.latency)
+ problem.latency_constraints;;
+
+let get_nr_instructions problem = Array.length problem.instruction_usages;;
+let get_nr_resources problem = Array.length problem.resource_bounds;;
+
+type solution = int array
+type scheduler = problem -> solution option
+
+(* DISABLED
+(** Schedule the problem optimally by constraint solving using the Gecode solver. *)
+external gecode_scheduler : problem -> solution option =
+ "caml_gecode_schedule_instr";;
+ *)
+
+let maximum_slot_used times =
+ let maxi = ref (-1) in
+ for i=0 to (Array.length times)-2
+ do
+ maxi := max !maxi times.(i)
+ done;
+ !maxi;;
+
+let check_schedule (problem : problem) (times : solution) =
+ let nr_instructions = get_nr_instructions problem in
+ (if Array.length times <> nr_instructions+1
+ then failwith
+ (Printf.sprintf "check_schedule: %d times expected, got %d"
+ (nr_instructions+1) (Array.length times)));
+ (if problem.max_latency >= 0 && times.(nr_instructions)> problem.max_latency
+ then failwith "check_schedule: max_latency exceeded");
+ (Array.iteri (fun i time ->
+ (if time < 0
+ then failwith (Printf.sprintf "time[%d] < 0" i))) times);
+ let slot_resources = Array.init ((maximum_slot_used times)+1)
+ (fun _ -> Array.copy problem.resource_bounds) in
+ for i=0 to nr_instructions -1
+ do
+ let remaining_resources = slot_resources.(times.(i))
+ and used_resources = problem.instruction_usages.(i) in
+ for resource=0 to (Array.length used_resources)-1
+ do
+ let after = remaining_resources.(resource) - used_resources.(resource) in
+ (if after < 0
+ then failwith (Printf.sprintf "check_schedule: instruction %d exceeds resource %d at slot %d" i resource times.(i)));
+ remaining_resources.(resource) <- after
+ done
+ done;
+ List.iter (fun ctr ->
+ if times.(ctr.instr_to) - times.(ctr.instr_from) < ctr.latency
+ then failwith (Printf.sprintf "check_schedule: time[%d]=%d - time[%d]=%d < %d"
+ ctr.instr_to times.(ctr.instr_to)
+ ctr.instr_from times.(ctr.instr_from)
+ ctr.latency)
+ ) problem.latency_constraints;;
+
+let bound_max_time problem =
+ let total = ref(Array.length problem.instruction_usages) in
+ List.iter (fun ctr -> total := !total + ctr.latency) problem.latency_constraints;
+ !total;;
+
+let vector_less_equal a b =
+ try
+ Array.iter2 (fun x y ->
+ if x>y
+ then raise Exit) a b;
+ true
+ with Exit -> false;;
+
+let vector_subtract a b =
+ assert ((Array.length a) = (Array.length b));
+ for i=0 to (Array.length a)-1
+ do
+ b.(i) <- b.(i) - a.(i)
+ done;;
+
+(* The version with critical path ordering is much better! *)
+type list_scheduler_order =
+ | INSTRUCTION_ORDER
+ | CRITICAL_PATH_ORDER;;
+
+let int_max (x : int) (y : int) =
+ if x > y then x else y;;
+
+let int_min (x : int) (y : int) =
+ if x < y then x else y;;
+
+let get_predecessors problem =
+ let nr_instructions = get_nr_instructions problem in
+ let predecessors = Array.make (nr_instructions+1) [] in
+ List.iter (fun ctr ->
+ predecessors.(ctr.instr_to) <-
+ (ctr.instr_from, ctr.latency)::predecessors.(ctr.instr_to))
+ problem.latency_constraints;
+ predecessors;;
+
+let get_successors problem =
+ let nr_instructions = get_nr_instructions problem in
+ let successors = Array.make nr_instructions [] in
+ List.iter (fun ctr ->
+ successors.(ctr.instr_from) <-
+ (ctr.instr_to, ctr.latency)::successors.(ctr.instr_from))
+ problem.latency_constraints;
+ successors;;
+
+let critical_paths successors =
+ let nr_instructions = Array.length successors in
+ let path_lengths = Array.make nr_instructions (-1) in
+ let rec compute i =
+ if i=nr_instructions then 0 else
+ match path_lengths.(i) with
+ | -2 -> failwith "InstructionScheduler: the dependency graph has cycles"
+ | -1 -> path_lengths.(i) <- -2;
+ let x = List.fold_left
+ (fun cur (j, latency)-> int_max cur (latency+(compute j)))
+ 1 successors.(i)
+ in path_lengths.(i) <- x; x
+ | x -> x
+ in for i = nr_instructions-1 downto 0
+ do
+ ignore (compute i)
+ done;
+ path_lengths;;
+
+let maximum_critical_path problem =
+ let paths = critical_paths (get_successors problem) in
+ Array.fold_left int_max 0 paths;;
+
+let get_earliest_dates predecessors =
+ let nr_instructions = (Array.length predecessors)-1 in
+ let path_lengths = Array.make (nr_instructions+1) (-1) in
+ let rec compute i =
+ match path_lengths.(i) with
+ | -2 -> failwith "InstructionScheduler: the dependency graph has cycles"
+ | -1 -> path_lengths.(i) <- -2;
+ let x = List.fold_left
+ (fun cur (j, latency)-> int_max cur (latency+(compute j)))
+ 0 predecessors.(i)
+ in path_lengths.(i) <- x; x
+ | x -> x
+ in for i = 0 to nr_instructions
+ do
+ ignore (compute i)
+ done;
+ for i = 0 to nr_instructions - 1
+ do
+ path_lengths.(nr_instructions) <- int_max
+ path_lengths.(nr_instructions) (1 + path_lengths.(i))
+ done;
+ path_lengths;;
+
+exception Unschedulable
+
+let get_latest_dates deadline successors =
+ let nr_instructions = Array.length successors
+ and path_lengths = critical_paths successors in
+ Array.init (nr_instructions + 1)
+ (fun i ->
+ if i < nr_instructions then
+ let path_length = path_lengths.(i) in
+ assert (path_length >= 1);
+ (if path_length > deadline
+ then raise Unschedulable);
+ deadline - path_length
+ else deadline);;
+
+let priority_list_scheduler (order : list_scheduler_order)
+ (problem : problem) :
+ solution option =
+ let nr_instructions = get_nr_instructions problem in
+ let successors = get_successors problem
+ and predecessors = get_predecessors problem
+ and times = Array.make (nr_instructions+1) (-1) in
+
+ let priorities = match order with
+ | INSTRUCTION_ORDER -> None
+ | CRITICAL_PATH_ORDER -> Some (critical_paths successors) in
+
+ let module InstrSet =
+ Set.Make (struct type t=int
+ let compare = match priorities with
+ | None -> (fun x y -> x - y)
+ | Some p -> (fun x y ->
+ (match p.(y)-p.(x) with
+ | 0 -> x - y
+ | z -> z))
+ end) in
+
+ let max_time = bound_max_time problem in
+ let ready = Array.make max_time InstrSet.empty in
+ Array.iteri (fun i preds ->
+ if i<nr_instructions && preds=[]
+ then ready.(0) <- InstrSet.add i ready.(0)) predecessors;
+
+ let current_time = ref 0
+ and current_resources = Array.copy problem.resource_bounds
+ and earliest_time i =
+ try
+ let time = ref (-1) in
+ List.iter (fun (j, latency) ->
+ if times.(j) < 0
+ then raise Exit
+ else let t = times.(j) + latency in
+ if t > !time
+ then time := t) predecessors.(i);
+ assert(!time >= 0);
+ !time
+ with Exit -> -1
+
+ in
+ let advance_time() =
+ begin
+ (if !current_time < max_time-1
+ then
+ begin
+ Array.blit problem.resource_bounds 0 current_resources 0
+ (Array.length current_resources);
+ ready.(!current_time + 1) <-
+ InstrSet.union (ready.(!current_time)) (ready.(!current_time + 1));
+ ready.(!current_time) <- InstrSet.empty;
+ end);
+ incr current_time
+ end in
+
+ let attempt_scheduling ready usages =
+ let result = ref (-1) in
+ try
+ InstrSet.iter (fun i ->
+ (* Printf.printf "trying scheduling %d\n" i;
+ pr int_vector usages.(i);
+ print _vector current_resources; *)
+ if vector_less_equal usages.(i) current_resources
+ then
+ begin
+ vector_subtract usages.(i) current_resources;
+ result := i;
+ raise Exit
+ end) ready;
+ -1
+ with Exit -> !result in
+
+ while !current_time < max_time
+ do
+ if (InstrSet.is_empty ready.(!current_time))
+ then advance_time()
+ else
+ match attempt_scheduling ready.(!current_time)
+ problem.instruction_usages with
+ | -1 -> advance_time()
+ | i ->
+ begin
+ assert(times.(i) < 0);
+ times.(i) <- !current_time;
+ ready.(!current_time) <- InstrSet.remove i (ready.(!current_time));
+ List.iter (fun (instr_to, latency) ->
+ if instr_to < nr_instructions then
+ match earliest_time instr_to with
+ | -1 -> ()
+ | to_time ->
+ ready.(to_time) <- InstrSet.add instr_to ready.(to_time))
+ successors.(i);
+ successors.(i) <- []
+ end
+ done;
+ try
+ let final_time = ref (-1) in
+ for i=0 to nr_instructions-1
+ do
+ (if times.(i) < 0 then raise Exit);
+ (if !final_time < times.(i)+1 then final_time := times.(i)+1)
+ done;
+ List.iter (fun (i, latency) ->
+ let target_time = latency + times.(i) in
+ if target_time > !final_time
+ then final_time := target_time
+ ) predecessors.(nr_instructions);
+ times.(nr_instructions) <- !final_time;
+ Some times
+ with Exit -> None;;
+
+let list_scheduler = priority_list_scheduler CRITICAL_PATH_ORDER;;
+
+(* dummy code for placating ocaml's warnings *)
+let _ = fun x -> priority_list_scheduler INSTRUCTION_ORDER x;;
+
+type bundle = int list;;
+
+let rec extract_deps_to index = function
+ | [] -> []
+ | dep :: deps -> let extracts = extract_deps_to index deps in
+ if (dep.instr_to == index) then
+ dep :: extracts
+ else
+ extracts
+
+exception InvalidBundle;;
+
+let dependency_check problem bundle index =
+ let index_deps = extract_deps_to index problem.latency_constraints in
+ List.iter (fun i ->
+ List.iter (fun dep ->
+ if (dep.instr_from == i) then raise InvalidBundle
+ ) index_deps
+ ) bundle;;
+
+let rec make_bundle problem resources bundle index =
+ let resources_copy = Array.copy resources in
+ let nr_instructions = get_nr_instructions problem in
+ if (index >= nr_instructions) then (bundle, index+1) else
+ let inst_usage = problem.instruction_usages.(index) in
+ try match vector_less_equal inst_usage resources with
+ | false -> raise InvalidBundle
+ | true -> (
+ dependency_check problem bundle index;
+ vector_subtract problem.instruction_usages.(index) resources_copy;
+ make_bundle problem resources_copy (index::bundle) (index+1)
+ )
+ with InvalidBundle -> (bundle, index);;
+
+let rec make_bundles problem index : bundle list =
+ if index >= get_nr_instructions problem then
+ []
+ else
+ let (bundle, new_index) = make_bundle problem problem.resource_bounds [] index in
+ bundle :: (make_bundles problem new_index);;
+
+let bundles_to_schedule problem bundles : solution =
+ let nr_instructions = get_nr_instructions problem in
+ let schedule = Array.make (nr_instructions+1) (nr_instructions+4) in
+ let time = ref 0 in
+ List.iter (fun bundle ->
+ begin
+ List.iter (fun i ->
+ schedule.(i) <- !time
+ ) bundle;
+ time := !time + 1
+ end
+ ) bundles; schedule;;
+
+let greedy_scheduler (problem : problem) : solution option =
+ let bundles = make_bundles problem 0 in
+ Some (bundles_to_schedule problem bundles);;
+
+(* alternate implementation
+let swap_array_elements a i j =
+ let x = a.(i) in
+ a.(i) <- a.(j);
+ a.(j) <- x;;
+
+let array_reverse_slice a first last =
+ let i = ref first and j = ref last in
+ while i < j
+ do
+ swap_array_elements a !i !j;
+ incr i;
+ decr j
+ done;;
+
+let array_reverse a =
+ let a' = Array.copy a in
+ array_reverse_slice a' 0 ((Array.length a)-1);
+ a';;
+ *)
+
+(* unneeded
+let array_reverse a =
+ let n=Array.length a in
+ Array.init n (fun i -> a.(n-1-i));;
+ *)
+
+let reverse_constraint nr_instructions ctr =
+ { instr_to = nr_instructions -ctr.instr_from;
+ instr_from = nr_instructions - ctr.instr_to;
+ latency = ctr.latency };;
+
+(* unneeded
+let rec list_map_filter f = function
+ | [] -> []
+ | h::t ->
+ (match f h with
+ | None -> list_map_filter f t
+ | Some x -> x :: (list_map_filter f t));;
+ *)
+
+let reverse_problem problem =
+ let nr_instructions = get_nr_instructions problem in
+ {
+ max_latency = problem.max_latency;
+ resource_bounds = problem.resource_bounds;
+ instruction_usages = Array.init (nr_instructions + 1)
+ (fun i ->
+ if i=0
+ then Array.map (fun _ -> 0) problem.resource_bounds else problem.instruction_usages.(nr_instructions - i));
+ latency_constraints = List.map (reverse_constraint nr_instructions)
+ problem.latency_constraints
+ };;
+
+let max_scheduled_time solution =
+ let time = ref (-1) in
+ for i = 0 to ((Array.length solution) - 2)
+ do
+ time := max !time solution.(i)
+ done;
+ !time;;
+
+(*
+let recompute_makespan problem solution =
+ let n = (Array.length solution) - 1 and ms = ref 0 in
+ List.iter (fun cstr ->
+ if cstr.instr_to = n
+ then ms := max !ms (solution.(cstr.instr_from) + cstr.latency)
+ ) problem.latency_constraints;
+ !ms;;
+ *)
+
+let schedule_reversed (scheduler : problem -> solution option)
+ (problem : problem) =
+ match scheduler (reverse_problem problem) with
+ | None -> None
+ | Some solution ->
+ let nr_instructions = get_nr_instructions problem in
+ let makespan = max_scheduled_time solution in
+ let ret = Array.init (nr_instructions + 1)
+ (fun i -> makespan-solution.(nr_instructions-i)) in
+ ret.(nr_instructions) <- max ((max_scheduled_time ret) + 1)
+ (ret.(nr_instructions));
+ Some ret;;
+
+(** Schedule the problem using a greedy list scheduling algorithm, from the end. *)
+let reverse_list_scheduler = schedule_reversed list_scheduler;;
+
+let check_problem problem =
+ (if (Array.length problem.instruction_usages) < 1
+ then failwith "length(problem.instruction_usages) < 1");;
+
+let validated_scheduler (scheduler : problem -> solution option)
+ (problem : problem) =
+ check_problem problem;
+ match scheduler problem with
+ | None -> None
+ | (Some solution) as ret -> check_schedule problem solution; ret;;
+
+let get_max_latency solution =
+ solution.((Array.length solution)-1);;
+
+let show_date_ranges problem =
+ let deadline = problem.max_latency in
+ assert(deadline >= 0);
+ let successors = get_successors problem
+ and predecessors = get_predecessors problem in
+ let earliest_dates : int array = get_earliest_dates predecessors
+ and latest_dates : int array = get_latest_dates deadline successors in
+ assert ((Array.length earliest_dates) =
+ (Array.length latest_dates));
+ Array.iteri (fun i early ->
+ let late = latest_dates.(i) in
+ Printf.printf "t[%d] in %d..%d\n" i early late)
+ earliest_dates;;
+
+type pseudo_boolean_problem_type =
+ | SATISFIABILITY
+ | OPTIMIZATION;;
+
+type pseudo_boolean_mapper = {
+ mapper_pb_type : pseudo_boolean_problem_type;
+ mapper_nr_instructions : int;
+ mapper_nr_pb_variables : int;
+ mapper_earliest_dates : int array;
+ mapper_latest_dates : int array;
+ mapper_var_offsets : int array;
+ mapper_final_predecessors : (int * int) list
+};;
+
+(* Latency constraints are:
+ presence of instr-to at each t <= sum of presences of instr-from at compatible times
+
+ if reverse_encoding
+ presence of instr-from at each t <= sum of presences of instr-to at compatible times *)
+
+(* Experiments show reverse_encoding=true multiplies time by 2 in sat4j
+ without making hard instances easier *)
+let direct_encoding = false
+and reverse_encoding = false
+and delta_encoding = true
+
+let pseudo_boolean_print_problem channel problem pb_type =
+ let deadline = problem.max_latency in
+ assert (deadline > 0);
+ let nr_instructions = get_nr_instructions problem
+ and nr_resources = get_nr_resources problem
+ and successors = get_successors problem
+ and predecessors = get_predecessors problem in
+ let earliest_dates = get_earliest_dates predecessors
+ and latest_dates = get_latest_dates deadline successors in
+ let var_offsets = Array.make
+ (match pb_type with
+ | OPTIMIZATION -> nr_instructions+1
+ | SATISFIABILITY -> nr_instructions) 0 in
+ let nr_pb_variables =
+ (let nr = ref 0 in
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ var_offsets.(i) <- !nr;
+ nr := !nr + latest_dates.(i) - earliest_dates.(i) + 1
+ done;
+ !nr)
+ and nr_pb_constraints =
+ (match pb_type with
+ | OPTIMIZATION -> nr_instructions+1
+ | SATISFIABILITY -> nr_instructions) +
+
+ (let count = ref 0 in
+ for t=0 to deadline-1
+ do
+ for j=0 to nr_resources-1
+ do
+ try
+ for i=0 to nr_instructions-1
+ do
+ let usage = problem.instruction_usages.(i).(j) in
+ if t >= earliest_dates.(i) && t <= latest_dates.(i)
+ && usage > 0 then raise Exit
+ done
+ with Exit -> incr count
+ done
+ done;
+ !count) +
+
+ (let count=ref 0 in
+ List.iter
+ (fun ctr ->
+ if ctr.instr_to < nr_instructions
+ then count := !count + 1 + latest_dates.(ctr.instr_to)
+ - earliest_dates.(ctr.instr_to)
+ + (if reverse_encoding
+ then 1 + latest_dates.(ctr.instr_from)
+ - earliest_dates.(ctr.instr_from)
+ else 0)
+ )
+ problem.latency_constraints;
+ !count) +
+
+ (match pb_type with
+ | OPTIMIZATION -> (1 + deadline - earliest_dates.(nr_instructions)) * nr_instructions
+ | SATISFIABILITY -> 0)
+ and measured_nr_constraints = ref 0 in
+
+ let pb_var i t =
+ assert(t >= earliest_dates.(i));
+ assert(t <= latest_dates.(i));
+ let v = 1+var_offsets.(i)+t-earliest_dates.(i) in
+ assert(v <= nr_pb_variables);
+ Printf.sprintf "x%d" v in
+
+ let end_constraint () =
+ begin
+ output_string channel ";\n";
+ incr measured_nr_constraints
+ end in
+
+ let gen_latency_constraint i_to i_from latency t_to =
+ Printf.fprintf channel "* t[%d] - t[%d] >= %d when t[%d]=%d\n"
+ i_to i_from latency i_to t_to;
+ for t_from=earliest_dates.(i_from) to
+ int_min latest_dates.(i_from) (t_to - latency)
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i_from t_from)
+ done;
+ Printf.fprintf channel "-1 %s " (pb_var i_to t_to);
+ Printf.fprintf channel ">= 0";
+ end_constraint()
+
+ and gen_dual_latency_constraint i_to i_from latency t_from =
+ Printf.fprintf channel "* t[%d] - t[%d] >= %d when t[%d]=%d\n"
+ i_to i_from latency i_to t_from;
+ for t_to=int_max earliest_dates.(i_to) (t_from + latency)
+ to latest_dates.(i_to)
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i_to t_to)
+ done;
+ Printf.fprintf channel "-1 %s " (pb_var i_from t_from);
+ Printf.fprintf channel ">= 0";
+ end_constraint()
+ in
+
+ Printf.fprintf channel "* #variable= %d #constraint= %d\n" nr_pb_variables nr_pb_constraints;
+ Printf.fprintf channel "* nr_instructions=%d deadline=%d\n" nr_instructions deadline;
+ begin
+ match pb_type with
+ | SATISFIABILITY -> ()
+ | OPTIMIZATION ->
+ output_string channel "min:";
+ for t=earliest_dates.(nr_instructions) to deadline
+ do
+ Printf.fprintf channel " %+d %s" t (pb_var nr_instructions t)
+ done;
+ output_string channel ";\n";
+ end;
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ let early = earliest_dates.(i) and late= latest_dates.(i) in
+ Printf.fprintf channel "* t[%d] in %d..%d\n" i early late;
+ for t=early to late
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i t)
+ done;
+ Printf.fprintf channel "= 1";
+ end_constraint()
+ done;
+
+ for t=0 to deadline-1
+ do
+ for j=0 to nr_resources-1
+ do
+ let bound = problem.resource_bounds.(j)
+ and coeffs = ref [] in
+ for i=0 to nr_instructions-1
+ do
+ let usage = problem.instruction_usages.(i).(j) in
+ if t >= earliest_dates.(i) && t <= latest_dates.(i)
+ && usage > 0
+ then coeffs := (i, usage) :: !coeffs
+ done;
+ if !coeffs <> [] then
+ begin
+ Printf.fprintf channel "* resource #%d at t=%d <= %d\n" j t bound;
+ List.iter (fun (i, usage) ->
+ Printf.fprintf channel "%+d %s " (-usage) (pb_var i t)) !coeffs;
+ Printf.fprintf channel ">= %d" (-bound);
+ end_constraint();
+ end
+ done
+ done;
+
+ List.iter
+ (fun ctr ->
+ if ctr.instr_to < nr_instructions then
+ begin
+ for t_to=earliest_dates.(ctr.instr_to) to latest_dates.(ctr.instr_to)
+ do
+ gen_latency_constraint ctr.instr_to ctr.instr_from ctr.latency t_to
+ done;
+ if reverse_encoding
+ then
+ for t_from=earliest_dates.(ctr.instr_from) to latest_dates.(ctr.instr_from)
+ do
+ gen_dual_latency_constraint ctr.instr_to ctr.instr_from ctr.latency t_from
+ done
+ end
+ ) problem.latency_constraints;
+
+ begin
+ match pb_type with
+ | SATISFIABILITY -> ()
+ | OPTIMIZATION ->
+ let final_latencies = Array.make nr_instructions 1 in
+ List.iter (fun (i, latency) ->
+ final_latencies.(i) <- int_max final_latencies.(i) latency)
+ predecessors.(nr_instructions);
+ for t_to=earliest_dates.(nr_instructions) to deadline
+ do
+ for i_from = 0 to nr_instructions -1
+ do
+ gen_latency_constraint nr_instructions i_from final_latencies.(i_from) t_to
+ done
+ done
+ end;
+ assert (!measured_nr_constraints = nr_pb_constraints);
+ {
+ mapper_pb_type = pb_type;
+ mapper_nr_instructions = nr_instructions;
+ mapper_nr_pb_variables = nr_pb_variables;
+ mapper_earliest_dates = earliest_dates;
+ mapper_latest_dates = latest_dates;
+ mapper_var_offsets = var_offsets;
+ mapper_final_predecessors = predecessors.(nr_instructions)
+ };;
+
+type pb_answer =
+ | Positive
+ | Negative
+ | Unknown
+
+let line_to_pb_solution sol line nr_pb_variables =
+ let assign s v =
+ begin
+ let i = int_of_string s in
+ sol.(i-1) <- v
+ end in
+ List.iter
+ begin
+ function "" -> ()
+ | item ->
+ (match String.get item 0 with
+ | '+' ->
+ assert ((String.length item) >= 3);
+ assert ((String.get item 1) = 'x');
+ assign (String.sub item 2 ((String.length item)-2)) Positive
+ | '-' ->
+ assert ((String.length item) >= 3);
+ assert ((String.get item 1) = 'x');
+ assign (String.sub item 2 ((String.length item)-2)) Negative
+ | 'x' ->
+ assert ((String.length item) >= 2);
+ assign (String.sub item 1 ((String.length item)-1)) Positive
+ | _ -> failwith "syntax error in pseudo Boolean solution: epected + - or x"
+ )
+ end
+ (String.split_on_char ' ' (String.sub line 2 ((String.length line)-2)));;
+
+let pb_solution_to_schedule mapper pb_solution =
+ Array.mapi (fun i offset ->
+ let first = mapper.mapper_earliest_dates.(i)
+ and last = mapper.mapper_latest_dates.(i)
+ and time = ref (-1) in
+ for t=first to last
+ do
+ match pb_solution.(t - first + offset) with
+ | Positive ->
+ (if !time = -1
+ then time:=t
+ else failwith "duplicate time in pseudo boolean solution")
+ | Negative -> ()
+ | Unknown -> failwith "unknown value in pseudo boolean solution"
+ done;
+ (if !time = -1
+ then failwith "no time in pseudo boolean solution");
+ !time
+ ) mapper.mapper_var_offsets;;
+
+let pseudo_boolean_read_solution mapper channel =
+ let optimum = ref (-1)
+ and optimum_found = ref false
+ and solution = Array.make mapper.mapper_nr_pb_variables Unknown in
+ try
+ while true do
+ match input_line channel with
+ | "" -> ()
+ | line ->
+ begin
+ match String.get line 0 with
+ | 'c' -> ()
+ | 'o' ->
+ assert ((String.length line) >= 2);
+ assert ((String.get line 1) = ' ');
+ optimum := int_of_string (String.sub line 2 ((String.length line)-2))
+ | 's' -> (match line with
+ | "s OPTIMUM FOUND" -> optimum_found := true
+ | "s SATISFIABLE" -> ()
+ | "s UNSATISFIABLE" -> close_in channel;
+ raise Unschedulable
+ | _ -> failwith line)
+ | 'v' -> line_to_pb_solution solution line mapper.mapper_nr_pb_variables
+ | x -> Printf.printf "unknown: %s\n" line
+ end
+ done;
+ assert false
+ with End_of_file ->
+ close_in channel;
+ begin
+ let sol = pb_solution_to_schedule mapper solution in
+ sol
+ end;;
+
+let recompute_max_latency mapper solution =
+ let maxi = ref (-1) in
+ for i=0 to (mapper.mapper_nr_instructions-1)
+ do
+ maxi := int_max !maxi (1+solution.(i))
+ done;
+ List.iter (fun (i, latency) ->
+ maxi := int_max !maxi (solution.(i) + latency)) mapper.mapper_final_predecessors;
+ !maxi;;
+
+let adjust_check_solution mapper solution =
+ match mapper.mapper_pb_type with
+ | OPTIMIZATION ->
+ let max_latency = recompute_max_latency mapper solution in
+ assert (max_latency = solution.(mapper.mapper_nr_instructions));
+ solution
+ | SATISFIABILITY ->
+ let max_latency = recompute_max_latency mapper solution in
+ Array.init (mapper.mapper_nr_instructions+1)
+ (fun i -> if i < mapper.mapper_nr_instructions
+ then solution.(i)
+ else max_latency);;
+
+(* let pseudo_boolean_solver = ref "/local/monniaux/progs/naps/naps" *)
+(* let pseudo_boolean_solver = ref "/local/monniaux/packages/sat4j/org.sat4j.pb.jar CuttingPlanes" *)
+
+(* let pseudo_boolean_solver = ref "java -jar /usr/share/java/org.sat4j.pb.jar CuttingPlanes" *)
+(* let pseudo_boolean_solver = ref "java -jar /usr/share/java/org.sat4j.pb.jar" *)
+(* let pseudo_boolean_solver = ref "clasp" *)
+(* let pseudo_boolean_solver = ref "/home/monniaux/progs/CP/open-wbo/open-wbo_static -formula=1" *)
+(* let pseudo_boolean_solver = ref "/home/monniaux/progs/CP/naps/naps" *)
+(* let pseudo_boolean_solver = ref "/home/monniaux/progs/CP/minisatp/build/release/bin/minisatp" *)
+(* let pseudo_boolean_solver = ref "java -jar sat4j-pb.jar CuttingPlanesStar" *)
+let pseudo_boolean_solver = ref "pb_solver"
+
+let pseudo_boolean_scheduler pb_type problem =
+ try
+ let filename_in = "problem.opb" in
+ (* needed only if not using stdout and filename_out = "problem.sol" *)
+ let mapper =
+ with_out_channel (open_out filename_in)
+ (fun opb_problem ->
+ pseudo_boolean_print_problem opb_problem problem pb_type) in
+ Some (with_in_channel
+ (Unix.open_process_in (!pseudo_boolean_solver ^ " " ^ filename_in))
+ (fun opb_solution -> adjust_check_solution mapper (pseudo_boolean_read_solution mapper opb_solution)))
+ with
+ | Unschedulable -> None;;
+
+let rec reoptimizing_scheduler (scheduler : scheduler) (previous_solution : solution) (problem : problem) =
+ if (get_max_latency previous_solution)>1 then
+ begin
+ Printf.printf "reoptimizing < %d\n" (get_max_latency previous_solution);
+ flush stdout;
+ match scheduler
+ { problem with max_latency = (get_max_latency previous_solution)-1 }
+ with
+ | None -> previous_solution
+ | Some solution -> reoptimizing_scheduler scheduler solution problem
+ end
+ else previous_solution;;
+
+let smt_var i = Printf.sprintf "t%d" i
+
+let is_resource_used problem j =
+ try
+ Array.iter (fun usages ->
+ if usages.(j) > 0
+ then raise Exit) problem.instruction_usages;
+ false
+ with Exit -> true;;
+
+let smt_use_quantifiers = false
+
+let smt_print_problem channel problem =
+ let nr_instructions = get_nr_instructions problem in
+ let gen_smt_resource_constraint time j =
+ output_string channel "(<= (+";
+ Array.iteri
+ (fun i usages ->
+ let usage=usages.(j) in
+ if usage > 0
+ then Printf.fprintf channel " (ite (= %s %s) %d 0)"
+ time (smt_var i) usage)
+ problem.instruction_usages;
+ Printf.fprintf channel ") %d)" problem.resource_bounds.(j)
+ in
+ output_string channel "(set-option :produce-models true)\n";
+ for i=0 to nr_instructions
+ do
+ Printf.fprintf channel "(declare-const %s Int)\n" (smt_var i);
+ Printf.fprintf channel "(assert (>= %s 0))\n" (smt_var i)
+ done;
+ for i=0 to nr_instructions-1
+ do
+ Printf.fprintf channel "(assert (< %s %s))\n"
+ (smt_var i) (smt_var nr_instructions)
+ done;
+ (if problem.max_latency > 0
+ then Printf.fprintf channel "(assert (<= %s %d))\n"
+ (smt_var nr_instructions) problem.max_latency);
+ List.iter (fun ctr ->
+ Printf.fprintf channel "(assert (>= (- %s %s) %d))\n"
+ (smt_var ctr.instr_to)
+ (smt_var ctr.instr_from)
+ ctr.latency) problem.latency_constraints;
+ for j=0 to (Array.length problem.resource_bounds)-1
+ do
+ if is_resource_used problem j
+ then
+ begin
+ if smt_use_quantifiers
+ then
+ begin
+ Printf.fprintf channel
+ "; resource #%d <= %d\n(assert (forall ((t Int)) "
+ j problem.resource_bounds.(j);
+ gen_smt_resource_constraint "t" j;
+ output_string channel "))\n"
+ end
+ else
+ begin
+ (if problem.max_latency < 0
+ then failwith "quantifier explosion needs max latency");
+ for t=0 to problem.max_latency
+ do
+ Printf.fprintf channel
+ "; resource #%d <= %d at t=%d\n(assert "
+ j problem.resource_bounds.(j) t;
+ gen_smt_resource_constraint (string_of_int t) j;
+ output_string channel ")\n"
+ done
+ end
+ end
+ done;
+ output_string channel "(check-sat)(get-model)\n";;
+
+
+let ilp_print_problem channel problem pb_type =
+ let deadline = problem.max_latency in
+ assert (deadline > 0);
+ let nr_instructions = get_nr_instructions problem
+ and nr_resources = get_nr_resources problem
+ and successors = get_successors problem
+ and predecessors = get_predecessors problem in
+ let earliest_dates = get_earliest_dates predecessors
+ and latest_dates = get_latest_dates deadline successors in
+
+ let pb_var i t =
+ Printf.sprintf "x%d_%d" i t in
+
+ let gen_latency_constraint i_to i_from latency t_to =
+ Printf.fprintf channel "\\ t[%d] - t[%d] >= %d when t[%d]=%d\n"
+ i_to i_from latency i_to t_to;
+ Printf.fprintf channel "c_%d_%d_%d_%d: "
+ i_to i_from latency t_to;
+ for t_from=earliest_dates.(i_from) to
+ int_min latest_dates.(i_from) (t_to - latency)
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i_from t_from)
+ done;
+ Printf.fprintf channel "-1 %s " (pb_var i_to t_to);
+ output_string channel ">= 0\n"
+
+ and gen_dual_latency_constraint i_to i_from latency t_from =
+ Printf.fprintf channel "\\ t[%d] - t[%d] >= %d when t[%d]=%d\n"
+ i_to i_from latency i_to t_from;
+ Printf.fprintf channel "d_%d_%d_%d_%d: "
+ i_to i_from latency t_from;
+ for t_to=int_max earliest_dates.(i_to) (t_from + latency)
+ to latest_dates.(i_to)
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i_to t_to)
+ done;
+ Printf.fprintf channel "-1 %s " (pb_var i_from t_from);
+ Printf.fprintf channel ">= 0\n"
+
+ and gen_delta_constraint i_from i_to latency =
+ if delta_encoding
+ then Printf.fprintf channel "l_%d_%d_%d: +1 t%d -1 t%d >= %d\n"
+ i_from i_to latency i_to i_from latency
+
+ in
+
+ Printf.fprintf channel "\\ nr_instructions=%d deadline=%d\n" nr_instructions deadline;
+ begin
+ match pb_type with
+ | SATISFIABILITY -> output_string channel "Minimize dummy: 0\n"
+ | OPTIMIZATION ->
+ Printf.fprintf channel "Minimize\nmakespan: t%d\n" nr_instructions
+ end;
+ output_string channel "Subject To\n";
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ let early = earliest_dates.(i) and late= latest_dates.(i) in
+ Printf.fprintf channel "\\ t[%d] in %d..%d\ntimes%d: " i early late i;
+ for t=early to late
+ do
+ Printf.fprintf channel "+1 %s " (pb_var i t)
+ done;
+ Printf.fprintf channel "= 1\n"
+ done;
+
+ for t=0 to deadline-1
+ do
+ for j=0 to nr_resources-1
+ do
+ let bound = problem.resource_bounds.(j)
+ and coeffs = ref [] in
+ for i=0 to nr_instructions-1
+ do
+ let usage = problem.instruction_usages.(i).(j) in
+ if t >= earliest_dates.(i) && t <= latest_dates.(i)
+ && usage > 0
+ then coeffs := (i, usage) :: !coeffs
+ done;
+ if !coeffs <> [] then
+ begin
+ Printf.fprintf channel "\\ resource #%d at t=%d <= %d\nr%d_%d: " j t bound j t;
+ List.iter (fun (i, usage) ->
+ Printf.fprintf channel "%+d %s " (-usage) (pb_var i t)) !coeffs;
+ Printf.fprintf channel ">= %d\n" (-bound)
+ end
+ done
+ done;
+
+ List.iter
+ (fun ctr ->
+ if ctr.instr_to < nr_instructions then
+ begin
+ gen_delta_constraint ctr.instr_from ctr.instr_to ctr.latency;
+ begin
+ if direct_encoding
+ then
+ for t_to=earliest_dates.(ctr.instr_to) to latest_dates.(ctr.instr_to)
+ do
+ gen_latency_constraint ctr.instr_to ctr.instr_from ctr.latency t_to
+ done
+ end;
+ begin
+ if reverse_encoding
+ then
+ for t_from=earliest_dates.(ctr.instr_from) to latest_dates.(ctr.instr_from)
+ do
+ gen_dual_latency_constraint ctr.instr_to ctr.instr_from ctr.latency t_from
+ done
+ end
+ end
+ ) problem.latency_constraints;
+
+ begin
+ match pb_type with
+ | SATISFIABILITY -> ()
+ | OPTIMIZATION ->
+ let final_latencies = Array.make nr_instructions 1 in
+ List.iter (fun (i, latency) ->
+ final_latencies.(i) <- int_max final_latencies.(i) latency)
+ predecessors.(nr_instructions);
+ for i_from = 0 to nr_instructions -1
+ do
+ gen_delta_constraint i_from nr_instructions final_latencies.(i_from)
+ done;
+ for t_to=earliest_dates.(nr_instructions) to deadline
+ do
+ for i_from = 0 to nr_instructions -1
+ do
+ gen_latency_constraint nr_instructions i_from final_latencies.(i_from) t_to
+ done
+ done
+ end;
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ Printf.fprintf channel "ct%d : -1 t%d" i i;
+ let early = earliest_dates.(i) and late= latest_dates.(i) in
+ for t=early to late do
+ Printf.fprintf channel " +%d %s" t (pb_var i t)
+ done;
+ output_string channel " = 0\n"
+ done;
+ output_string channel "Bounds\n";
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ let early = earliest_dates.(i) and late= latest_dates.(i) in
+ begin
+ Printf.fprintf channel "%d <= t%d <= %d\n" early i late;
+ if true then
+ for t=early to late do
+ Printf.fprintf channel "0 <= %s <= 1\n" (pb_var i t)
+ done
+ end
+ done;
+ output_string channel "Integer\n";
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ Printf.fprintf channel "t%d " i
+ done;
+ output_string channel "\nBinary\n";
+ for i=0 to (match pb_type with
+ | OPTIMIZATION -> nr_instructions
+ | SATISFIABILITY -> nr_instructions-1)
+ do
+ let early = earliest_dates.(i) and late= latest_dates.(i) in
+ for t=early to late do
+ output_string channel (pb_var i t);
+ output_string channel " "
+ done;
+ output_string channel "\n"
+ done;
+ output_string channel "End\n";
+ {
+ mapper_pb_type = pb_type;
+ mapper_nr_instructions = nr_instructions;
+ mapper_nr_pb_variables = 0;
+ mapper_earliest_dates = earliest_dates;
+ mapper_latest_dates = latest_dates;
+ mapper_var_offsets = [| |];
+ mapper_final_predecessors = predecessors.(nr_instructions)
+ };;
+
+(* Guess what? Cplex sometimes outputs 11.000000004 instead of integer 11 *)
+
+let positive_float_round x = truncate (x +. 0.5)
+
+let float_round (x : float) : int =
+ if x > 0.0
+ then positive_float_round x
+ else - (positive_float_round (-. x))
+
+let rounded_int_of_string x = float_round (float_of_string x)
+
+let ilp_read_solution mapper channel =
+ let times = Array.make
+ (match mapper.mapper_pb_type with
+ | OPTIMIZATION -> 1+mapper.mapper_nr_instructions
+ | SATISFIABILITY -> mapper.mapper_nr_instructions) (-1) in
+ try
+ while true do
+ let line = input_line channel in
+ ( if (String.length line) < 3
+ then failwith (Printf.sprintf "bad ilp output: length(line) < 3: %s" line));
+ match String.get line 0 with
+ | 'x' -> ()
+ | 't' -> let space =
+ try String.index line ' '
+ with Not_found ->
+ failwith "bad ilp output: no t variable number"
+ in
+ let tnumber =
+ try int_of_string (String.sub line 1 (space-1))
+ with Failure _ ->
+ failwith "bad ilp output: not a variable number"
+ in
+ (if tnumber < 0 || tnumber >= (Array.length times)
+ then failwith (Printf.sprintf "bad ilp output: not a correct variable number: %d (%d)" tnumber (Array.length times)));
+ let value =
+ let s = String.sub line (space+1) ((String.length line)-space-1) in
+ try rounded_int_of_string s
+ with Failure _ ->
+ failwith (Printf.sprintf "bad ilp output: not a time number (%s)" s)
+ in
+ (if value < 0
+ then failwith "bad ilp output: negative time");
+ times.(tnumber) <- value
+ | '#' -> ()
+ | '0' -> ()
+ | _ -> failwith (Printf.sprintf "bad ilp output: bad variable initial, line = %s" line)
+ done;
+ assert false
+ with End_of_file ->
+ Array.iteri (fun i x ->
+ if i<(Array.length times)-1
+ && x<0 then raise Unschedulable) times;
+ times;;
+
+let ilp_solver = ref "ilp_solver"
+
+let problem_nr = ref 0
+
+let ilp_scheduler pb_type problem =
+ try
+ let filename_in = Printf.sprintf "problem%05d.lp" !problem_nr
+ and filename_out = Printf.sprintf "problem%05d.sol" !problem_nr in
+ incr problem_nr;
+ let mapper = with_out_channel (open_out filename_in)
+ (fun opb_problem -> ilp_print_problem opb_problem problem pb_type) in
+
+ begin
+ match Unix.system (!ilp_solver ^ " " ^ filename_in ^ " " ^ filename_out) with
+ | Unix.WEXITED 0 ->
+ Some (with_in_channel
+ (open_in filename_out)
+ (fun opb_solution ->
+ adjust_check_solution mapper
+ (ilp_read_solution mapper opb_solution)))
+ | Unix.WEXITED _ -> failwith "failed to start ilp solver"
+ | _ -> None
+ end
+ with
+ | Unschedulable -> None;;
+
+let current_utime_all () =
+ let t = Unix.times() in
+ t.Unix.tms_cutime +. t.Unix.tms_utime;;
+
+let utime_all_fn fn arg =
+ let utime_start = current_utime_all () in
+ let output = fn arg in
+ let utime_end = current_utime_all () in
+ (output, utime_end -. utime_start);;
+
+let cascaded_scheduler (problem : problem) =
+ let (some_initial_solution, list_scheduler_time) =
+ utime_all_fn (validated_scheduler list_scheduler) problem in
+ match some_initial_solution with
+ | None -> None
+ | Some initial_solution ->
+ let (solution, reoptimizing_time) = utime_all_fn (reoptimizing_scheduler (validated_scheduler (ilp_scheduler SATISFIABILITY)) initial_solution) problem in
+ begin
+ let latency2 = get_max_latency solution
+ and latency1 = get_max_latency initial_solution in
+ Printf.printf "postpass %s: %d, %d, %d, %g, %g\n"
+ (if latency2 < latency1 then "REOPTIMIZED" else "unchanged")
+ (get_nr_instructions problem)
+ latency1 latency2
+ list_scheduler_time reoptimizing_time;
+ flush stdout
+ end;
+ Some solution;;
+
+let scheduler_by_name name =
+ match name with
+ | "ilp" -> validated_scheduler cascaded_scheduler
+ | "list" -> validated_scheduler list_scheduler
+ | "revlist" -> validated_scheduler reverse_list_scheduler
+ | "greedy" -> greedy_scheduler
+ | s -> failwith ("unknown scheduler: " ^ s);;
diff --git a/aarch64/InstructionScheduler.mli b/aarch64/InstructionScheduler.mli
new file mode 100644
index 00000000..85e2a5c6
--- /dev/null
+++ b/aarch64/InstructionScheduler.mli
@@ -0,0 +1,113 @@
+(** Schedule instructions on a synchronized pipeline
+by David Monniaux, CNRS, VERIMAG *)
+
+(** A latency constraint: instruction number [instr_to] should be scheduled at least [latency] clock ticks before [instr_from].
+
+It is possible to specify [latency]=0, meaning that [instr_to] can be scheduled at the same clock tick as [instr_from], but not before.
+
+[instr_to] can be the special value equal to the number of instructions, meaning that it refers to the final output latency. *)
+type latency_constraint = {
+ instr_from : int;
+ instr_to : int;
+ latency : int;
+ }
+
+(** A scheduling problem.
+
+In addition to the latency constraints, the resource constraints should be satisfied: at every clock tick, the sum of vectors of resources used by the instructions scheduled at that tick does not exceed the resource bounds.
+*)
+type problem = {
+ max_latency : int;
+ (** An optional maximal total latency of the problem, after which the problem is deemed not schedulable. -1 means there should be no maximum. *)
+
+ resource_bounds : int array;
+ (** An array of number of units available indexed by the kind of resources to be allocated. It can be empty, in which case the problem is scheduling without resource constraints. *)
+
+ instruction_usages: int array array;
+ (** At index {i i} the vector of resources used by instruction number {i i}. It must be the same length as [resource_bounds] *)
+
+ latency_constraints : latency_constraint list
+ (** The latency constraints that must be satisfied *)
+ };;
+
+(** Print problem for human readability. *)
+val print_problem : out_channel -> problem -> unit;;
+
+(** Scheduling solution. For {i n} instructions to schedule, and 0≤{i i}<{i n}, position {i i} contains the time to which instruction {i i} should be scheduled. Position {i n} contains the final output latency. *)
+type solution = int array
+
+(** A scheduling algorithm.
+The return value [Some x] is a solution [x].
+[None] means that scheduling failed. *)
+type scheduler = problem -> solution option;;
+
+(* DISABLED
+(** Schedule the problem optimally by constraint solving using the Gecode solver. *)
+external gecode_scheduler : problem -> solution option
+ = "caml_gecode_schedule_instr"
+ *)
+
+(** Get the number the last scheduling time used for an instruction in a solution.
+@return The last clock tick used *)
+val maximum_slot_used : solution -> int
+
+(** Validate that a solution is truly a solution of a scheduling problem.
+@raise Failure if validation fails *)
+val check_schedule : problem -> solution -> unit
+
+(** Schedule the problem using a greedy list scheduling algorithm, from the start.
+The first (according to instruction ordering) instruction that is ready (according to the latency constraints) is scheduled at the current clock tick.
+Once a clock tick is full go to the next.
+
+@return [Some solution] when a solution is found, [None] if not. *)
+val list_scheduler : problem -> solution option
+
+(** Schedule the problem using the order of instructions without any reordering *)
+val greedy_scheduler : problem -> solution option
+
+(** Schedule a problem using a scheduler applied in the opposite direction, e.g. for list scheduling from the end instead of the start. BUGGY *)
+val schedule_reversed : scheduler -> problem -> int array option
+
+(** Schedule a problem from the end using a list scheduler. BUGGY *)
+val reverse_list_scheduler : problem -> int array option
+
+(** Check that a problem is well-formed.
+@raise Failure if validation fails *)
+val check_problem : problem -> unit
+
+(** Apply a scheduler and validate the result against the input problem.
+@return The solution found
+@raise Failure if validation fails *)
+val validated_scheduler : scheduler -> problem -> solution option;;
+
+(** Get max latency from solution
+@return Max latency *)
+val get_max_latency : solution -> int;;
+
+(** Get the length of a maximal critical path
+@return Max length *)
+val maximum_critical_path : problem -> int;;
+
+(** Apply line scheduler then advanced solver
+@return A solution if found *)
+val cascaded_scheduler : problem -> solution option;;
+
+val show_date_ranges : problem -> unit;;
+
+type pseudo_boolean_problem_type =
+ | SATISFIABILITY
+ | OPTIMIZATION;;
+
+type pseudo_boolean_mapper
+val pseudo_boolean_print_problem : out_channel -> problem -> pseudo_boolean_problem_type -> pseudo_boolean_mapper;;
+val pseudo_boolean_read_solution : pseudo_boolean_mapper -> in_channel -> solution;;
+val pseudo_boolean_scheduler : pseudo_boolean_problem_type -> problem -> solution option;;
+
+val smt_print_problem : out_channel -> problem -> unit;;
+
+val ilp_print_problem : out_channel -> problem -> pseudo_boolean_problem_type -> pseudo_boolean_mapper;;
+
+val ilp_scheduler : pseudo_boolean_problem_type -> problem -> solution option;;
+
+(** Schedule a problem using a scheduler given by a string name *)
+val scheduler_by_name : string -> problem -> int array option;;
diff --git a/aarch64/OpWeightsAsm.ml b/aarch64/OpWeightsAsm.ml
new file mode 100644
index 00000000..c1d0583a
--- /dev/null
+++ b/aarch64/OpWeightsAsm.ml
@@ -0,0 +1,377 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(*type called_function = (Registers.reg, AST.ident) Datatypes.sum*)
+
+type real_instruction =
+ | Add
+ | Adr
+ | Adrp
+ | And
+ | Asr
+ | B
+ | Bic
+ | Bl
+ | Blr
+ | Br
+ | Cbnz
+ | Cbz
+ | Cls
+ | Clz
+ | Cmn
+ | Cmp
+ | Csel
+ | Cset
+ | Eon
+ | Eor
+ | Fabs
+ | Fadd
+ | Fcmp
+ | Fcsel
+ | Fcvt
+ | Fcvtzs
+ | Fcvtzu
+ | Fdiv
+ | Fmadd
+ | Fmov
+ | Fmsub
+ | Fmul
+ | Fnmadd
+ | Fnmul
+ | Fnmsub
+ | Fneg
+ | Fsqrt
+ | Fsub
+ | Ldaxr
+ | Ldp
+ | Ldr
+ | Ldrb
+ | Ldrh
+ | Ldrsb
+ | Ldrsh
+ | Ldrsw
+ | Lr
+ | Lsl
+ | Lsr
+ | Madd
+ | Mov
+ | Movk
+ | Movn
+ | Movz
+ | Msub
+ | Nop
+ | Orn
+ | Orr
+ | Ret
+ | Rev
+ | Rev16
+ | Ror
+ | Sbfiz
+ | Sbfx
+ | Scvtf
+ | Sdiv
+ | Smulh
+ | Stlxr
+ | Stp
+ | Str
+ | Strb
+ | Strh
+ | Sub
+ | Sxtb
+ | Sxth
+ | Sxtw
+ | Tbnz
+ | Tbz
+ | Tst
+ | Ubfiz
+ | Ubfx
+ | Ucvtf
+ | Udiv
+ | Umulh
+ | Uxtb
+ | Uxth
+ | Uxtw
+ | Uxtx
+ (* Pseudo instr *)
+ | Btbl
+ | Allocframe
+ | Freeframe
+ | Builtin
+ | Cvtx2w
+
+type opweights = {
+ pipelined_resource_bounds : int array;
+ nr_non_pipelined_units : int;
+ latency_of_op : real_instruction -> int -> int;
+ resources_of_op : real_instruction -> int -> int array;
+ (*non_pipelined_resources_of_op : Op.operation -> int -> int array;*)
+ (*latency_of_load : AST.trapping_mode -> AST.memory_chunk -> Op.addressing -> int -> int;*)
+ (*resources_of_load : AST.trapping_mode -> AST.memory_chunk -> Op.addressing -> int -> int array;*)
+ (*resources_of_store : AST.memory_chunk -> Op.addressing -> int -> int array;*)
+ (*resources_of_cond : Op.condition -> int -> int array;*)
+ (*latency_of_call : AST.signature -> called_function -> int;*)
+ (*resources_of_call : AST.signature -> called_function -> int array;*)
+ (*resources_of_builtin : AST.external_function -> int array*)
+}
+
+module Cortex_A53 = struct
+ let resource_bounds = [| 2; 2; 1; 1 |]
+
+ (* instr ; ALU ; MAC; LSU *)
+ let nr_non_pipelined_units = 1
+
+ let latency_of_op (i : real_instruction) (nargs : int) =
+ match i with
+ | Add -> 1
+ | Adr -> 1
+ | Adrp -> 1 (* XXX *)
+ | And -> 1
+ | Asr -> 2
+ | B -> 1
+ | Bic -> 1
+ | Bl -> 1
+ | Blr -> 1
+ | Br -> 1
+ | Cbnz -> 1
+ | Cbz -> 1
+ | Cls -> 1
+ | Clz -> 1
+ | Cmn -> 6
+ | Cmp -> 6
+ | Csel -> 2
+ | Cset -> 2
+ | Eon -> 1
+ | Eor -> 1
+ | Fabs -> 6
+ | Fadd -> 1
+ | Fcmp -> 6
+ | Fcsel -> 1
+ | Fcvt -> 6
+ | Fcvtzs -> 6
+ | Fcvtzu -> 6
+ | Fdiv -> 50
+ | Fmadd -> 1
+ | Fmov -> 1
+ | Fmsub -> 1
+ | Fmul -> 6
+ | Fnmadd -> 1
+ | Fnmul -> 1
+ | Fnmsub -> 1
+ | Fneg -> 6
+ | Fsqrt -> 1
+ | Fsub -> 6
+ | Ldaxr -> 3
+ | Ldp -> 3
+ | Ldr -> 3
+ | Ldrb -> 3
+ | Ldrh -> 3
+ | Ldrsb -> 3
+ | Ldrsh -> 3
+ | Ldrsw -> 3
+ | Lr -> 3
+ | Lsl -> 2
+ | Lsr -> 2
+ | Madd -> 4
+ | Mov -> 1 (* XXX *)
+ | Movk -> 1
+ | Movn -> 1
+ | Movz -> 1
+ | Msub -> 4
+ | Nop -> 1
+ | Orn -> 1
+ | Orr -> 1
+ | Ret -> 1
+ | Rev -> 1
+ | Rev16 -> 1
+ | Ror -> 2
+ | Sbfiz -> 2 (* XXX *)
+ | Sbfx -> 2
+ | Scvtf -> 6
+ | Sdiv -> 50
+ | Smulh -> 4
+ | Stlxr -> 2
+ | Stp -> 2
+ | Str -> 2
+ | Strb -> 2
+ | Strh -> 2
+ | Sub -> 1
+ | Sxtb -> 1
+ | Sxth -> 1
+ | Sxtw -> 1
+ | Tbnz -> 1
+ | Tbz -> 1
+ | Tst -> 6
+ | Ubfiz -> 2 (* XXX *)
+ | Ubfx -> 2
+ | Ucvtf -> 6
+ | Udiv -> 50
+ | Umulh -> 4
+ | Uxtb -> 1
+ | Uxth -> 1
+ | Uxtw -> 1
+ | Uxtx -> 1
+ | Btbl -> 1
+ | Allocframe -> 51
+ | Freeframe -> 51
+ | Builtin -> 51
+ | Cvtx2w -> 51
+
+ let resources_of_op (i : real_instruction) (nargs : int) =
+ match i with
+ | Add -> [| 1; 1; 0; 0 |]
+ | Adr -> [| 1; 1; 0; 0 |]
+ | Adrp -> [| 1; 1; 0; 0 |]
+ | And -> [| 1; 1; 0; 0 |]
+ | Asr -> [| 1; 1; 0; 0 |]
+ | B -> [| 1; 1; 0; 0 |]
+ | Bic -> [| 1; 1; 0; 0 |]
+ | Bl -> [| 1; 1; 0; 0 |]
+ | Blr -> [| 1; 1; 0; 0 |]
+ | Br -> [| 1; 1; 0; 0 |]
+ | Cbnz -> [| 1; 1; 0; 0 |]
+ | Cbz -> [| 1; 1; 0; 0 |]
+ | Cls -> [| 1; 1; 0; 0 |]
+ | Clz -> [| 1; 1; 0; 0 |]
+ | Cmn -> [| 1; 1; 1; 0 |]
+ | Cmp -> [| 1; 1; 1; 0 |]
+ | Csel -> [| 1; 1; 1; 0 |]
+ | Cset -> [| 1; 1; 1; 0 |]
+ | Eon -> [| 1; 1; 0; 0 |]
+ | Eor -> [| 1; 1; 0; 0 |]
+ | Fabs -> [| 1; 1; 1; 0 |]
+ | Fadd -> [| 1; 1; 1; 0 |]
+ | Fcmp -> [| 1; 1; 1; 0 |]
+ | Fcsel -> [| 1; 1; 0; 0 |]
+ | Fcvt -> [| 1; 1; 1; 0 |]
+ | Fcvtzs -> [| 1; 1; 1; 0 |]
+ | Fcvtzu -> [| 1; 1; 1; 0 |]
+ | Fdiv -> [| 1; 1; 1; 0 |]
+ | Fmadd -> [| 1; 1; 0; 0 |]
+ | Fmov -> [| 1; 1; 0; 0 |]
+ | Fmsub -> [| 1; 1; 0; 0 |]
+ | Fmul -> [| 1; 1; 1; 0 |]
+ | Fnmadd -> [| 1; 1; 0; 0 |]
+ | Fnmul -> [| 1; 1; 0; 0 |]
+ | Fnmsub -> [| 1; 1; 0; 0 |]
+ | Fneg -> [| 1; 1; 1; 0 |]
+ | Fsqrt -> [| 1; 1; 0; 0 |]
+ | Fsub -> [| 1; 1; 1; 0 |]
+ | Ldaxr -> [| 1; 0; 0; 1 |]
+ | Ldp -> [| 1; 0; 0; 1 |]
+ | Ldr -> [| 1; 0; 0; 1 |]
+ | Ldrb -> [| 1; 0; 0; 1 |]
+ | Ldrh -> [| 1; 0; 0; 1 |]
+ | Ldrsb -> [| 1; 0; 0; 1 |]
+ | Ldrsh -> [| 1; 0; 0; 1 |]
+ | Ldrsw -> [| 1; 0; 0; 1 |]
+ | Lr -> [| 1; 0; 0; 1 |]
+ | Lsl -> [| 1; 1; 0; 0 |]
+ | Lsr -> [| 1; 1; 0; 0 |]
+ | Madd -> [| 1; 1; 1; 0 |]
+ | Mov -> [| 1; 1; 0; 0 |]
+ | Movk -> [| 1; 1; 0; 0 |]
+ | Movn -> [| 1; 1; 0; 0 |]
+ | Movz -> [| 1; 1; 0; 0 |]
+ | Msub -> [| 1; 1; 1; 0 |]
+ | Nop -> [| 1; 1; 0; 0 |]
+ | Orn -> [| 1; 1; 0; 0 |]
+ | Orr -> [| 1; 1; 0; 0 |]
+ | Ret -> [| 1; 1; 0; 0 |]
+ | Rev -> [| 1; 1; 0; 0 |]
+ | Rev16 -> [| 1; 1; 0; 0 |]
+ | Ror -> [| 1; 1; 0; 0 |]
+ | Sbfiz -> [| 1; 1; 0; 0 |]
+ | Sbfx -> [| 1; 1; 0; 0 |]
+ | Scvtf -> [| 1; 1; 1; 0 |]
+ | Sdiv -> [| 1; 0; 0; 0 |]
+ | Smulh -> [| 1; 1; 0; 0 |]
+ | Stlxr -> [| 1; 0; 0; 1 |]
+ | Stp -> [| 1; 0; 0; 1 |]
+ | Str -> [| 1; 0; 0; 1 |]
+ | Strb -> [| 1; 0; 0; 1 |]
+ | Strh -> [| 1; 0; 0; 1 |]
+ | Sub -> [| 1; 1; 0; 0 |]
+ | Sxtb -> [| 1; 1; 0; 0 |]
+ | Sxth -> [| 1; 1; 0; 0 |]
+ | Sxtw -> [| 1; 1; 0; 0 |]
+ | Tbnz -> [| 1; 1; 0; 0 |]
+ | Tbz -> [| 1; 1; 0; 0 |]
+ | Tst -> [| 1; 1; 1; 0 |]
+ | Ubfiz -> [| 1; 1; 0; 0 |]
+ | Ubfx -> [| 1; 1; 0; 0 |]
+ | Ucvtf -> [| 1; 1; 1; 0 |]
+ | Udiv -> [| 1; 0; 0; 0 |]
+ | Umulh -> [| 1; 1; 0; 0 |]
+ | Uxtb -> [| 1; 1; 0; 0 |]
+ | Uxth -> [| 1; 1; 0; 0 |]
+ | Uxtw -> [| 1; 1; 0; 0 |]
+ | Uxtx -> [| 1; 1; 0; 0 |]
+ | Btbl -> [| 1; 1; 0; 0 |]
+ | Allocframe -> [| 1; 1; 1; 1 |]
+ | Freeframe -> [| 1; 1; 1; 1 |]
+ | Builtin -> [| 1; 1; 1; 1 |]
+ | Cvtx2w -> [| 1; 1; 1; 1 |]
+
+ (*let non_pipelined_resources_of_op (op : operation) (nargs : int) =
+ match op with
+ | Odiv | Odivu -> [| 29 |]
+ | Odivfs -> [| 20 |]
+ | Odivl | Odivlu | Odivf -> [| 50 |]
+ | _ -> [| -1 |];;
+
+ let resources_of_cond (cmp : condition) (nargs : int) =
+ (match cmp with
+ | Ccompf _ (* r FP comparison *)
+ | Cnotcompf _ (* r negation of an FP comparison *)
+ | Ccompfzero _ (* r comparison with 0.0 *)
+ | Cnotcompfzero _ (* r negation of comparison with 0.0 *)
+ | Ccompfs _ (* r FP comparison *)
+ | Cnotcompfs _ (* r negation of an FP comparison *)
+ | Ccompfszero _ (* r equal to 0.0 *)
+ | Cnotcompfszero _ (* r not equal to 0.0 *) ->
+ [| 1; 1; 1; 0 |]
+ | _ -> [| 1; 1; 0; 0 |] )*)
+
+ let latency_of_load trap chunk _ _ = 3
+
+ let latency_of_call _ _ = 6
+
+ let resources_of_load trap chunk addressing nargs = [| 1; 0; 0; 1 |]
+
+ let resources_of_store chunk addressing nargs = [| 1; 0; 0; 1 |]
+
+ let resources_of_call _ _ = resource_bounds
+
+ let resources_of_builtin _ = resource_bounds
+end
+
+let get_opweights () : opweights =
+ (*match !Clflags.option_mtune with*)
+ (*| "cortex-a53" | "cortex-a35" | "" ->*)
+ {
+ pipelined_resource_bounds = Cortex_A53.resource_bounds;
+ nr_non_pipelined_units = Cortex_A53.nr_non_pipelined_units;
+ latency_of_op = Cortex_A53.latency_of_op;
+ resources_of_op =
+ Cortex_A53.resources_of_op
+ (*non_pipelined_resources_of_op = Cortex_A53.non_pipelined_resources_of_op;*)
+ (*latency_of_load = Cortex_A53.latency_of_load;*)
+ (*resources_of_load = Cortex_A53.resources_of_load;*)
+ (*resources_of_store = Cortex_A53.resources_of_store;*)
+ (*resources_of_cond = Cortex_A53.resources_of_cond;*)
+ (*latency_of_call = Cortex_A53.latency_of_call;*)
+ (*resources_of_call = Cortex_A53.resources_of_call;*)
+ (*resources_of_builtin = Cortex_A53.resources_of_builtin*);
+ }
+
+(*| xxx -> failwith (Printf.sprintf "unknown -mtune: %s" xxx);;*)
diff --git a/aarch64/OrigAsmgen.ml b/aarch64/OrigAsmgen.ml
new file mode 100644
index 00000000..1bbcf085
--- /dev/null
+++ b/aarch64/OrigAsmgen.ml
@@ -0,0 +1,282 @@
+(** File (more or less) extracted from the official aarch64/Asmgen.v of CompCert
+
+TODO: prune some definition in these files by reusing the ones of Asmblockgen that are identical...
+e.g. all those which do not involve Asm.code
+
+**)
+
+open Asm
+open BinInt
+open BinNums
+open Integers
+open List0
+open Zbits
+
+module I = Integers.Int
+module I64 = Integers.Int64
+module N = PeanoNat.Nat
+
+let s_ x = Datatypes.S x
+let o_ = Datatypes.O
+
+module Automaton =
+ struct
+ type state =
+ | SA
+ | SB
+ | SC
+ | SD
+ | SE
+ | SF
+ | SG
+ | Sbad
+
+ (** val start : state **)
+
+ let start =
+ SA
+
+ (** val next : state -> bool -> state **)
+
+ let next s b =
+ match s with
+ | SA -> if b then SC else SB
+ | SB -> if b then SD else SB
+ | SC -> if b then SC else SE
+ | SD -> if b then SD else SF
+ | SE -> if b then SG else SE
+ | SF -> if b then Sbad else SF
+ | SG -> if b then SG else Sbad
+ | Sbad -> Sbad
+
+ (** val accepting : state -> bool **)
+
+ let accepting = function
+ | Sbad -> false
+ | _ -> true
+
+ (** val run : nat -> state -> coq_Z -> bool **)
+
+ let rec run len s x =
+ match len with
+ | Datatypes.O -> accepting s
+ | Datatypes.S len0 -> run len0 (next s (Z.odd x)) (Z.div2 x)
+ end
+
+(** val logical_imm_length : coq_Z -> bool -> nat **)
+
+let logical_imm_length x sixtyfour =
+ let test = fun n ->
+ Z.eqb (coq_Zzero_ext n x) (coq_Zzero_ext n (Z.shiftr x n))
+ in
+ if (&&) sixtyfour
+ (Datatypes.negb
+ (test (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xO (Coq_xO Coq_xH))))))))
+ then s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_
+ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_
+ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_
+ o_)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
+ else if Datatypes.negb (test (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xO Coq_xH))))))
+ then s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_
+ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ o_)))))))))))))))))))))))))))))))
+ else if Datatypes.negb (test (Zpos (Coq_xO (Coq_xO (Coq_xO Coq_xH)))))
+ then s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_
+ o_)))))))))))))))
+ else if Datatypes.negb (test (Zpos (Coq_xO (Coq_xO Coq_xH))))
+ then s_ (s_ (s_ (s_ (s_ (s_ (s_ (s_ o_)))))))
+ else if Datatypes.negb (test (Zpos (Coq_xO Coq_xH)))
+ then s_ (s_ (s_ (s_ o_)))
+ else s_ (s_ o_)
+
+(** val is_logical_imm32 : I.int -> bool **)
+
+let is_logical_imm32 x =
+ (&&) ((&&) (Datatypes.negb (I.eq x I.zero)) (Datatypes.negb (I.eq x I.mone)))
+ (Automaton.run (logical_imm_length (I.unsigned x) false)
+ Automaton.start (I.unsigned x))
+
+(** val is_logical_imm64 : I64.int -> bool **)
+
+let is_logical_imm64 x =
+ (&&) ((&&) (Datatypes.negb (I64.eq x I64.zero)) (Datatypes.negb (I64.eq x I64.mone)))
+ (Automaton.run (logical_imm_length (I64.unsigned x) true)
+ Automaton.start (I64.unsigned x))
+
+(** val is_arith_imm32 : I.int -> bool **)
+
+let is_arith_imm32 x =
+ (||) (I.eq x (I.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))) x))
+ (I.eq x
+ (I.shl
+ (I.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH))))
+ (I.shru x (I.repr (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))))))
+ (I.repr (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))))))
+
+(** val is_arith_imm64 : I64.int -> bool **)
+
+let is_arith_imm64 x =
+ (||)
+ (I64.eq x (I64.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))) x))
+ (I64.eq x
+ (I64.shl
+ (I64.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH))))
+ (I64.shru x (I64.repr (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))))))
+ (I64.repr (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))))))
+
+(** val decompose_int : nat -> coq_Z -> coq_Z -> (coq_Z * coq_Z) list **)
+
+let rec decompose_int n n0 p =
+ match n with
+ | Datatypes.O -> []
+ | Datatypes.S n1 ->
+ let frag =
+ coq_Zzero_ext (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xO Coq_xH)))))
+ (Z.shiftr n0 p)
+ in
+ if Z.eqb frag Z0
+ then decompose_int n1 n0
+ (Z.add p (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xO Coq_xH))))))
+ else (frag,
+ p) :: (decompose_int n1
+ (Z.ldiff n0
+ (Z.shiftl (Zpos (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI
+ (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI
+ (Coq_xI (Coq_xI (Coq_xI (Coq_xI Coq_xH))))))))))))))))
+ p))
+ (Z.add p (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xO Coq_xH)))))))
+
+(** val negate_decomposition :
+ (coq_Z * coq_Z) list -> (coq_Z * coq_Z) list **)
+
+let negate_decomposition l =
+ map (fun np ->
+ ((Z.coq_lxor (fst np) (Zpos (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI
+ (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI (Coq_xI
+ (Coq_xI (Coq_xI Coq_xH))))))))))))))))), (snd np))) l
+
+(** val loadimm_k :
+ isize -> ireg -> (coq_Z * coq_Z) list -> Asm.code -> Asm.code **)
+
+let loadimm_k sz rd l k =
+ fold_right (fun np k0 -> (Pmovk (sz, rd, (fst np), (snd np))) :: k0) k l
+
+(** val loadimm_z :
+ isize -> ireg -> (coq_Z * coq_Z) list -> Asm.code -> Asm.code **)
+
+let loadimm_z sz rd l k =
+ match l with
+ | [] -> (Pmovz (sz, rd, Z0, Z0)) :: k
+ | p :: l0 ->
+ let (n1, p1) = p in (Pmovz (sz, rd, n1, p1)) :: (loadimm_k sz rd l0 k)
+
+(** val loadimm_n :
+ isize -> ireg -> (coq_Z * coq_Z) list -> Asm.code -> Asm.code **)
+
+let loadimm_n sz rd l k =
+ match l with
+ | [] -> (Pmovn (sz, rd, Z0, Z0)) :: k
+ | p :: l0 ->
+ let (n1, p1) = p in
+ (Pmovn (sz, rd, n1, p1)) :: (loadimm_k sz rd (negate_decomposition l0) k)
+
+(** val loadimm : isize -> ireg -> coq_Z -> Asm.code -> Asm.code **)
+
+let loadimm sz rd n k =
+ let n0 = match sz with
+ | W -> s_ (s_ o_)
+ | X -> s_ (s_ (s_ (s_ o_))) in
+ let dz = decompose_int n0 n Z0 in
+ let dn = decompose_int n0 (Z.lnot n) Z0 in
+ if N.leb (Datatypes.length dz) (Datatypes.length dn)
+ then loadimm_z sz rd dz k
+ else loadimm_n sz rd dn k
+
+(** val loadimm32 : ireg -> I.int -> Asm.code -> Asm.code **)
+
+let loadimm32 rd n k =
+ if is_logical_imm32 n
+ then (Porrimm (W, rd, XZR, (I.unsigned n))) :: k
+ else loadimm W rd (I.unsigned n) k
+
+(** val loadimm64 : ireg -> I64.int -> Asm.code -> Asm.code **)
+
+let loadimm64 rd n k =
+ if is_logical_imm64 n
+ then (Porrimm (X, rd, XZR, (I64.unsigned n))) :: k
+ else loadimm X rd (I64.unsigned n) k
+
+(** val addimm_aux :
+ (iregsp -> iregsp -> coq_Z -> Asm.instruction) -> iregsp -> iregsp ->
+ coq_Z -> Asm.code -> Asm.instruction list **)
+
+let addimm_aux insn rd r1 n k =
+ let nlo = coq_Zzero_ext (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH)))) n in
+ let nhi = Z.sub n nlo in
+ if Z.eqb nhi Z0
+ then (insn rd r1 nlo) :: k
+ else if Z.eqb nlo Z0
+ then (insn rd r1 nhi) :: k
+ else (insn rd r1 nhi) :: ((insn rd rd nlo) :: k)
+
+(** val addimm32 : ireg -> ireg -> I.int -> Asm.code -> Asm.code **)
+
+let addimm32 rd r1 n k =
+ let m = I.neg n in
+ if I.eq n
+ (I.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xI Coq_xH))))) n)
+ then addimm_aux (fun x x0 x1 -> Paddimm (W, x, x0, x1)) (RR1 rd) (RR1 r1)
+ (I.unsigned n) k
+ else if I.eq m
+ (I.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xI Coq_xH))))) m)
+ then addimm_aux (fun x x0 x1 -> Psubimm (W, x, x0, x1)) (RR1 rd) (RR1
+ r1) (I.unsigned m) k
+ else if I.lt n I.zero
+ then loadimm32 X16 m ((Psub (W, rd, (RR0 r1), X16, SOnone)) :: k)
+ else loadimm32 X16 n ((Padd (W, rd, (RR0 r1), X16, SOnone)) :: k)
+
+(** val addimm64 : iregsp -> iregsp -> I64.int -> Asm.code -> Asm.code **)
+
+let addimm64 rd r1 n k =
+ let m = I64.neg n in
+ if I64.eq n
+ (I64.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xI Coq_xH))))) n)
+ then addimm_aux (fun x x0 x1 -> Paddimm (X, x, x0, x1)) rd r1
+ (I64.unsigned n) k
+ else if I64.eq m
+ (I64.zero_ext (Zpos (Coq_xO (Coq_xO (Coq_xO (Coq_xI Coq_xH)))))
+ m)
+ then addimm_aux (fun x x0 x1 -> Psubimm (X, x, x0, x1)) rd r1
+ (I64.unsigned m) k
+ else if I64.lt n I64.zero
+ then loadimm64 X16 m ((Psubext (rd, r1, X16, (EOuxtx
+ I.zero))) :: k)
+ else loadimm64 X16 n ((Paddext (rd, r1, X16, (EOuxtx
+ I.zero))) :: k)
+
+(** val offset_representable : coq_Z -> I64.int -> bool **)
+
+let offset_representable sz ofs =
+ let isz = I64.repr sz in
+ (||)
+ (I64.eq ofs
+ (I64.sign_ext (Zpos (Coq_xI (Coq_xO (Coq_xO Coq_xH)))) ofs))
+ ((&&) (I64.eq (I64.modu ofs isz) I64.zero)
+ (I64.ltu ofs
+ (I64.shl isz (I64.repr (Zpos (Coq_xO (Coq_xO (Coq_xI Coq_xH))))))))
+
+(** val indexed_memory_access :
+ (Asm.addressing -> Asm.instruction) -> coq_Z -> iregsp -> Ptrofs.int ->
+ Asm.code -> Asm.instruction list **)
+
+let indexed_memory_access insn sz base ofs k =
+ let ofs0 = Ptrofs.to_int64 ofs in
+ if offset_representable sz ofs0
+ then (insn (ADimm (base, ofs0))) :: k
+ else loadimm64 X16 ofs0 ((insn (ADreg (base, X16))) :: k)
+
+(** val storeptr :
+ ireg -> iregsp -> Ptrofs.int -> Asm.code -> Asm.instruction list **)
+
+let storeptr src base ofs k =
+ indexed_memory_access (fun x -> Pstrx (src, x)) (Zpos (Coq_xO (Coq_xO
+ (Coq_xO Coq_xH)))) base ofs k
diff --git a/aarch64/PostpassScheduling.v b/aarch64/PostpassScheduling.v
new file mode 100644
index 00000000..a9473789
--- /dev/null
+++ b/aarch64/PostpassScheduling.v
@@ -0,0 +1,495 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+(** Implementation (and basic properties) of the verified postpass scheduler *)
+
+Require Import Coqlib Errors AST Integers.
+Require Import Asmblock Axioms Memory Globalenvs.
+Require Import Asmblockdeps Asmblockgenproof0 Asmblockprops.
+(*Require Peephole.*)
+
+Local Open Scope error_monad_scope.
+
+(** * Oracle taking as input a basic block,
+ returns a scheduled basic block *)
+Axiom schedule: bblock -> (list basic) * option control.
+
+Extract Constant schedule => "PostpassSchedulingOracle.schedule".
+
+(*
+(** * Concat all bundles into one big basic block *)
+
+(* Lemmas necessary for defining concat_all *)
+Lemma app_nonil {A: Type} (l l': list A) : l <> nil -> l ++ l' <> nil.
+Proof.
+ intros. destruct l; simpl.
+ - contradiction.
+ - discriminate.
+Qed.
+
+Lemma app_nonil2 {A: Type} : forall (l l': list A), l' <> nil -> l ++ l' <> nil.
+Proof.
+ destruct l.
+ - intros. simpl; auto.
+ - intros. rewrite <- app_comm_cons. discriminate.
+Qed.
+
+Definition check_size bb :=
+ if zlt Ptrofs.max_unsigned (size bb)
+ then Error (msg "PostpassSchedulingproof.check_size")
+ else OK tt.
+
+Program Definition concat2 (bb bb': bblock) : res bblock :=
+ do ch <- check_size bb;
+ do ch' <- check_size bb';
+ match (exit bb) with
+ | None =>
+ match (header bb') with
+ | nil =>
+ match (exit bb') with
+ | Some (PExpand (Pbuiltin _ _ _)) => Error (msg "PostpassSchedulingproof.concat2: builtin not alone")
+ | _ => OK {| header := header bb; body := body bb ++ body bb'; exit := exit bb' |}
+ end
+ | _ => Error (msg "PostpassSchedulingproof.concat2")
+ end
+ | _ => Error (msg "PostpassSchedulingproof.concat2")
+ end.
+Next Obligation.
+ apply wf_bblock_refl. constructor.
+ - destruct bb' as [hd' bdy' ex' WF']. destruct bb as [hd bdy ex WF]. simpl in *.
+ apply wf_bblock_refl in WF'. apply wf_bblock_refl in WF.
+ inversion_clear WF'. inversion_clear WF. clear H1 H3.
+ inversion H2; inversion H0.
+ + left. apply app_nonil. auto.
+ + right. auto.
+ + left. apply app_nonil2. auto.
+ + right. auto.
+ - unfold builtin_alone. intros. rewrite H0 in H.
+ assert (Some (PExpand (Pbuiltin ef args res)) <> Some (PExpand (Pbuiltin ef args res))).
+ apply (H ef args res). contradict H1. auto.
+Defined.
+
+Lemma concat2_zlt_size:
+ forall a b bb,
+ concat2 a b = OK bb ->
+ size a <= Ptrofs.max_unsigned
+ /\ size b <= Ptrofs.max_unsigned.
+Proof.
+ intros. monadInv H.
+ split.
+ - unfold check_size in EQ. destruct (zlt Ptrofs.max_unsigned (size a)); monadInv EQ. omega.
+ - unfold check_size in EQ1. destruct (zlt Ptrofs.max_unsigned (size b)); monadInv EQ1. omega.
+Qed.
+
+Lemma concat2_noexit:
+ forall a b bb,
+ concat2 a b = OK bb ->
+ exit a = None.
+Proof.
+ intros. destruct a as [hd bdy ex WF]; simpl in *.
+ destruct ex as [e|]; simpl in *; auto.
+ unfold concat2 in H. simpl in H. monadInv H.
+Qed.
+
+Lemma concat2_decomp:
+ forall a b bb,
+ concat2 a b = OK bb ->
+ body bb = body a ++ body b
+ /\ exit bb = exit b.
+Proof.
+ intros. exploit concat2_noexit; eauto. intros.
+ destruct a as [hda bda exa WFa]; destruct b as [hdb bdb exb WFb]; destruct bb as [hd bd ex WF]; simpl in *.
+ subst exa.
+ unfold concat2 in H; simpl in H.
+ destruct hdb.
+ - destruct exb.
+ + destruct c.
+ * destruct i; monadInv H; split; auto.
+ * monadInv H. split; auto.
+ + monadInv H. split; auto.
+ - monadInv H.
+Qed.
+
+Lemma concat2_size:
+ forall a b bb, concat2 a b = OK bb -> size bb = size a + size b.
+Proof.
+ intros. unfold concat2 in H.
+ destruct a as [hda bda exa WFa]; destruct b as [hdb bdb exb WFb]; destruct bb as [hd bdy ex WF]; simpl in *.
+ destruct exa; monadInv H. destruct hdb; try (monadInv EQ2). destruct exb; try (monadInv EQ2).
+ - destruct c.
+ + destruct i; monadInv EQ2;
+ unfold size; simpl; rewrite app_length; rewrite Nat.add_0_r; rewrite <- Nat2Z.inj_add; rewrite Nat.add_assoc; reflexivity.
+ + monadInv EQ2. unfold size; simpl. rewrite app_length. rewrite Nat.add_0_r. rewrite <- Nat2Z.inj_add. rewrite Nat.add_assoc. reflexivity.
+ - unfold size; simpl. rewrite app_length. repeat (rewrite Nat.add_0_r). rewrite <- Nat2Z.inj_add. reflexivity.
+Qed.
+
+Lemma concat2_header:
+ forall bb bb' tbb,
+ concat2 bb bb' = OK tbb -> header bb = header tbb.
+Proof.
+ intros. destruct bb as [hd bdy ex COR]; destruct bb' as [hd' bdy' ex' COR']; destruct tbb as [thd tbdy tex tCOR]; simpl in *.
+ unfold concat2 in H. simpl in H. monadInv H.
+ destruct ex; try discriminate. destruct hd'; try discriminate. destruct ex'.
+ - destruct c.
+ + destruct i; try discriminate; congruence.
+ + congruence.
+ - congruence.
+Qed.
+
+Lemma concat2_no_header_in_middle:
+ forall bb bb' tbb,
+ concat2 bb bb' = OK tbb ->
+ header bb' = nil.
+Proof.
+ intros. destruct bb as [hd bdy ex COR]; destruct bb' as [hd' bdy' ex' COR']; destruct tbb as [thd tbdy tex tCOR]; simpl in *.
+ unfold concat2 in H. simpl in H. monadInv H.
+ destruct ex; try discriminate. destruct hd'; try discriminate. reflexivity.
+Qed.
+
+
+
+Fixpoint concat_all (lbb: list bblock) : res bblock :=
+ match lbb with
+ | nil => Error (msg "PostpassSchedulingproof.concatenate: empty list")
+ | bb::nil => OK bb
+ | bb::lbb =>
+ do bb' <- concat_all lbb;
+ concat2 bb bb'
+ end.
+
+Lemma concat_all_size :
+ forall lbb a bb bb',
+ concat_all (a :: lbb) = OK bb ->
+ concat_all lbb = OK bb' ->
+ size bb = size a + size bb'.
+Proof.
+ intros. unfold concat_all in H. fold concat_all in H.
+ destruct lbb; try discriminate.
+ monadInv H. rewrite H0 in EQ. inv EQ.
+ apply concat2_size. assumption.
+Qed.
+
+Lemma concat_all_header:
+ forall lbb bb tbb,
+ concat_all (bb::lbb) = OK tbb -> header bb = header tbb.
+Proof.
+ destruct lbb.
+ - intros. simpl in H. congruence.
+ - intros. simpl in H. destruct lbb.
+ + inv H. eapply concat2_header; eassumption.
+ + monadInv H. eapply concat2_header; eassumption.
+Qed.
+
+Lemma concat_all_no_header_in_middle:
+ forall lbb tbb,
+ concat_all lbb = OK tbb ->
+ Forall (fun b => header b = nil) (tail lbb).
+Proof.
+ induction lbb; intros; try constructor.
+ simpl. simpl in H. destruct lbb.
+ - constructor.
+ - monadInv H. simpl tl in IHlbb. constructor.
+ + apply concat2_no_header_in_middle in EQ0. apply concat_all_header in EQ. congruence.
+ + apply IHlbb in EQ. assumption.
+Qed.
+
+Inductive is_concat : bblock -> list bblock -> Prop :=
+ | mk_is_concat: forall tbb lbb, concat_all lbb = OK tbb -> is_concat tbb lbb.
+*)
+(** * Remainder of the verified scheduler *)
+
+Definition verify_schedule (bb bb' : bblock) : res unit :=
+ match bblock_simub bb bb' with
+ | true => OK tt
+ | false => Error (msg "PostpassScheduling.verify_schedule")
+ end.
+
+(*Definition verify_size bb lbb := if (Z.eqb (size bb) (size_blocks lbb)) then OK tt else Error (msg "PostpassScheduling:verify_size: wrong size").*)
+
+(*Lemma verify_size_size:*)
+ (*forall bb lbb, verify_size bb lbb = OK tt -> size bb = size_blocks lbb.*)
+(*Proof.*)
+ (*intros. unfold verify_size in H. destruct (size bb =? size_blocks lbb) eqn:SIZE; try discriminate.*)
+ (*apply Z.eqb_eq. assumption.*)
+(*Qed.*)
+
+(*Lemma verify_schedule_no_header:*)
+ (*forall bb bb',*)
+ (*verify_schedule (no_header bb) bb' = verify_schedule bb bb'.*)
+(*Proof.*)
+ (*intros. unfold verify_schedule. unfold bblock_simub. unfold pure_bblock_simu_test, bblock_simu_test. rewrite trans_block_noheader_inv.*)
+ (*reflexivity.*)
+(*Qed.*)
+
+
+(*Lemma stick_header_verify_schedule:*)
+ (*forall hd bb' hbb' bb,*)
+ (*stick_header hd bb' = hbb' ->*)
+ (*verify_schedule bb bb' = verify_schedule bb hbb'.*)
+(*Proof.*)
+ (*intros. unfold verify_schedule. unfold bblock_simub, pure_bblock_simu_test, bblock_simu_test.*)
+ (*rewrite <- H. rewrite trans_block_header_inv. reflexivity.*)
+(*Qed.*)
+
+(*Lemma check_size_stick_header:*)
+ (*forall bb hd,*)
+ (*check_size bb = check_size (stick_header hd bb).*)
+(*Proof.*)
+ (*intros. unfold check_size. rewrite stick_header_size. reflexivity.*)
+(*Qed.*)
+
+(*Lemma stick_header_concat2:*)
+ (*forall bb bb' hd tbb,*)
+ (*concat2 bb bb' = OK tbb ->*)
+ (*concat2 (stick_header hd bb) bb' = OK (stick_header hd tbb).*)
+(*Proof.*)
+ (*intros. monadInv H. erewrite check_size_stick_header in EQ.*)
+ (*unfold concat2. rewrite EQ. rewrite EQ1. simpl.*)
+ (*destruct bb as [hdr bdy ex COR]; destruct bb' as [hdr' bdy' ex' COR']; simpl in *.*)
+ (*destruct ex; try discriminate. destruct hdr'; try discriminate. destruct ex'.*)
+ (*- destruct c.*)
+ (*+ destruct i; try discriminate; inv EQ2; unfold stick_header; simpl; reflexivity.*)
+ (*+ inv EQ2. unfold stick_header; simpl. reflexivity.*)
+ (*- inv EQ2. unfold stick_header; simpl. reflexivity.*)
+(*Qed.*)
+
+(*Lemma stick_header_concat_all:*)
+ (*forall bb c tbb hd,*)
+ (*concat_all (bb :: c) = OK tbb ->*)
+ (*concat_all (stick_header hd bb :: c) = OK (stick_header hd tbb).*)
+(*Proof.*)
+ (*intros. simpl in *. destruct c; try congruence.*)
+ (*monadInv H. rewrite EQ. simpl.*)
+ (*apply stick_header_concat2. assumption.*)
+(*Qed.*)
+
+(*Lemma stick_header_code_no_header:*)
+ (*forall bb c,*)
+ (*stick_header_code (header bb) (no_header bb :: c) = OK (bb :: c).*)
+(*Proof.*)
+ (*intros. unfold stick_header_code. simpl. rewrite stick_header_no_header. reflexivity.*)
+(*Qed.*)
+
+(*Lemma hd_tl_size:*)
+ (*forall lbb bb, hd_error lbb = Some bb -> size_blocks lbb = size bb + size_blocks (tl lbb).*)
+(*Proof.*)
+ (*destruct lbb.*)
+ (*- intros. simpl in H. discriminate.*)
+ (*- intros. simpl in H. inv H. simpl. reflexivity.*)
+(*Qed.*)
+
+(*Lemma stick_header_code_size:*)
+ (*forall h lbb lbb', stick_header_code h lbb = OK lbb' -> size_blocks lbb = size_blocks lbb'.*)
+(*Proof.*)
+ (*intros. unfold stick_header_code in H. destruct (hd_error lbb) eqn:HD; try discriminate.*)
+ (*inv H. simpl. rewrite stick_header_size. erewrite hd_tl_size; eauto.*)
+(*Qed.*)
+
+(*Lemma stick_header_code_no_header_in_middle:*)
+ (*forall c h lbb,*)
+ (*stick_header_code h c = OK lbb ->*)
+ (*Forall (fun b => header b = nil) (tl c) ->*)
+ (*Forall (fun b => header b = nil) (tl lbb).*)
+(*Proof.*)
+ (*destruct c; intros.*)
+ (*- unfold stick_header_code in H. simpl in H. discriminate.*)
+ (*- unfold stick_header_code in H. simpl in H. inv H. simpl in H0.*)
+ (*simpl. assumption.*)
+(*Qed.*)
+
+(*Lemma stick_header_code_concat_all:*)
+ (*forall hd lbb hlbb tbb,*)
+ (*stick_header_code hd lbb = OK hlbb ->*)
+ (*concat_all lbb = OK tbb ->*)
+ (*exists htbb,*)
+ (*concat_all hlbb = OK htbb*)
+ (*/\ stick_header hd tbb = htbb.*)
+(*Proof.*)
+ (*intros. exists (stick_header hd tbb). split; auto.*)
+ (*destruct lbb.*)
+ (*- unfold stick_header_code in H. simpl in H. discriminate.*)
+ (*- unfold stick_header_code in H. simpl in H. inv H.*)
+ (*apply stick_header_concat_all. assumption.*)
+(*Qed.*)
+
+Program Definition make_bblock_from_basics lb :=
+ match lb with
+ | nil => Error (msg "PostpassScheduling.make_bblock_from_basics")
+ | b :: lb => OK {| header := nil; body := b::lb; exit := None |}
+ end.
+
+Program Definition schedule_to_bblock (lb: list basic) (oc: option control) : res bblock :=
+ match oc with
+ | None => make_bblock_from_basics lb
+ | Some c => OK {| header := nil; body := lb; exit := Some c |}
+ end.
+Next Obligation.
+ unfold Is_true, AB.non_empty_bblockb.
+ unfold AB.non_empty_exit. rewrite orb_true_r. reflexivity.
+Qed.
+
+Definition do_schedule (bb: bblock) : res bblock :=
+ if (Z.eqb (size bb) 1) then OK (bb)
+ else match (schedule bb) with (lb, oc) => schedule_to_bblock lb oc end. (* TODO Something here *)
+
+(* TODO to remove ? *)
+(*Definition verify_par_bblock (bb: bblock) : res unit :=*)
+ (*if (bblock_para_check bb) then OK tt else Error (msg "PostpassScheduling.verify_par_bblock").*)
+(*Fixpoint verify_par (lbb: list bblock) :=*)
+ (*match lbb with*)
+ (*| nil => OK tt*)
+ (*| bb :: lbb => do res <- verify_par_bblock bb; verify_par lbb*)
+ (*end.*)
+
+Definition verified_schedule (bb : bblock) : res bblock :=
+ let bb' := no_header bb in
+ (* TODO remove? let bb'' := Peephole.optimize_bblock bb' in *)
+ do lb <- do_schedule bb';
+ (*do tbb <- concat_all lbb;*)
+ (*do sizecheck <- verify_size bb lbb;*)
+ do schedcheck <- verify_schedule bb' lb; (* TODO Keep this one *)
+ (*do parcheck <- verify_par res;*)
+ OK (stick_header (header bb) lb).
+
+(*Lemma verified_schedule_nob_size:*)
+ (*forall bb lbb, verified_schedule_nob bb = OK lbb -> size bb = size_blocks lbb.*)
+(*Proof.*)
+ (*intros. monadInv H. erewrite <- stick_header_code_size; eauto.*)
+ (*apply verify_size_size.*)
+ (*destruct x1; try discriminate. assumption.*)
+(*Qed.*)
+
+(*Lemma verified_schedule_nob_no_header_in_middle:*)
+ (*forall lbb bb,*)
+ (*verified_schedule_nob bb = OK lbb ->*)
+ (*Forall (fun b => header b = nil) (tail lbb).*)
+(*Proof.*)
+ (*intros. monadInv H. eapply stick_header_code_no_header_in_middle; eauto.*)
+ (*eapply concat_all_no_header_in_middle. eassumption.*)
+(*Qed.*)
+
+(*Lemma verified_schedule_nob_header:*)
+ (*forall bb tbb lbb,*)
+ (*verified_schedule_nob bb = OK (tbb :: lbb) ->*)
+ (*header bb = header tbb*)
+ (*/\ Forall (fun b => header b = nil) lbb.*)
+(*Proof.*)
+ (*intros. split.*)
+ (*- monadInv H. unfold stick_header_code in EQ3. destruct (hd_error _); try discriminate. inv EQ3.*)
+ (*simpl. reflexivity.*)
+ (*- apply verified_schedule_nob_no_header_in_middle in H. assumption.*)
+(*Qed.*)
+
+
+(*Definition verified_schedule (bb : bblock) : res (list bblock) :=*)
+ (*verified_schedule_nob bb.*)
+(* TODO Remove?
+ match exit bb with
+ | Some (PExpand (Pbuiltin ef args res)) => OK (bb::nil) (* Special case for ensuring the lemma verified_schedule_builtin_idem *)
+ | _ => verified_schedule_nob bb
+ end.*)
+
+(*Lemma verified_schedule_size:*)
+ (*forall bb lbb, verified_schedule bb = OK lbb -> size bb = size_blocks lbb.*)
+(*Proof.*)
+ (*intros. unfold verified_schedule in H. destruct (exit bb). destruct c. destruct i.*)
+ (*all: try (apply verified_schedule_nob_size; auto; fail).*)
+ (*inv H. simpl. omega.*)
+(*Qed.*)
+
+(*Lemma verified_schedule_no_header_in_middle:*)
+ (*forall lbb bb,*)
+ (*verified_schedule bb = OK lbb ->*)
+ (*Forall (fun b => header b = nil) (tail lbb).*)
+(*Proof.*)
+ (*intros. unfold verified_schedule in H. destruct (exit bb). destruct c. destruct i.*)
+ (*all: try (eapply verified_schedule_nob_no_header_in_middle; eauto; fail).*)
+ (*inv H. simpl. auto.*)
+(*Qed.*)
+
+(*Lemma verified_schedule_header:*)
+ (*forall bb tbb lbb,*)
+ (*verified_schedule bb = OK (tbb :: lbb) ->*)
+ (*header bb = header tbb*)
+ (*/\ Forall (fun b => header b = nil) lbb.*)
+(*Proof.*)
+ (*intros. unfold verified_schedule in H. destruct (exit bb). destruct c. destruct i.*)
+ (*all: try (eapply verified_schedule_nob_header; eauto; fail).*)
+ (*inv H. split; simpl; auto.*)
+(*Qed.*)
+
+
+(*Lemma verified_schedule_nob_correct:*)
+ (*forall ge f bb lbb,*)
+ (*verified_schedule_nob bb = OK lbb ->*)
+ (*exists tbb,*)
+ (*is_concat tbb lbb*)
+ (*/\ bblock_simu ge f bb tbb.*)
+(*Proof.*)
+ (*intros. monadInv H.*)
+ (*exploit stick_header_code_concat_all; eauto.*)
+ (*intros (tbb & CONC & STH).*)
+ (*exists tbb. split; auto. constructor; auto.*)
+ (*rewrite verify_schedule_no_header in EQ2. erewrite stick_header_verify_schedule in EQ2; eauto.*)
+ (*eapply bblock_simub_correct; eauto. unfold verify_schedule in EQ2.*)
+ (*destruct (bblock_simub _ _); auto; try discriminate.*)
+(*Qed.*)
+
+(*Theorem verified_schedule_correct:*)
+ (*forall ge f bb lbb,*)
+ (*verified_schedule bb = OK lbb ->*)
+ (*exists tbb,*)
+ (*is_concat tbb lbb*)
+ (*/\ bblock_simu ge f bb tbb.*)
+(*Proof.*)
+ (*intros. unfold verified_schedule in H. destruct (exit bb). destruct c. destruct i.*)
+ (*all: try (eapply verified_schedule_nob_correct; eauto; fail).*)
+ (*inv H. eexists. split; simpl; auto. constructor; auto. simpl; auto. constructor; auto.*)
+(*Qed.*)
+
+(*Lemma verified_schedule_builtin_idem:*)
+ (*forall bb ef args res lbb,*)
+ (*exit bb = Some (PExpand (Pbuiltin ef args res)) ->*)
+ (*verified_schedule bb = OK lbb ->*)
+ (*lbb = bb :: nil.*)
+(*Proof.*)
+ (*intros. unfold verified_schedule in H0. rewrite H in H0. inv H0. reflexivity.*)
+(*Qed.*)
+
+
+Fixpoint transf_blocks (lbb : list bblock) : res (list bblock) :=
+ match lbb with
+ | nil => OK nil
+ | bb :: lbb =>
+ do tlbb <- transf_blocks lbb;
+ do tbb <- verified_schedule bb;
+ OK (tbb :: tlbb)
+ end.
+
+Definition transl_function (f: function) : res function :=
+ do lb <- transf_blocks (fn_blocks f);
+ OK (mkfunction (fn_sig f) lb).
+
+Definition transf_function (f: function) : res function :=
+ do tf <- transl_function f;
+ if zlt Ptrofs.max_unsigned (size_blocks tf.(fn_blocks))
+ then Error (msg "code size exceeded")
+ else OK tf.
+
+Definition transf_fundef (f: fundef) : res fundef :=
+ transf_partial_fundef transf_function f.
+
+Definition transf_program (p: program) : res program :=
+ transform_partial_program transf_fundef p.
diff --git a/aarch64/PostpassSchedulingOracle.ml b/aarch64/PostpassSchedulingOracle.ml
new file mode 100644
index 00000000..821a1d53
--- /dev/null
+++ b/aarch64/PostpassSchedulingOracle.ml
@@ -0,0 +1,984 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* Léo Gourdin UGA, VERIMAG *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+open Asmblock
+open OpWeightsAsm
+open InstructionScheduler
+
+let debug = true
+
+(**
+ * Extracting infos from Asm instructions
+ *)
+
+type location = Reg of Asm.preg | Mem | IREG0_XZR
+
+type ab_inst_rec = {
+ inst : real_instruction;
+ write_locs : location list;
+ read_locs : location list;
+ is_control : bool;
+}
+
+(** Asm constructor to real instructions *)
+
+exception OpaqueInstruction
+
+let arith_p_real = function
+ | Padrp (_, _) -> Adrp
+ | Pmovz (_, _, _) -> Movz
+ | Pmovn (_, _, _) -> Movn
+ | Pfmovimms _ -> Fmov (* TODO not sure about this and below too *)
+ | Pfmovimmd _ -> Fmov
+
+let arith_pp_real = function
+ | Pmov -> Mov
+ | Pmovk (_, _, _) -> Movk
+ | Paddadr (_, _) -> Add
+ | Psbfiz (_, _, _) -> Sbfiz
+ | Psbfx (_, _, _) -> Sbfx
+ | Pubfiz (_, _, _) -> Ubfiz
+ | Pubfx (_, _, _) -> Ubfx
+ | Pfmov -> Fmov
+ | Pfcvtds -> Fcvt
+ | Pfcvtsd -> Fcvt
+ | Pfabs _ -> Fabs
+ | Pfneg _ -> Fneg
+ | Pscvtf (_, _) -> Scvtf
+ | Pucvtf (_, _) -> Ucvtf
+ | Pfcvtzs (_, _) -> Fcvtzs
+ | Pfcvtzu (_, _) -> Fcvtzu
+ | Paddimm (_, _) -> Add
+ | Psubimm (_, _) -> Sub
+
+let arith_ppp_real = function
+ | Pasrv _ -> Asr
+ | Plslv _ -> Lsl
+ | Plsrv _ -> Lsr
+ | Prorv _ -> Ror
+ | Psmulh -> Smulh
+ | Pumulh -> Umulh
+ | Psdiv _ -> Sdiv
+ | Pudiv _ -> Udiv
+ | Paddext _ -> Add
+ | Psubext _ -> Sub
+ | Pfadd _ -> Fadd
+ | Pfdiv _ -> Fdiv
+ | Pfmul _ -> Fmul
+ | Pfsub _ -> Fsub
+
+let arith_rr0r_real = function
+ | Padd (_, _) -> Add
+ | Psub (_, _) -> Sub
+ | Pand (_, _) -> And
+ | Pbic (_, _) -> Bic
+ | Peon (_, _) -> Eon
+ | Peor (_, _) -> Eor
+ | Porr (_, _) -> Orr
+ | Porn (_, _) -> Orn
+
+let arith_rr0_real = function
+ | Pandimm (_, _) -> And
+ | Peorimm (_, _) -> Eor
+ | Porrimm (_, _) -> Orr
+
+let arith_arrrr0_real = function Pmadd _ -> Madd | Pmsub _ -> Msub
+
+let arith_comparison_p_real = function
+ | Pfcmp0 _ -> Fcmp
+ | Pcmpimm (_, _) -> Cmp
+ | Pcmnimm (_, _) -> Cmn
+ | Ptstimm (_, _) -> Tst
+
+let arith_comparison_pp_real = function
+ | Pcmpext _ -> Cmp
+ | Pcmnext _ -> Cmn
+ | Pfcmp _ -> Fcmp
+
+let arith_comparison_r0r_real = function
+ | Pcmp (_, _) -> Cmp
+ | Pcmn (_, _) -> Cmn
+ | Ptst (_, _) -> Tst
+
+let arith_comparison_rr0r_real = function
+ | Padd (_, _) -> Add
+ | Psub (_, _) -> Sub
+ | Pand (_, _) -> And
+ | Pbic (_, _) -> Bic
+ | Peon (_, _) -> Eon
+ | Peor (_, _) -> Eor
+ | Porr (_, _) -> Orr
+ | Porn (_, _) -> Orn
+
+let arith_comparison_rr0_real = function
+ | Pandimm (_, _) -> And
+ | Peorimm (_, _) -> Eor
+ | Porrimm (_, _) -> Orr
+
+let arith_comparison_arrrr0_real = function Pmadd _ -> Madd | Pmsub _ -> Msub
+
+let store_rs_a_real = function
+ | Pstrw -> Str
+ | Pstrw_a -> Str
+ | Pstrx -> Str
+ | Pstrx_a -> Str
+ | Pstrb -> Strb
+ | Pstrh -> Strh
+ | Pstrs -> Str
+ | Pstrd -> Str
+ | Pstrd_a -> Str
+
+let load_rd_a_real = function
+ | Pldrw -> Ldr
+ | Pldrw_a -> Ldr
+ | Pldrx -> Ldr
+ | Pldrx_a -> Ldr
+ | Pldrb _ -> Ldrb
+ | Pldrsb _ -> Ldrsb
+ | Pldrh _ -> Ldrh
+ | Pldrsh _ -> Ldrsh
+ | Pldrzw -> Ldr
+ | Pldrsw -> Ldrsw
+ | Pldrs -> Ldr
+ | Pldrd -> Ldr
+ | Pldrd_a -> Ldr
+
+let loadsymbol_real = Ldr
+
+let cvtsw2x_real = Sxtw
+
+let cvtuw2x_real = Uxtw
+
+let cset_real = Cset
+
+let csel_real = Csel
+
+let fmovi_real = Fmov
+
+let fnmul_real = Fnmul
+
+let b_real = B
+
+let bc_real = B
+
+let bl_real = Bl
+
+let bs_real = B
+
+let blr_real = Blr
+
+let br_real = Br
+
+let ret_real = Ret
+
+let cbnz_real = Cbnz
+
+let cbz_real = Cbz
+
+let tbnz_real = Tbnz
+
+let tbz_real = Tbz
+
+let btbl_real = Btbl
+
+let allocframe_real = Allocframe
+
+let freeframe_real = Freeframe
+
+let builtin_real = Builtin
+
+let cvtx2w_real = Cvtx2w
+
+let is_XZR = function IREG0_XZR -> true | _ -> false
+
+let reg_of_pc = Reg Asm.PC
+
+let reg_of_dreg r = Reg (Asm.DR r)
+
+let reg_of_ireg r = Reg (Asm.DR (Asm.IR (Asm.RR1 r)))
+
+let reg_of_iregsp r = Reg (Asm.DR (Asm.IR r))
+
+let reg_of_ireg0 r =
+ match r with Asm.RR0 ir -> reg_of_ireg ir | Asm.XZR -> IREG0_XZR
+
+let reg_of_freg r = Reg (Asm.DR (Asm.FR r))
+
+let reg_of_cr r = Reg (Asm.CR r)
+
+let regXSP = Reg (Asm.DR (Asm.IR Asm.XSP))
+
+let flags_wlocs =
+ [ reg_of_cr Asm.CN; reg_of_cr Asm.CZ; reg_of_cr Asm.CC; reg_of_cr Asm.CV ]
+
+let arith_p_rec i rd =
+ {
+ inst = arith_p_real i;
+ write_locs = [ rd ];
+ read_locs = [];
+ is_control = false;
+ }
+
+let arith_pp_rec i rd rs =
+ {
+ inst = arith_pp_real i;
+ write_locs = [ rd ];
+ read_locs = [ rs ];
+ is_control = false;
+ }
+
+let arith_ppp_rec i rd r1 r2 =
+ {
+ inst = arith_ppp_real i;
+ write_locs = [ rd ];
+ read_locs = [ r1; r2 ];
+ is_control = false;
+ }
+
+let arith_rr0r_rec i rd r1 r2 =
+ let rlocs = if is_XZR r1 then [ r2 ] else [ r1; r2 ] in
+ {
+ inst = arith_rr0r_real i;
+ write_locs = [ rd ];
+ read_locs = rlocs;
+ is_control = false;
+ }
+
+let arith_rr0_rec i rd r1 =
+ let rlocs = if is_XZR r1 then [] else [ r1 ] in
+ {
+ inst = arith_rr0_real i;
+ write_locs = [ rd ];
+ read_locs = rlocs;
+ is_control = false;
+ }
+
+let arith_arrrr0_rec i rd r1 r2 r3 =
+ let rlocs = if is_XZR r3 then [ r1; r2 ] else [ r1; r2; r3 ] in
+ {
+ inst = arith_arrrr0_real i;
+ write_locs = [ rd ];
+ read_locs = rlocs;
+ is_control = false;
+ }
+
+let arith_comparison_pp_rec i r1 r2 =
+ {
+ inst = arith_comparison_pp_real i;
+ write_locs = flags_wlocs;
+ read_locs = [ r1; r2 ];
+ is_control = false;
+ }
+
+let arith_comparison_r0r_rec i r1 r2 =
+ let rlocs = if is_XZR r1 then [ r2 ] else [ r1; r2 ] in
+ {
+ inst = arith_comparison_r0r_real i;
+ write_locs = flags_wlocs;
+ read_locs = rlocs;
+ is_control = false;
+ }
+
+let arith_comparison_p_rec i r1 =
+ {
+ inst = arith_comparison_p_real i;
+ write_locs = flags_wlocs;
+ read_locs = [ r1 ];
+ is_control = false;
+ }
+
+let get_eval_addressing_rlocs a =
+ match a with
+ | Asm.ADimm (base, _) -> [ reg_of_iregsp base ]
+ | Asm.ADreg (base, r) -> [ reg_of_iregsp base; reg_of_ireg r ]
+ | Asm.ADlsl (base, r, _) -> [ reg_of_iregsp base; reg_of_ireg r ]
+ | Asm.ADsxt (base, r, _) -> [ reg_of_iregsp base; reg_of_ireg r ]
+ | Asm.ADuxt (base, r, _) -> [ reg_of_iregsp base; reg_of_ireg r ]
+ | Asm.ADadr (base, _, _) -> [ reg_of_iregsp base ]
+ | Asm.ADpostincr (base, _) -> []
+
+let load_rec ld rd a =
+ {
+ inst = load_rd_a_real ld;
+ write_locs = [ rd ];
+ read_locs = [ Mem ] @ get_eval_addressing_rlocs a;
+ is_control = false;
+ }
+
+let store_rec st r a =
+ {
+ inst = store_rs_a_real st;
+ write_locs = [ Mem ];
+ read_locs = [ r; Mem ] @ get_eval_addressing_rlocs a;
+ is_control = false;
+ }
+
+let loadsymbol_rec rd id =
+ {
+ inst = loadsymbol_real;
+ write_locs = [ rd ];
+ read_locs = [ Mem ];
+ is_control = false;
+ }
+
+let cvtsw2x_rec rd r1 =
+ {
+ inst = cvtsw2x_real;
+ write_locs = [ rd ];
+ read_locs = [ r1 ];
+ is_control = false;
+ }
+
+let cvtuw2x_rec rd r1 =
+ {
+ inst = cvtuw2x_real;
+ write_locs = [ rd ];
+ read_locs = [ r1 ];
+ is_control = false;
+ }
+
+let cvtx2w_rec rd =
+ {
+ inst = cvtx2w_real;
+ write_locs = [ rd ];
+ read_locs = [ rd ];
+ is_control = false;
+ }
+
+let get_testcond_rlocs c =
+ match c with
+ | Asm.TCeq -> [ reg_of_cr Asm.CZ ]
+ | Asm.TCne -> [ reg_of_cr Asm.CZ ]
+ | Asm.TChs -> [ reg_of_cr Asm.CC ]
+ | Asm.TClo -> [ reg_of_cr Asm.CC ]
+ | Asm.TCmi -> [ reg_of_cr Asm.CN ]
+ | Asm.TCpl -> [ reg_of_cr Asm.CN ]
+ | Asm.TChi -> [ reg_of_cr Asm.CZ; reg_of_cr Asm.CC ]
+ | Asm.TCls -> [ reg_of_cr Asm.CZ; reg_of_cr Asm.CC ]
+ | Asm.TCge -> [ reg_of_cr Asm.CN; reg_of_cr Asm.CV ]
+ | Asm.TClt -> [ reg_of_cr Asm.CN; reg_of_cr Asm.CV ]
+ | Asm.TCgt -> [ reg_of_cr Asm.CN; reg_of_cr Asm.CZ; reg_of_cr Asm.CV ]
+ | Asm.TCle -> [ reg_of_cr Asm.CN; reg_of_cr Asm.CZ; reg_of_cr Asm.CV ]
+
+let cset_rec rd c =
+ {
+ inst = cset_real;
+ write_locs = [ rd ];
+ read_locs = get_testcond_rlocs c;
+ is_control = false;
+ }
+
+let csel_rec rd r1 r2 c =
+ {
+ inst = csel_real;
+ write_locs = [ rd ];
+ read_locs = [ r1; r2 ] @ get_testcond_rlocs c;
+ is_control = false;
+ }
+
+let fmovi_rec fsz rd r1 =
+ let rlocs = if is_XZR r1 then [] else [ r1 ] in
+ {
+ inst = fmovi_real;
+ write_locs = [ rd ];
+ read_locs = rlocs;
+ is_control = false;
+ }
+
+let fnmul_rec fsz rd r1 r2 =
+ {
+ inst = fnmul_real;
+ write_locs = [ rd ];
+ read_locs = [ r1; r2 ];
+ is_control = false;
+ }
+
+let allocframe_rec sz linkofs =
+ {
+ inst = allocframe_real;
+ write_locs = [ Mem; regXSP; reg_of_ireg Asm.X16; reg_of_ireg Asm.X29 ];
+ read_locs = [ regXSP; Mem ];
+ is_control = false;
+ }
+
+let freeframe_rec sz linkofs =
+ {
+ inst = freeframe_real;
+ write_locs = [ Mem; regXSP; reg_of_ireg Asm.X16 ];
+ read_locs = [ regXSP; Mem ];
+ is_control = false;
+ }
+
+let arith_rec i =
+ match i with
+ | PArithP (i', rd) -> arith_p_rec i' (reg_of_dreg rd)
+ | PArithPP (i', rd, rs) -> arith_pp_rec i' (reg_of_dreg rd) (reg_of_dreg rs)
+ | PArithPPP (i', rd, r1, r2) ->
+ arith_ppp_rec i' (reg_of_dreg rd) (reg_of_dreg r1) (reg_of_dreg r2)
+ | PArithRR0R (i', rd, r1, r2) ->
+ arith_rr0r_rec i' (reg_of_ireg rd) (reg_of_ireg0 r1) (reg_of_ireg r2)
+ | PArithRR0 (i', rd, r1) ->
+ arith_rr0_rec i' (reg_of_ireg rd) (reg_of_ireg0 r1)
+ | PArithARRRR0 (i', rd, r1, r2, r3) ->
+ arith_arrrr0_rec i' (reg_of_ireg rd) (reg_of_ireg r1) (reg_of_ireg r2)
+ (reg_of_ireg0 r3)
+ | PArithComparisonPP (i', r1, r2) ->
+ arith_comparison_pp_rec i' (reg_of_dreg r1) (reg_of_dreg r2)
+ | PArithComparisonR0R (i', r1, r2) ->
+ arith_comparison_r0r_rec i' (reg_of_ireg0 r1) (reg_of_ireg r2)
+ | PArithComparisonP (i', r1) -> arith_comparison_p_rec i' (reg_of_dreg r1)
+ | Pcset (rd, c) -> cset_rec (reg_of_ireg rd) c
+ | Pfmovi (fsz, rd, r1) -> fmovi_rec fsz (reg_of_freg rd) (reg_of_ireg0 r1)
+ | Pcsel (rd, r1, r2, c) ->
+ csel_rec (reg_of_dreg rd) (reg_of_dreg r1) (reg_of_dreg r2) c
+ | Pfnmul (fsz, rd, r1, r2) ->
+ fnmul_rec fsz (reg_of_freg rd) (reg_of_freg r1) (reg_of_freg r2)
+
+let basic_rec i =
+ match i with
+ | PArith i' -> arith_rec i'
+ | PLoad (ld, rd, a) -> load_rec ld (reg_of_dreg rd) a
+ | PStore (st, r, a) -> store_rec st (reg_of_dreg r) a
+ | Pallocframe (sz, linkofs) -> allocframe_rec sz linkofs
+ | Pfreeframe (sz, linkofs) -> freeframe_rec sz linkofs
+ | Ploadsymbol (rd, id) -> loadsymbol_rec (reg_of_ireg rd) id
+ | Pcvtsw2x (rd, r1) -> cvtsw2x_rec (reg_of_ireg rd) (reg_of_ireg r1)
+ | Pcvtuw2x (rd, r1) -> cvtuw2x_rec (reg_of_ireg rd) (reg_of_ireg r1)
+ | Pcvtx2w rd -> cvtx2w_rec (reg_of_ireg rd)
+
+let builtin_rec ef args res =
+ (* XXX verify this *)
+ {
+ inst = builtin_real;
+ write_locs = [ Mem ];
+ read_locs = [ Mem ];
+ is_control = true;
+ }
+
+let ctl_flow_rec i =
+ match i with
+ | Pb lbl ->
+ {
+ inst = b_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_pc ];
+ is_control = true;
+ }
+ | Pbc (c, lbl) ->
+ {
+ inst = bc_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_pc ];
+ is_control = true;
+ }
+ | Pbl (id, sg) ->
+ {
+ inst = bl_real;
+ write_locs = [ reg_of_ireg Asm.X30; reg_of_pc ];
+ read_locs = [ reg_of_pc ];
+ is_control = true;
+ }
+ (* XXX not sure about X30 *)
+ | Pbs (id, sg) ->
+ {
+ inst = bs_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [];
+ is_control = true;
+ }
+ | Pblr (r, sg) ->
+ {
+ inst = blr_real;
+ write_locs = [ reg_of_ireg Asm.X30; reg_of_pc ];
+ read_locs = [ reg_of_ireg r ];
+ is_control = true;
+ }
+ | Pbr (r, sg) ->
+ {
+ inst = br_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r ];
+ is_control = true;
+ }
+ | Pret r ->
+ {
+ inst = ret_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r ];
+ is_control = true;
+ }
+ | Pcbnz (sz, r, lbl) ->
+ {
+ inst = cbnz_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r; reg_of_pc ];
+ is_control = true;
+ }
+ | Pcbz (sz, r, lbl) ->
+ {
+ inst = cbz_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r; reg_of_pc ];
+ is_control = true;
+ }
+ | Ptbnz (sz, r, n, lbl) ->
+ {
+ inst = tbnz_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r; reg_of_pc ];
+ is_control = true;
+ }
+ | Ptbz (sz, r, n, lbl) ->
+ {
+ inst = tbz_real;
+ write_locs = [ reg_of_pc ];
+ read_locs = [ reg_of_ireg r; reg_of_pc ];
+ is_control = true;
+ }
+ | Pbtbl (r1, tbl) ->
+ {
+ inst = btbl_real;
+ write_locs = [ reg_of_ireg Asm.X16; reg_of_ireg Asm.X17; reg_of_pc ];
+ read_locs = [ reg_of_ireg r1; reg_of_pc ];
+ is_control = true;
+ }
+
+(* XXX Verify this (Pbtbl) *)
+
+let control_rec i =
+ match i with
+ | Pbuiltin (ef, args, res) -> builtin_rec ef args res
+ | PCtlFlow i' -> ctl_flow_rec i'
+
+let rec basic_recs body =
+ match body with [] -> [] | bi :: body -> basic_rec bi :: basic_recs body
+
+let exit_rec exit = match exit with None -> [] | Some ex -> [ control_rec ex ]
+
+let instruction_recs bb = basic_recs bb.body @ exit_rec bb.exit
+
+(**
+ * Providing informations relative to the real instructions
+ *)
+
+type inst_info = {
+ write_locs : location list;
+ read_locs : location list;
+ is_control : bool;
+ usage : int array;
+ (* resources consumed by the instruction *)
+ latency : int;
+}
+(** Abstraction providing all the necessary informations for solving the scheduling problem *)
+
+(*(** Resources *)*)
+(*type rname = Rissue | Rtiny | Rlite | Rfull | Rlsu | Rmau | Rbcu | Rtca | Rauxr | Rauxw | Rcrrp | Rcrwl | Rcrwh | Rnop*)
+
+(*let resource_names = [Rissue; Rtiny; Rlite; Rfull; Rlsu; Rmau; Rbcu; Rtca; Rauxr; Rauxw; Rcrrp; Rcrwl; Rcrwh; Rnop]*)
+
+(*let rec find_index elt l =*)
+(*match l with*)
+(*| [] -> raise Not_found*)
+(*| e::l -> if (e == elt) then 0*)
+(*else 1 + find_index elt l*)
+
+(*let resource_id resource : int = find_index resource resource_names*)
+
+(*let resource_bounds : int array = Array.of_list (List.map resource_bound resource_names)*)
+
+(*let rec empty_inter la = function*)
+(*| [] -> true*)
+(*| b::lb -> if (List.mem b la) then false else empty_inter la lb*)
+
+let rec_to_info (r : ab_inst_rec) : inst_info =
+ let opweights = OpWeightsAsm.get_opweights () in
+ let usage = opweights.resources_of_op r.inst 0
+ and latency = opweights.latency_of_op r.inst 0 in
+ {
+ write_locs = r.write_locs;
+ read_locs = r.read_locs;
+ usage;
+ latency;
+ is_control = r.is_control;
+ }
+
+let instruction_infos bb = List.map rec_to_info (instruction_recs bb)
+
+(*let instruction_infos bb = instruction_recs bb*)
+
+let instruction_usages bb =
+ let usages = List.map (fun info -> info.usage) (instruction_infos bb) in
+ Array.of_list usages
+
+(**
+ * Latency constraints building
+ *)
+
+(*(* type access = { inst: int; loc: location } *)*)
+
+(*let preg2int pr = Camlcoq.P.to_int @@ Asmblockdeps.ppos pr*)
+
+(*let loc2int = function*)
+(*| Mem -> 1*)
+(*| Reg pr -> preg2int pr*)
+
+(*(* module HashedLoc = struct*)
+ (*type t = { loc: location; key: int }*)
+ (*let equal l1 l2 = (l1.key = l2.key)*)
+ (*let hash l = l.key*)
+ (*let create (l:location) : t = { loc=l; key = loc2int l }*)
+(*end *)*)
+
+(*(* module LocHash = Hashtbl.Make(HashedLoc) *)*)
+module LocHash = Hashtbl
+
+(*(* Hash table : location => list of instruction ids *)*)
+
+let rec intlist n =
+ if n < 0 then failwith "intlist: n < 0"
+ else if n = 0 then []
+ else (n - 1) :: intlist (n - 1)
+
+let find_in_hash hashloc loc =
+ match LocHash.find_opt hashloc loc with Some idl -> idl | None -> []
+
+(* Returns a list of instruction ids *)
+let rec get_accesses hashloc (ll : location list) =
+ match ll with
+ | [] -> []
+ | loc :: llocs -> find_in_hash hashloc loc @ get_accesses hashloc llocs
+
+let compute_latency (ifrom : inst_info) = ifrom.latency
+
+(*let dlat = inst_info_to_dlatency ito*)
+(*in let lat = ifrom.latency + dlat*)
+(*in assert (lat >= 0); if (lat == 0) then 1 else lat*)
+
+let latency_constraints bb =
+ let written = LocHash.create 70
+ and read = LocHash.create 70
+ and count = ref 0
+ and constraints = ref []
+ and instr_infos = instruction_infos bb in
+ let step (i : inst_info) =
+ let raw = get_accesses written i.read_locs
+ and waw = get_accesses written i.write_locs
+ and war = get_accesses read i.write_locs in
+ List.iter
+ (fun i ->
+ constraints :=
+ {
+ instr_from = i;
+ instr_to = !count;
+ latency = compute_latency (List.nth instr_infos i);
+ }
+ :: !constraints)
+ raw;
+ List.iter
+ (fun i ->
+ constraints :=
+ {
+ instr_from = i;
+ instr_to = !count;
+ latency = compute_latency (List.nth instr_infos i);
+ }
+ :: !constraints)
+ waw;
+ List.iter
+ (fun i ->
+ constraints :=
+ { instr_from = i; instr_to = !count; latency = 0 } :: !constraints)
+ war;
+ if i.is_control then
+ List.iter
+ (fun n ->
+ constraints :=
+ { instr_from = n; instr_to = !count; latency = 0 } :: !constraints)
+ (intlist !count);
+ (* Updating "read" and "written" hashmaps *)
+ List.iter
+ (fun loc ->
+ LocHash.replace written loc [ !count ];
+ LocHash.replace read loc []
+ (* Clearing all the entries of "read" hashmap when a register is written *))
+ i.write_locs;
+ List.iter
+ (fun loc -> LocHash.replace read loc (!count :: find_in_hash read loc))
+ i.read_locs;
+ count := !count + 1
+ in
+ List.iter step instr_infos;
+ !constraints
+
+(**
+ * Using the InstructionScheduler
+ *)
+
+(* TODO RESUME HERE *)
+
+let opweights = OpWeightsAsm.get_opweights ()
+
+let build_problem bb =
+ {
+ max_latency = -1;
+ resource_bounds = opweights.pipelined_resource_bounds;
+ instruction_usages = instruction_usages bb;
+ latency_constraints = latency_constraints bb;
+ }
+
+(*let rec find_min_opt (l: int option list) =*)
+(*match l with*)
+(*| [] -> None *)
+(*| e :: l ->*)
+(*begin match find_min_opt l with*)
+(*| None -> e*)
+(*| Some m ->*)
+(*begin match e with*)
+(*| None -> Some m*)
+(*| Some n -> if n < m then Some n else Some m*)
+(*end*)
+(*end*)
+
+(*let rec filter_indexes predicate = function*)
+(*| [] -> []*)
+(*| e :: l -> if (predicate e) then e :: (filter_indexes predicate l) else filter_indexes predicate l*)
+
+let get_from_indexes indexes l = List.map (List.nth l) indexes
+
+(*let is_basic = function PBasic _ -> true | _ -> false*)
+let is_control = function PControl _ -> true | _ -> false
+
+(*let to_basic = function*)
+(*| PBasic i -> i*)
+(*| _ -> failwith "to_basic: control instruction found"*)
+
+let to_control = function
+ | PControl i -> i
+ | _ -> failwith "to_control: basic instruction found"
+
+let rec body_to_instrs bdy =
+ match bdy with [] -> [] | i :: l' -> PBasic i :: body_to_instrs l'
+
+let rec instrs_to_bdy instrs =
+ match instrs with
+ | [] -> []
+ | PBasic i :: l' -> i :: instrs_to_bdy l'
+ | PControl _ :: l' -> failwith "instrs_to_bdy: control instruction found"
+
+let repack li hd =
+ let last = List.nth li (List.length li - 1) in
+ if is_control last then
+ let cut_li =
+ Array.to_list @@ Array.sub (Array.of_list li) 0 (List.length li - 1)
+ in
+ { header = hd; body = instrs_to_bdy cut_li; exit = Some (to_control last) }
+ else { header = hd; body = instrs_to_bdy li; exit = None }
+
+(*let extract_some o = match o with Some e -> e | None -> failwith "extract_some: None found"*)
+
+(*let rec find_min = function*)
+(*| [] -> None*)
+(*| e :: l ->*)
+(*match find_min l with*)
+(*| None -> Some e*)
+(*| Some m -> if (e < m) then Some e else Some m*)
+
+(*let rec remove_all m = function*)
+(*| [] -> []*)
+(*| e :: l -> if m=e then remove_all m l*)
+(*else e :: (remove_all m l)*)
+
+(*let rec find_mins l = match find_min l with*)
+(*| None -> []*)
+(*| Some m -> m :: find_mins (remove_all m l)*)
+
+(*let find_all_indices m l = *)
+(*let rec find m off = function*)
+(*| [] -> []*)
+(*| e :: l -> if m=e then off :: find m (off+1) l*)
+(*else find m (off+1) l*)
+(*in find m 0 l*)
+
+module TimeHash = Hashtbl
+
+(*Hash table : time => list of instruction ids *)
+
+let hashtbl2flatarray h maxint =
+ let rec f i =
+ match TimeHash.find_opt h i with
+ | None -> if i > maxint then [] else f (i + 1)
+ | Some bund -> bund @ f (i + 1)
+ in
+ f 0
+
+let find_max l =
+ let rec f = function
+ | [] -> None
+ | e :: l -> (
+ match f l with
+ | None -> Some e
+ | Some m -> if e > m then Some e else Some m )
+ in
+ match f l with None -> raise Not_found | Some m -> m
+
+(*(* [0, 2, 3, 1, 1, 2, 4, 5] -> [[0], [3, 4], [1, 5], [2], [6], [7]] *)*)
+let minpack_list (l : int list) =
+ let timehash = TimeHash.create (List.length l) in
+ let rec f i = function
+ | [] -> ()
+ | t :: l ->
+ ( match TimeHash.find_opt timehash t with
+ | None -> TimeHash.add timehash t [ i ]
+ | Some bund -> TimeHash.replace timehash t (bund @ [ i ]) );
+ f (i + 1) l
+ in
+ f 0 l;
+ hashtbl2flatarray timehash (find_max l)
+
+(*let minpack_list l =*)
+(*let mins = find_mins l*)
+(*in List.map (fun m -> find_all_indices m l) mins*)
+
+let bb_to_instrs bb =
+ body_to_instrs bb.body
+ @ match bb.exit with None -> [] | Some e -> [ PControl e ]
+
+let build_solution bb sol =
+ (* Remove last element - the total *)
+ let tmp = Array.to_list @@ Array.sub sol 0 (Array.length sol - 1) in
+ let pack = minpack_list tmp and instrs = bb_to_instrs bb in
+ repack (get_from_indexes pack instrs) bb.header
+
+(*in let rec bund hd = function*)
+(*| [] -> []*)
+(*| pack :: packs -> repack (get_from_indexes pack instrs) hd :: (bund [] packs)*)
+(*in bund bb.header packs*)
+
+(*let print_inst oc = function i -> TargetPrinter.Target.print_instructions oc i*)
+(*| Asm.Pallocframe(sz, ofs) -> Printf.fprintf oc " Pallocframe\n"*)
+(*| Asm.Pfreeframe(sz, ofs) -> Printf.fprintf oc " Pfreeframe\n"*)
+(*| Asm.Pbuiltin(ef, args, res) -> Printf.fprintf oc " Pbuiltin\n"*)
+
+(*let print_bb oc bb =*)
+(*match Asmgen.Asmblock_TRANSF.unfold_bblock bb with*)
+(*| Errors.OK instructions -> List.iter (print_inst oc) instructions*)
+(*| Errors.Error _ -> Printf.eprintf "Error in print_bb"*)
+
+let print_schedule sched =
+ print_string "[ ";
+ Array.iter (fun x -> Printf.printf "%d; " x) sched;
+ print_endline "]"
+
+let do_schedule bb =
+ let problem = build_problem bb in
+ if debug then print_problem stdout problem;
+ let solution = scheduler_by_name !Clflags.option_fpostpass_sched problem in
+ match solution with
+ | None -> failwith "Could not find a valid schedule"
+ | Some sol ->
+ if debug then print_schedule sol;
+ build_solution bb sol
+
+(**
+ * Dumb schedule if the above doesn't work
+ *)
+
+(* Pack result *)
+let pack_result (bb : bblock) = (bb.body, bb.exit)
+
+(**
+ * Separates the opaque instructions such as Pfreeframe and Pallocframe
+ *)
+
+(*let is_opaque = function*)
+(*| Pallocframe _ | Pfreeframe _ -> true*)
+(*| _ -> false*)
+
+(*(* Returns : (accumulated instructions, remaining instructions, opaque instruction if found) *)*)
+(*let rec biggest_wo_opaque = function
+ | [] -> ([], [], None)
+ | i :: li -> if is_opaque i then ([], li, Some i)
+ else let big, rem, opaque = biggest_wo_opaque li in (i :: big, rem, opaque);;
+
+let separate_opaque bb =
+ let instrs = bb_to_instrs bb
+ in let rec f hd li =
+ match li with
+ | [] -> []
+ | li -> let big, rem, opaque = biggest_wo_opaque li in
+ match opaque with
+ | Some i ->
+ (match big with
+ | [] -> (repack [i] hd) :: (f [] rem)
+ | big -> (repack big hd) :: (bundlize [i] []) :: (f [] rem)
+ )
+ | None -> (bundlize big hd) :: (f [] rem)
+ in f bb.header instrs*)
+
+let smart_schedule bb =
+ let bb' =
+ try do_schedule bb with
+ | OpaqueInstruction ->
+ if debug then
+ Printf.eprintf "OpaqueInstruction raised, using identity scheduling\n";
+ bb (* Identity in case of failure *)
+ | e ->
+ let msg = Printexc.to_string e and stack = Printexc.get_backtrace () in
+ Printf.eprintf "Postpass scheduling could not complete: %s\n%s" msg
+ stack;
+ failwith "Invalid schedule"
+ in
+ pack_result bb'
+
+let bblock_schedule bb =
+ let identity_mode = not !Clflags.option_fpostpass in
+ if debug && not identity_mode then (
+ Printf.eprintf "###############################\n";
+ Printf.eprintf "SCHEDULING\n" );
+ if identity_mode then pack_result bb else smart_schedule bb
+
+(** Called schedule function from Coq *)
+
+(*let schedule_notime bb = let toto = bblock_schedule in toto*)
+let schedule bb =
+ Timing.time_coq
+ [
+ 'P';
+ 'o';
+ 's';
+ 't';
+ 'p';
+ 'a';
+ 's';
+ 's';
+ 'S';
+ 'c';
+ 'h';
+ 'e';
+ 'd';
+ 'u';
+ 'l';
+ 'i';
+ 'n';
+ 'g';
+ ' ';
+ 'o';
+ 'r';
+ 'a';
+ 'c';
+ 'l';
+ 'e';
+ ]
+ bblock_schedule bb
diff --git a/aarch64/PostpassSchedulingproof.v b/aarch64/PostpassSchedulingproof.v
new file mode 100644
index 00000000..86a160bd
--- /dev/null
+++ b/aarch64/PostpassSchedulingproof.v
@@ -0,0 +1,690 @@
+(* *************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Sylvain Boulmé Grenoble-INP, VERIMAG *)
+(* David Monniaux CNRS, VERIMAG *)
+(* Cyril Six Kalray *)
+(* *)
+(* Copyright Kalray. Copyright VERIMAG. All rights reserved. *)
+(* This file is distributed under the terms of the INRIA *)
+(* Non-Commercial License Agreement. *)
+(* *)
+(* *************************************************************)
+
+Require Import Coqlib Errors.
+Require Import Integers Floats AST Linking.
+Require Import Values Memory Events Globalenvs Smallstep.
+Require Import Op Locations Machblock Conventions Asmblock.
+Require Import Asmblockgenproof0 Asmblockprops.
+Require Import PostpassScheduling.
+Require Import Asmblockgenproof.
+Require Import Axioms.
+
+Local Open Scope error_monad_scope.
+
+Definition match_prog (p tp: Asmblock.program) :=
+ match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
+
+Lemma transf_program_match:
+ forall p tp, transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros. eapply match_transform_partial_program; eauto.
+Qed.
+
+(*
+Lemma regset_double_set_id:
+ forall r (rs: regset) v1 v2,
+ (rs # r <- v1 # r <- v2) = (rs # r <- v2).
+Proof.
+ intros. apply functional_extensionality. intros. destruct (preg_eq r x).
+ - subst r. repeat (rewrite Pregmap.gss; auto).
+ - repeat (rewrite Pregmap.gso); auto.
+Qed.
+
+Lemma exec_body_pc_var:
+ forall l ge rs m rs' m' v,
+ exec_body ge l rs m = Next rs' m' ->
+ exec_body ge l (rs # PC <- v) m = Next (rs' # PC <- v) m'.
+Proof.
+ induction l.
+ - intros. simpl. simpl in H. inv H. auto.
+ - intros. simpl in *.
+ destruct (exec_basic_instr ge a rs m) eqn:EXEBI; try discriminate.
+ erewrite exec_basic_instr_pc_var; eauto.
+Qed.
+
+Lemma pc_set_add:
+ forall rs v r x y,
+ 0 <= x <= Ptrofs.max_unsigned ->
+ 0 <= y <= Ptrofs.max_unsigned ->
+ rs # r <- (Val.offset_ptr v (Ptrofs.repr (x + y))) = rs # r <- (Val.offset_ptr (rs # r <- (Val.offset_ptr v (Ptrofs.repr x)) r) (Ptrofs.repr y)).
+Proof.
+ intros. apply functional_extensionality. intros r0. destruct (preg_eq r r0).
+ - subst. repeat (rewrite Pregmap.gss); auto.
+ destruct v; simpl; auto.
+ rewrite Ptrofs.add_assoc.
+ enough (Ptrofs.repr (x + y) = Ptrofs.add (Ptrofs.repr x) (Ptrofs.repr y)) as ->; auto.
+ unfold Ptrofs.add.
+ enough (x + y = Ptrofs.unsigned (Ptrofs.repr x) + Ptrofs.unsigned (Ptrofs.repr y)) as ->; auto.
+ repeat (rewrite Ptrofs.unsigned_repr); auto.
+ - repeat (rewrite Pregmap.gso; auto).
+Qed.
+
+Lemma concat2_straight:
+ forall a b bb rs m rs'' m'' f ge,
+ concat2 a b = OK bb ->
+ exec_bblock ge f bb rs m = Next rs'' m'' ->
+ exists rs' m',
+ exec_bblock ge f a rs m = Next rs' m'
+ /\ rs' PC = Val.offset_ptr (rs PC) (Ptrofs.repr (size a))
+ /\ exec_bblock ge f b rs' m' = Next rs'' m''.
+Proof.
+ intros until ge. intros CONC2 EXEB.
+ exploit concat2_zlt_size; eauto. intros (LTA & LTB).
+ exploit concat2_noexit; eauto. intros EXA.
+ exploit concat2_decomp; eauto. intros. inv H.
+ unfold exec_bblock in EXEB. destruct (exec_body ge (body bb) rs m) eqn:EXEB'; try discriminate.
+ rewrite H0 in EXEB'. apply exec_body_app in EXEB'. destruct EXEB' as (rs1 & m1 & EXEB1 & EXEB2).
+ eexists; eexists. split.
+ unfold exec_bblock. rewrite EXEB1. rewrite EXA. simpl. eauto.
+ split.
+ exploit exec_body_pc. eapply EXEB1. intros. rewrite <- H. auto.
+ unfold exec_bblock. unfold nextblock, incrPC. rewrite regset_same_assign. erewrite exec_body_pc_var; eauto.
+ rewrite <- H1. unfold nextblock in EXEB. rewrite regset_double_set_id.
+ assert (size bb = size a + size b).
+ { unfold size. rewrite H0. rewrite H1. rewrite app_length. rewrite EXA. simpl. rewrite Nat.add_0_r.
+ repeat (rewrite Nat2Z.inj_add). omega. }
+ clear EXA H0 H1. rewrite H in EXEB.
+ assert (rs1 PC = rs0 PC). { apply exec_body_pc in EXEB2. auto. }
+ rewrite H0. rewrite <- pc_set_add; auto.
+ exploit size_positive. instantiate (1 := a). intro. omega.
+ exploit size_positive. instantiate (1 := b). intro. omega.
+Qed.
+
+Lemma concat_all_exec_bblock (ge: Genv.t fundef unit) (f: function) :
+ forall a bb rs m lbb rs'' m'',
+ lbb <> nil ->
+ concat_all (a :: lbb) = OK bb ->
+ exec_bblock ge f bb rs m = Next rs'' m'' ->
+ exists bb' rs' m',
+ concat_all lbb = OK bb'
+ /\ exec_bblock ge f a rs m = Next rs' m'
+ /\ rs' PC = Val.offset_ptr (rs PC) (Ptrofs.repr (size a))
+ /\ exec_bblock ge f bb' rs' m' = Next rs'' m''.
+Proof.
+ intros until m''. intros Hnonil CONC EXEB.
+ simpl in CONC.
+ destruct lbb as [|b lbb]; try contradiction. clear Hnonil.
+ monadInv CONC. exploit concat2_straight; eauto. intros (rs' & m' & EXEB1 & PCeq & EXEB2).
+ exists x. repeat econstructor. all: eauto.
+Qed.
+
+Lemma ptrofs_add_repr :
+ forall a b,
+ Ptrofs.unsigned (Ptrofs.add (Ptrofs.repr a) (Ptrofs.repr b)) = Ptrofs.unsigned (Ptrofs.repr (a + b)).
+Proof.
+ intros a b.
+ rewrite Ptrofs.add_unsigned. repeat (rewrite Ptrofs.unsigned_repr_eq).
+ rewrite <- Zplus_mod. auto.
+Qed.
+
+Section PRESERVATION_ASMBLOCK.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma transf_function_no_overflow:
+ forall f tf,
+ transf_function f = OK tf -> size_blocks tf.(fn_blocks) <= Ptrofs.max_unsigned.
+Proof.
+ intros. monadInv H. destruct (zlt Ptrofs.max_unsigned (size_blocks x.(fn_blocks))); inv EQ0.
+ omega.
+Qed.
+
+Lemma symbols_preserved:
+ forall id,
+ Genv.find_symbol tge id = Genv.find_symbol ge id.
+Proof (Genv.find_symbol_match TRANSL).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_match TRANSL).
+
+Lemma functions_translated:
+ forall v f,
+ Genv.find_funct ge v = Some f ->
+ exists tf,
+ Genv.find_funct tge v = Some tf /\ transf_fundef f = OK tf.
+Proof (Genv.find_funct_transf_partial TRANSL).
+
+Lemma function_ptr_translated:
+ forall v f,
+ Genv.find_funct_ptr ge v = Some f ->
+ exists tf,
+ Genv.find_funct_ptr tge v = Some tf /\ transf_fundef f = OK tf.
+Proof (Genv.find_funct_ptr_transf_partial TRANSL).
+
+Lemma functions_transl:
+ forall fb f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ Genv.find_funct_ptr tge fb = Some (Internal tf).
+Proof.
+ intros. exploit function_ptr_translated; eauto.
+ intros (tf' & A & B). monadInv B. rewrite H0 in EQ. inv EQ. auto.
+Qed.
+
+Inductive match_states: state -> state -> Prop :=
+ | match_states_intro:
+ forall s1 s2, s1 = s2 -> match_states s1 s2.
+
+Lemma prog_main_preserved:
+ prog_main tprog = prog_main prog.
+Proof (match_program_main TRANSL).
+
+Lemma prog_main_address_preserved:
+ (Genv.symbol_address (Genv.globalenv prog) (prog_main prog) Ptrofs.zero) =
+ (Genv.symbol_address (Genv.globalenv tprog) (prog_main tprog) Ptrofs.zero).
+Proof.
+ unfold Genv.symbol_address. rewrite symbols_preserved.
+ rewrite prog_main_preserved. auto.
+Qed.
+
+Lemma transf_initial_states:
+ forall st1, initial_state prog st1 ->
+ exists st2, initial_state tprog st2 /\ match_states st1 st2.
+Proof.
+ intros. inv H.
+ econstructor; split.
+ - eapply initial_state_intro.
+ eapply (Genv.init_mem_transf_partial TRANSL); eauto.
+ - econstructor; eauto. subst ge0. subst rs0. rewrite prog_main_address_preserved. auto.
+Qed.
+
+Lemma transf_final_states:
+ forall st1 st2 r,
+ match_states st1 st2 -> final_state st1 r -> final_state st2 r.
+Proof.
+ intros. inv H0. inv H. econstructor; eauto.
+Qed.
+
+Lemma tail_find_bblock:
+ forall lbb pos bb,
+ find_bblock pos lbb = Some bb ->
+ exists c, code_tail pos lbb (bb::c).
+Proof.
+ induction lbb.
+ - intros. simpl in H. inv H.
+ - intros. simpl in H.
+ destruct (zlt pos 0); try (inv H; fail).
+ destruct (zeq pos 0).
+ + inv H. exists lbb. constructor; auto.
+ + apply IHlbb in H. destruct H as (c & TAIL). exists c.
+ enough (pos = pos - size a + size a) as ->.
+ apply code_tail_S; auto.
+ omega.
+Qed.
+
+Lemma code_tail_head_app:
+ forall l pos c1 c2,
+ code_tail pos c1 c2 ->
+ code_tail (pos + size_blocks l) (l++c1) c2.
+Proof.
+ induction l.
+ - intros. simpl. rewrite Z.add_0_r. auto.
+ - intros. apply IHl in H. simpl. rewrite (Z.add_comm (size a)). rewrite Z.add_assoc. apply code_tail_S. assumption.
+Qed.
+
+Lemma transf_blocks_verified:
+ forall c tc pos bb c',
+ transf_blocks c = OK tc ->
+ code_tail pos c (bb::c') ->
+ exists lbb,
+ verified_schedule bb = OK lbb
+ /\ exists tc', code_tail pos tc (lbb ++ tc').
+Proof.
+ induction c; intros.
+ - simpl in H. inv H. inv H0.
+ - inv H0.
+ + monadInv H. exists x0.
+ split; simpl; auto. eexists; eauto. econstructor; eauto.
+ + unfold transf_blocks in H. fold transf_blocks in H. monadInv H.
+ exploit IHc; eauto.
+ intros (lbb & TRANS & tc' & TAIL).
+(* monadInv TRANS. *)
+ repeat eexists; eauto.
+ erewrite verified_schedule_size; eauto.
+ apply code_tail_head_app.
+ eauto.
+Qed.
+
+Lemma transf_find_bblock:
+ forall ofs f bb tf,
+ find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bb ->
+ transf_function f = OK tf ->
+ exists lbb,
+ verified_schedule bb = OK lbb
+ /\ exists c, code_tail (Ptrofs.unsigned ofs) (fn_blocks tf) (lbb ++ c).
+Proof.
+ intros.
+ monadInv H0. destruct (zlt Ptrofs.max_unsigned (size_blocks (fn_blocks x))); try (inv EQ0; fail). inv EQ0.
+ monadInv EQ. apply tail_find_bblock in H. destruct H as (c & TAIL).
+ eapply transf_blocks_verified; eauto.
+Qed.
+
+Lemma symbol_address_preserved:
+ forall l ofs, Genv.symbol_address ge l ofs = Genv.symbol_address tge l ofs.
+Proof.
+ intros. unfold Genv.symbol_address. repeat (rewrite symbols_preserved). reflexivity.
+Qed.
+
+Lemma head_tail {A: Type}:
+ forall (l: list A) hd, hd::l = hd :: (tail (hd::l)).
+Proof.
+ intros. simpl. auto.
+Qed.
+
+Lemma verified_schedule_not_empty:
+ forall bb lbb,
+ verified_schedule bb = OK lbb -> lbb <> nil.
+Proof.
+ intros. apply verified_schedule_size in H.
+ pose (size_positive bb). assert (size_blocks lbb > 0) by omega. clear H g.
+ destruct lbb; simpl in *; discriminate.
+Qed.
+
+Lemma header_nil_label_pos_none:
+ forall lbb l p,
+ Forall (fun b => header b = nil) lbb -> label_pos l p lbb = None.
+Proof.
+ induction lbb.
+ - intros. simpl. auto.
+ - intros. inv H. simpl. unfold is_label. rewrite H2. destruct (in_dec l nil). { inv i. }
+ auto.
+Qed.
+
+Lemma verified_schedule_label:
+ forall bb tbb lbb l,
+ verified_schedule bb = OK (tbb :: lbb) ->
+ is_label l bb = is_label l tbb
+ /\ label_pos l 0 lbb = None.
+Proof.
+ intros. exploit verified_schedule_header; eauto.
+ intros (HdrEq & HdrNil).
+ split.
+ - unfold is_label. rewrite HdrEq. reflexivity.
+ - apply header_nil_label_pos_none. assumption.
+Qed.
+
+Lemma label_pos_app_none:
+ forall c c' l p p',
+ label_pos l p c = None ->
+ label_pos l (p' + size_blocks c) c' = label_pos l p' (c ++ c').
+Proof.
+ induction c.
+ - intros. simpl in *. rewrite Z.add_0_r. reflexivity.
+ - intros. simpl in *. destruct (is_label _ _) eqn:ISLABEL.
+ + discriminate.
+ + eapply IHc in H. rewrite Z.add_assoc. eauto.
+Qed.
+
+Remark label_pos_pvar_none_add:
+ forall tc l p p' k,
+ label_pos l (p+k) tc = None -> label_pos l (p'+k) tc = None.
+Proof.
+ induction tc.
+ - intros. simpl. auto.
+ - intros. simpl in *. destruct (is_label _ _) eqn:ISLBL.
+ + discriminate.
+ + pose (IHtc l p p' (k + size a)). repeat (rewrite Z.add_assoc in e). auto.
+Qed.
+
+Lemma label_pos_pvar_none:
+ forall tc l p p',
+ label_pos l p tc = None -> label_pos l p' tc = None.
+Proof.
+ intros. rewrite (Zplus_0_r_reverse p') at 1. rewrite (Zplus_0_r_reverse p) in H at 1.
+ eapply label_pos_pvar_none_add; eauto.
+Qed.
+
+Remark label_pos_pvar_some_add_add:
+ forall tc l p p' k k',
+ label_pos l (p+k') tc = Some (p+k) -> label_pos l (p'+k') tc = Some (p'+k).
+Proof.
+ induction tc.
+ - intros. simpl in H. discriminate.
+ - intros. simpl in *. destruct (is_label _ _) eqn:ISLBL.
+ + inv H. assert (k = k') by omega. subst. reflexivity.
+ + pose (IHtc l p p' k (k' + size a)). repeat (rewrite Z.add_assoc in e). auto.
+Qed.
+
+Lemma label_pos_pvar_some_add:
+ forall tc l p p' k,
+ label_pos l p tc = Some (p+k) -> label_pos l p' tc = Some (p'+k).
+Proof.
+ intros. rewrite (Zplus_0_r_reverse p') at 1. rewrite (Zplus_0_r_reverse p) in H at 1.
+ eapply label_pos_pvar_some_add_add; eauto.
+Qed.
+
+Remark label_pos_pvar_add:
+ forall c tc l p p' k,
+ label_pos l (p+k) c = label_pos l p tc ->
+ label_pos l (p'+k) c = label_pos l p' tc.
+Proof.
+ induction c.
+ - intros. simpl in *.
+ exploit label_pos_pvar_none; eauto.
+ - intros. simpl in *. destruct (is_label _ _) eqn:ISLBL.
+ + exploit label_pos_pvar_some_add; eauto.
+ + pose (IHc tc l p p' (k+size a)). repeat (rewrite Z.add_assoc in e). auto.
+Qed.
+
+Lemma label_pos_pvar:
+ forall c tc l p p',
+ label_pos l p c = label_pos l p tc ->
+ label_pos l p' c = label_pos l p' tc.
+Proof.
+ intros. rewrite (Zplus_0_r_reverse p') at 1. rewrite (Zplus_0_r_reverse p) in H at 1.
+ eapply label_pos_pvar_add; eauto.
+Qed.
+
+Lemma label_pos_head_app:
+ forall c bb lbb l tc p,
+ verified_schedule bb = OK lbb ->
+ label_pos l p c = label_pos l p tc ->
+ label_pos l p (bb :: c) = label_pos l p (lbb ++ tc).
+Proof.
+ intros. simpl. destruct lbb as [|tbb lbb].
+ - apply verified_schedule_not_empty in H. contradiction.
+ - simpl. exploit verified_schedule_label; eauto. intros (ISLBL & LBLPOS).
+ rewrite ISLBL.
+ destruct (is_label l tbb) eqn:ISLBL'; simpl; auto.
+ eapply label_pos_pvar in H0. erewrite H0.
+ erewrite verified_schedule_size; eauto. simpl size_blocks. rewrite Z.add_assoc.
+ erewrite label_pos_app_none; eauto.
+Qed.
+
+Lemma label_pos_preserved:
+ forall c tc l,
+ transf_blocks c = OK tc -> label_pos l 0 c = label_pos l 0 tc.
+Proof.
+ induction c.
+ - intros. simpl in *. inv H. reflexivity.
+ - intros. unfold transf_blocks in H; fold transf_blocks in H. monadInv H. eapply IHc in EQ.
+ eapply label_pos_head_app; eauto.
+Qed.
+
+Lemma label_pos_preserved_blocks:
+ forall l f tf,
+ transf_function f = OK tf ->
+ label_pos l 0 (fn_blocks f) = label_pos l 0 (fn_blocks tf).
+Proof.
+ intros. monadInv H. monadInv EQ.
+ destruct (zlt Ptrofs.max_unsigned _); try discriminate.
+ monadInv EQ0. simpl. eapply label_pos_preserved; eauto.
+Qed.
+
+Lemma transf_exec_control:
+ forall f tf ex rs m,
+ transf_function f = OK tf ->
+ exec_control ge f ex rs m = exec_control tge tf ex rs m.
+Proof.
+ intros. destruct ex; simpl; auto.
+ assert (ge = Genv.globalenv prog). auto.
+ assert (tge = Genv.globalenv tprog). auto.
+ pose symbol_address_preserved.
+ exploreInst; simpl; auto; try congruence;
+ unfold par_goto_label; unfold par_eval_branch; unfold par_goto_label; erewrite label_pos_preserved_blocks; eauto.
+Qed.
+
+Lemma transf_exec_basic_instr:
+ forall i rs m, exec_basic_instr ge i rs m = exec_basic_instr tge i rs m.
+Proof.
+ intros. pose symbol_address_preserved.
+ unfold exec_basic_instr. unfold bstep. exploreInst; simpl; auto; try congruence.
+ unfold parexec_arith_instr; unfold arith_eval_r; exploreInst; simpl; auto; try congruence.
+Qed.
+
+Lemma transf_exec_body:
+ forall bdy rs m, exec_body ge bdy rs m = exec_body tge bdy rs m.
+Proof.
+ induction bdy; intros.
+ - simpl. reflexivity.
+ - simpl. rewrite transf_exec_basic_instr.
+ destruct (exec_basic_instr _ _ _); auto.
+Qed.
+
+Lemma transf_exec_bblock:
+ forall f tf bb rs m,
+ transf_function f = OK tf ->
+ exec_bblock ge f bb rs m = exec_bblock tge tf bb rs m.
+Proof.
+ intros. unfold exec_bblock. rewrite transf_exec_body. destruct (exec_body _ _ _ _); auto.
+ eapply transf_exec_control; eauto.
+Qed.
+
+Lemma transf_step_simu:
+ forall tf b lbb ofs c tbb rs m rs' m',
+ Genv.find_funct_ptr tge b = Some (Internal tf) ->
+ size_blocks (fn_blocks tf) <= Ptrofs.max_unsigned ->
+ rs PC = Vptr b ofs ->
+ code_tail (Ptrofs.unsigned ofs) (fn_blocks tf) (lbb ++ c) ->
+ concat_all lbb = OK tbb ->
+ exec_bblock tge tf tbb rs m = Next rs' m' ->
+ plus step tge (State rs m) E0 (State rs' m').
+Proof.
+ induction lbb.
+ - intros until m'. simpl. intros. discriminate.
+ - intros until m'. intros GFIND SIZE PCeq TAIL CONC EXEB.
+ destruct lbb.
+ + simpl in *. clear IHlbb. inv CONC. eapply plus_one. econstructor; eauto. eapply find_bblock_tail; eauto.
+ + exploit concat_all_exec_bblock; eauto; try discriminate.
+ intros (tbb0 & rs0 & m0 & CONC0 & EXEB0 & PCeq' & EXEB1).
+ eapply plus_left.
+ econstructor.
+ 3: eapply find_bblock_tail. rewrite <- app_comm_cons in TAIL. 3: eauto.
+ all: eauto.
+ eapply plus_star. eapply IHlbb; eauto. rewrite PCeq in PCeq'. simpl in PCeq'. all: eauto.
+ eapply code_tail_next_int; eauto.
+Qed.
+
+Theorem transf_step_correct:
+ forall s1 t s2, step ge s1 t s2 ->
+ forall s1' (MS: match_states s1 s1'),
+ (exists s2', plus step tge s1' t s2' /\ match_states s2 s2').
+Proof.
+ induction 1; intros; inv MS.
+ - exploit function_ptr_translated; eauto. intros (tf & FFP & TRANSF). monadInv TRANSF.
+ exploit transf_find_bblock; eauto. intros (lbb & VES & c & TAIL).
+ exploit verified_schedule_correct; eauto. intros (tbb & CONC & BBEQ). inv CONC. rename H3 into CONC.
+ assert (NOOV: size_blocks x.(fn_blocks) <= Ptrofs.max_unsigned).
+ eapply transf_function_no_overflow; eauto.
+
+ erewrite transf_exec_bblock in H2; eauto.
+ unfold bblock_simu in BBEQ. rewrite BBEQ in H2; try congruence.
+ exists (State rs' m'). split; try (constructor; auto).
+ eapply transf_step_simu; eauto.
+
+ - exploit function_ptr_translated; eauto. intros (tf & FFP & TRANSF). monadInv TRANSF.
+ exploit transf_find_bblock; eauto. intros (lbb & VES & c & TAIL).
+ exploit verified_schedule_builtin_idem; eauto. intros. subst lbb.
+
+ remember (State (nextblock _ _) _) as s'. exists s'.
+ split; try constructor; auto.
+ eapply plus_one. subst s'.
+ eapply exec_step_builtin.
+ 3: eapply find_bblock_tail. simpl in TAIL. 3: eauto.
+ all: eauto.
+ eapply eval_builtin_args_preserved with (ge1 := ge). exact symbols_preserved. eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+
+ - exploit function_ptr_translated; eauto. intros (tf & FFP & TRANSF). monadInv TRANSF.
+ remember (State _ m') as s'. exists s'. split; try constructor; auto.
+ subst s'. eapply plus_one. eapply exec_step_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+Qed.
+
+Theorem transf_program_correct_Asmblock:
+ forward_simulation (Asmblock.semantics prog) (Asmblock.semantics tprog).
+Proof.
+ eapply forward_simulation_plus.
+ - apply senv_preserved.
+ - apply transf_initial_states.
+ - apply transf_final_states.
+ - apply transf_step_correct.
+Qed.
+
+End PRESERVATION_ASMBLOCK.
+
+Require Import Asmvliw.
+
+Lemma verified_par_checks_alls_bundles lb x: forall bundle,
+ verify_par lb = OK x ->
+ List.In bundle lb -> verify_par_bblock bundle = OK tt.
+Proof.
+ induction lb; simpl; try tauto.
+ intros bundle H; monadInv H.
+ destruct 1; subst; eauto.
+ destruct x0; auto.
+Qed.
+
+Lemma verified_schedule_nob_checks_alls_bundles bb lb bundle:
+ verified_schedule_nob bb = OK lb ->
+ List.In bundle lb -> verify_par_bblock bundle = OK tt.
+Proof.
+ unfold verified_schedule_nob. intros H;
+ monadInv H. destruct x4.
+ intros; eapply verified_par_checks_alls_bundles; eauto.
+Qed.
+
+Lemma verify_par_bblock_PExpand bb i:
+ exit bb = Some (PExpand i) -> verify_par_bblock bb = OK tt.
+Proof.
+ destruct bb as [h bdy ext H]; simpl.
+ intros; subst. destruct i.
+ generalize H.
+ rewrite <- wf_bblock_refl in H.
+ destruct H as [H H0].
+ unfold builtin_alone in H0. erewrite H0; eauto.
+Qed.
+
+Local Hint Resolve verified_schedule_nob_checks_alls_bundles: core.
+
+Lemma verified_schedule_checks_alls_bundles bb lb bundle:
+ verified_schedule bb = OK lb ->
+ List.In bundle lb -> verify_par_bblock bundle = OK tt.
+Proof.
+ unfold verified_schedule. remember (exit bb) as exb.
+ destruct exb as [c|]; eauto.
+ destruct c as [i|]; eauto.
+ destruct i; intros H. inversion_clear H; simpl.
+ intuition subst.
+ intros; eapply verify_par_bblock_PExpand; eauto.
+Qed.
+
+Lemma transf_blocks_checks_all_bundles lbb: forall lb bundle,
+ transf_blocks lbb = OK lb ->
+ List.In bundle lb -> verify_par_bblock bundle = OK tt.
+Proof.
+ induction lbb; simpl.
+ - intros lb bundle H; inversion_clear H. simpl; try tauto.
+ - intros lb bundle H0.
+ monadInv H0.
+ rewrite in_app. destruct 1; eauto.
+ eapply verified_schedule_checks_alls_bundles; eauto.
+Qed.
+
+Lemma find_bblock_Some_in lb:
+ forall ofs b, find_bblock ofs lb = Some b -> List.In b lb.
+Proof.
+ induction lb; simpl; try congruence.
+ intros ofs b.
+ destruct (zlt ofs 0); try congruence.
+ destruct (zeq ofs 0); eauto.
+ intros X; inversion X; eauto.
+Qed.
+
+Section PRESERVATION_ASMVLIW.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Lemma all_bundles_are_checked b ofs f bundle:
+ Genv.find_funct_ptr (globalenv (Asmblock.semantics tprog)) b = Some (Internal f) ->
+ find_bblock ofs (fn_blocks f) = Some bundle ->
+ verify_par_bblock bundle = OK tt.
+Proof.
+ unfold match_prog, match_program in TRANSL.
+ unfold Genv.find_funct_ptr; simpl; intros X.
+ destruct (Genv.find_def_match_2 TRANSL b) as [|f0 y H]; try congruence.
+ destruct y as [tf0|]; try congruence.
+ inversion X as [H1]. subst. clear X.
+ remember (@Gfun fundef unit (Internal f)) as f2.
+ destruct H as [ctx' f1 f2 H0|]; try congruence.
+ inversion Heqf2 as [H2]. subst; clear Heqf2.
+ unfold transf_fundef, transf_partial_fundef in H.
+ destruct f1 as [f1|f1]; try congruence.
+ unfold transf_function, transl_function in H.
+ monadInv H. monadInv EQ.
+ destruct (zlt Ptrofs.max_unsigned (size_blocks (fn_blocks _))); simpl in *|-; try congruence.
+ injection EQ1; intros; subst.
+ monadInv EQ0. simpl in * |-.
+ intros; exploit transf_blocks_checks_all_bundles; eauto.
+ intros; eapply find_bblock_Some_in; eauto.
+Qed.
+
+Lemma checked_bundles_are_parexec_equiv f bundle rs rs' m m':
+ exec_bblock (globalenv (Asmblock.semantics tprog)) f bundle rs m = Next rs' m' ->
+ verify_par_bblock bundle = OK tt ->
+ det_parexec (globalenv (semantics tprog)) f bundle rs m rs' m'.
+Proof.
+ intros. unfold verify_par_bblock in H0. destruct (Asmblockdeps.bblock_para_check _) eqn:BPC; try discriminate. clear H0.
+ simpl in H.
+ eapply Asmblockdeps.bblock_para_check_correct; eauto.
+Qed.
+
+Lemma seqexec_parexec_equiv b ofs f bundle rs rs' m m':
+ Genv.find_funct_ptr (globalenv (Asmblock.semantics tprog)) b = Some (Internal f) ->
+ find_bblock (Ptrofs.unsigned ofs) (fn_blocks f) = Some bundle ->
+ exec_bblock (globalenv (Asmblock.semantics tprog)) f bundle rs m = Next rs' m' ->
+ det_parexec (globalenv (semantics tprog)) f bundle rs m rs' m'.
+Proof.
+ intros; eapply checked_bundles_are_parexec_equiv; eauto.
+ eapply all_bundles_are_checked; eauto.
+Qed.
+
+Theorem transf_program_correct_Asmvliw:
+ forward_simulation (Asmblock.semantics tprog) (Asmvliw.semantics tprog).
+Proof.
+ eapply forward_simulation_step with (match_states:=fun (s1:Asmvliw.state) s2 => s1=s2); eauto.
+ - intros; subst; auto.
+ - intros s1 t s1' H s2 H0; subst; inversion H; clear H; subst; eexists; split; eauto.
+ + eapply exec_step_internal; eauto.
+ intros; eapply seqexec_parexec_equiv; eauto.
+ + eapply exec_step_builtin; eauto.
+ + eapply exec_step_external; eauto.
+Qed.
+
+End PRESERVATION_ASMVLIW.
+
+Section PRESERVATION.
+
+Variables prog tprog: program.
+Hypothesis TRANSL: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Theorem transf_program_correct:
+ forward_simulation (Asmblock.semantics prog) (Asmvliw.semantics tprog).
+Proof.
+ eapply compose_forward_simulations.
+ eapply transf_program_correct_Asmblock; eauto.
+ eapply transf_program_correct_Asmvliw; eauto.
+Qed.
+
+End PRESERVATION.*)
diff --git a/aarch64/TargetPrinter.ml b/aarch64/TargetPrinter.ml
index 8d74daf4..324bd727 100644
--- a/aarch64/TargetPrinter.ml
+++ b/aarch64/TargetPrinter.ml
@@ -38,7 +38,7 @@ let is_immediate_float32 bits =
(* Module containing the printing functions *)
-module Target : TARGET =
+module Target (*: TARGET*) =
struct
(* Basic printing functions *)
@@ -120,13 +120,13 @@ module Target : TARGET =
output_string oc (match sz with D -> dreg_name r | S -> sreg_name r)
let preg_asm oc ty = function
- | IR r -> if ty = Tint then wreg oc r else xreg oc r
- | FR r -> if ty = Tsingle then sreg oc r else dreg oc r
+ | DR (IR (RR1 r)) -> if ty = Tint then wreg oc r else xreg oc r
+ | DR (FR r) -> if ty = Tsingle then sreg oc r else dreg oc r
| _ -> assert false
let preg_annot = function
- | IR r -> xreg_name r
- | FR r -> dreg_name r
+ | DR (IR (RR1 r)) -> xreg_name r
+ | DR (FR r) -> dreg_name r
| _ -> assert false
(* Names of sections *)
diff --git a/aarch64/extractionMachdep.v b/aarch64/extractionMachdep.v
index e82056e2..6815bc59 100644
--- a/aarch64/extractionMachdep.v
+++ b/aarch64/extractionMachdep.v
@@ -21,4 +21,4 @@ Extract Constant Archi.pic_code => "fun () -> false". (* for the time being *)
(* Asm *)
Extract Constant Asm.symbol_low => "fun _ _ _ -> assert false".
Extract Constant Asm.symbol_high => "fun _ _ _ -> assert false".
-Extract Constant Asmgen.symbol_is_aligned => "C2C.atom_is_aligned".
+Extract Constant Asmblockgen.symbol_is_aligned => "C2C.atom_is_aligned".
diff --git a/configure b/configure
index d0bbd0c1..91535bac 100755
--- a/configure
+++ b/configure
@@ -696,6 +696,9 @@ echo "-R lib compcert.lib \
-R cparser compcert.cparser \
-R MenhirLib compcert.MenhirLib" > _CoqProject
case $arch in
+ aarch64)
+ echo "-R kvx/lib compcert.kvx.lib -R kvx/abstractbb compcert.kvx.abstractbb" >> _CoqProject # import KVX libraries for aarch64
+ ;;
x86)
echo "-R x86_${bitsize} compcert.x86_${bitsize}" >> _CoqProject
;;
@@ -838,13 +841,27 @@ RESPONSEFILE="none"
EOF
fi
+if [ "$arch" = "aarch64" ]; then # for aarch64 scheduling
+cat >> Makefile.config <<EOF
+ARCHDIRS=$arch kvx/lib kvx/abstractbb kvx/abstractbb/Impure
+BACKENDLIB=Machblock.v Machblockgen.v Machblockgenproof.v OptionMonad.v IterList.v PseudoAsmblock.v PseudoAsmblockproof.v\\
+ Asmblock.v Asmblockgen.v Asmblockgenproof0.v Asmblockgenproof1.v Asmblockgenproof.v Asm.v Asmblockprops.v\\
+ ForwardSimulationBlock.v PostpassScheduling.v PostpassSchedulingproof.v\\
+ Asmblockdeps.v\\
+ AbstractBasicBlocksDef.v SeqSimuTheory.v ImpSimuTest.v Parallelizability.v\\
+ ImpConfig.v ImpCore.v ImpExtern.v ImpHCons.v ImpIO.v ImpLoops.v ImpMonads.v ImpPrelude.v
+ # TODO: UPDATE THIS
+ # DecBoolOps.v Chunks.v Peephole.v ExtValues.v ExtFloats.v
+EOF
+fi
+
if [ "$arch" = "kvx" ]; then
cat >> Makefile.config <<EOF
ARCHDIRS=$arch $arch/lib $arch/abstractbb $arch/abstractbb/Impure
EXECUTE=kvx-cluster --syscall=libstd_scalls.so --
CFLAGS= -D __KVX_COS__
SIMU=kvx-cluster --
-BACKENDLIB=Machblock.v Machblockgen.v Machblockgenproof.v\\
+BACKENDLIB=Machblock.v Machblockgen.v Machblockgenproof.v OptionMonad.v IterList.v PseudoAsmblock.v PseudoAsmblockproof.v\\
Asmblock.v Asmblockgen.v Asmblockgenproof0.v Asmblockgenproof1.v Asmblockgenproof.v Asmvliw.v Asmblockprops.v\\
ForwardSimulationBlock.v PostpassScheduling.v PostpassSchedulingproof.v\\
Asmblockdeps.v DecBoolOps.v Chunks.v Peephole.v ExtValues.v ExtFloats.v\\
diff --git a/extraction/extraction.v b/extraction/extraction.v
index c5fa7a62..f5b8291b 100644
--- a/extraction/extraction.v
+++ b/extraction/extraction.v
@@ -13,6 +13,7 @@
(* *)
(* *********************************************************************)
+Require Import ZArith PeanoNat.
Require Coqlib.
Require Wfsimpl.
Require DecidableClass Decidableplus.
@@ -220,7 +221,8 @@ Set Extraction AccessOpaque.
Cd "extraction".
-Separate Extraction
+Separate Extraction
+ Z.ldiff Z.lnot Nat.leb
CSE3analysis.internal_analysis CSE3analysis.eq_depends_on_mem
Compiler.transf_c_program Compiler.transf_cminor_program
Cexec.do_initial_state Cexec.do_step Cexec.at_final_state
diff --git a/kvx/lib/Asmblockgenproof0.v b/kvx/Asmblockgenproof0.v
index 1af59238..1af59238 100644
--- a/kvx/lib/Asmblockgenproof0.v
+++ b/kvx/Asmblockgenproof0.v
diff --git a/kvx/abstractbb/ImpSimuTest.v b/kvx/abstractbb/ImpSimuTest.v
index b1a3b985..6b64e1d8 100644
--- a/kvx/abstractbb/ImpSimuTest.v
+++ b/kvx/abstractbb/ImpSimuTest.v
@@ -23,9 +23,8 @@ Require Export Impure.ImpHCons. (**r Import the Impure library. See https://gith
Export Notations.
Import HConsing.
-
+Require Import Coq.Bool.Bool.
Require Export SeqSimuTheory.
-
Require Import PArith.
@@ -35,6 +34,8 @@ Import ListNotations.
Local Open Scope list_scope.
+Definition FULL_DEBUG_DUMP : bool := false. (* print debug traces, even if the verifier succeeds. *)
+
(** * Interface of (impure) equality tests for operators *)
Module Type ImpParam.
@@ -673,8 +674,8 @@ Hypothesis hco_term_correct: forall t, WHEN hco_term.(hC) t ~> t' THEN forall ge
Variable hco_list: hashConsing list_term.
Hypothesis hco_list_correct: forall t, WHEN hco_list.(hC) t ~> t' THEN forall ge m, list_term_eval ge (hdata t) m = list_term_eval ge t' m.
-Variable print_error_end: hsmem -> hsmem -> ?? unit.
-Variable print_error: pstring -> ?? unit.
+Variable print_end_error: hsmem -> hsmem -> ?? unit.
+Variable print_dump: (option pstring) -> ?? unit.
Variable check_failpreserv: bool.
Variable dbg_failpreserv: term -> ?? unit. (* info of additional failure of the output bbloc p2 wrt the input bbloc p1 *)
@@ -687,20 +688,23 @@ Program Definition g_bblock_simu_test (p1 p2: bblock): ?? bool :=
DO d2 <~ bblock_hsmem hco_term.(hC) hco_list.(hC) no_log_assign log_new_term log_inst2 p2;;
DO b <~ Dict.eq_test d1 d2 ;;
if b then (
- if check_failpreserv then (
+ (if check_failpreserv then
let hp := mk_hash_params dbg_failpreserv in
failure_in_failpreserv.(set)(true);;
- Sets.assert_list_incl hp d2.(hpre) d1.(hpre);;
- RET true
- ) else RET false
+ Sets.assert_list_incl hp d2.(hpre) d1.(hpre)
+ else RET tt);;
+ (if FULL_DEBUG_DUMP then
+ print_dump None (* not an error... *)
+ else RET tt);;
+ RET check_failpreserv
) else (
- print_error_end d1 d2 ;;
+ print_end_error d1 d2 ;;
RET false
)
CATCH_FAIL s, _ =>
DO b <~ failure_in_failpreserv.(get)();;
if b then RET false
- else print_error s;; RET false
+ else print_dump (Some s);; RET false
ENSURE (fun b => b=true -> forall ge, bblock_simu ge p1 p2));;
RET (`r).
Obligation 1.
@@ -773,12 +777,16 @@ Definition msg_unknow_term: pstring := "unknown term".
Definition msg_number: pstring := "on 2nd bblock -- on inst num ".
Definition msg_notfailpreserv: pstring := "a possible failure of 2nd bblock is absent in 1st bblock (INTERNAL ERROR: this error is expected to be detected before!!!)".
-Definition print_error_end (_ _: hsmem): ?? unit
+Definition print_end_error (_ _: hsmem): ?? unit
:= println (msg_prefix +; msg_error_on_end).
-Definition print_error (log: logger unit) (s:pstring): ?? unit
- := DO n <~ log_info log ();;
- println (msg_prefix +; msg_number +; n +; " -- " +; s).
+Definition print_error (log: logger unit) (os: option pstring): ?? unit
+ := match os with
+ | Some s =>
+ DO n <~ log_info log ();;
+ println (msg_prefix +; msg_number +; n +; " -- " +; s)
+ | None => RET tt
+ end.
Definition failpreserv_error (_: term): ?? unit
:= println (msg_prefix +; msg_notfailpreserv).
@@ -808,7 +816,7 @@ Program Definition bblock_simu_test (p1 p2: bblock): ?? bool :=
(log_insert log)
hco_term _
hco_list _
- print_error_end
+ print_end_error
(print_error log)
true (* check_failpreserv *)
failpreserv_error
@@ -905,7 +913,6 @@ with string_of_list_term (l: list_term): ?? pstring :=
RET (st +; ";" +; sl)
end.
-
End PrettryPrint.
@@ -948,7 +955,7 @@ Definition print_tables gdi ext exl: ?? unit :=
iterall exl (fun head _ pl => print_list gdi head pl.(hdata));;
println "----------------".
-Definition print_final_debug gdi (d1 d2: hsmem): ?? unit
+Definition print_final_debug gdi (d1 d2: hsmem): ?? unit
:= DO b <~ Dict.not_eq_witness d1 d2 ;;
match b with
| Some x =>
@@ -986,39 +993,44 @@ Definition print_witness gdi cr (*msg*) :=
| None => println "Unexpected failure: no witness info (hint: hash-consing bug ?)"
end.
-
-Definition print_error_end1 gdi hct hcl (d1 d2:hsmem): ?? unit
+Definition print_end_error1 gdi hct hcl (d1 d2:hsmem): ?? unit
:= println "- GRAPH of 1st bblock";;
DO ext <~ export hct ();;
DO exl <~ export hcl ();;
print_tables gdi ext exl;;
- print_error_end d1 d2;;
+ print_end_error d1 d2;;
print_final_debug gdi d1 d2.
-Definition print_error1 gdi hct hcl cr log s : ?? unit
+Definition print_dump1 gdi hct hcl cr log os : ?? unit
:= println "- GRAPH of 1st bblock";;
DO ext <~ export hct ();;
DO exl <~ export hcl ();;
print_tables gdi ext exl;;
- print_error log s;;
- print_witness gdi cr (*"1st"*).
-
+ print_error log os;;
+ match os with
+ | Some _ => print_witness gdi cr (*"1st"*)
+ | None => RET tt
+ end.
Definition xmsg_number: pstring := "on 1st bblock -- on inst num ".
-Definition print_error_end2 gdi hct hcl (d1 d2:hsmem): ?? unit
+Definition print_end_error2 gdi hct hcl (d1 d2:hsmem): ?? unit
:= println (msg_prefix +; msg_error_on_end);;
println "- GRAPH of 2nd bblock";;
DO ext <~ export hct ();;
DO exl <~ export hcl ();;
print_tables gdi ext exl.
-Definition print_error2 gdi hct hcl cr (log: logger unit) (s:pstring): ?? unit
+Definition print_dump2 gdi hct hcl cr (log: logger unit) (os:option pstring): ?? unit
:= DO n <~ log_info log ();;
DO ext <~ export hct ();;
DO exl <~ export hcl ();;
- println (msg_prefix +; xmsg_number +; n +; " -- " +; s);;
- print_witness gdi cr (*"2nd"*);;
+ match os with
+ | Some s =>
+ println (msg_prefix +; xmsg_number +; n +; " -- " +; s);;
+ print_witness gdi cr (*"2nd"*)
+ | None => RET tt
+ end;;
println "- GRAPH of 2nd bblock";;
print_tables gdi ext exl.
@@ -1051,21 +1063,25 @@ Program Definition verb_bblock_simu_test (p1 p2: bblock): ?? bool :=
DO cr <~ make_cref None;;
DO hco_term <~ mk_annot (hCons hpt);;
DO hco_list <~ mk_annot (hCons hplt);;
- DO result1 <~ g_bblock_simu_test
+ (if FULL_DEBUG_DUMP then
+ println("");;
+ println("-- START simu checker --")
+ else RET tt);;
+ DO result1 <~ (g_bblock_simu_test
(log_assign dict_info log1)
(log_new_term (msg_term cr))
(hlog log1 hco_term hco_list)
(log_insert log2)
hco_term _
hco_list _
- (print_error_end1 dict_info.(D.get) hco_term hco_list)
- (print_error1 dict_info.(D.get) hco_term hco_list cr log2)
+ (print_end_error1 dict_info.(D.get) hco_term hco_list)
+ (print_dump1 dict_info.(D.get) hco_term hco_list cr log2)
true
failpreserv_error
- p1 p2;;
- if result1
- then RET true
- else
+ p1 p2);;
+ if (if FULL_DEBUG_DUMP then false else result1)
+ then RET true
+ else (
DO dict_info <~ make_dict (mk_hash_params (fun _ => RET tt));;
DO log1 <~ count_logger ();;
DO log2 <~ count_logger ();;
@@ -1080,31 +1096,35 @@ Program Definition verb_bblock_simu_test (p1 p2: bblock): ?? bool :=
(log_insert log2)
hco_term _
hco_list _
- (print_error_end2 dict_info.(D.get) hco_term hco_list)
- (print_error2 dict_info.(D.get) hco_term hco_list cr log2)
+ (print_end_error2 dict_info.(D.get) hco_term hco_list)
+ (print_dump2 dict_info.(D.get) hco_term hco_list cr log2)
false
(fun _ => RET tt)
p2 p1;;
- if result2
- then (
- println (msg_prefix +; " OOops - symmetry violation in bblock_simu_test => this is a bug of bblock_simu_test ??");;
- RET false
- ) else RET false
- .
+ if FULL_DEBUG_DUMP then
+ println("-- END simu checker --");;
+ println("");;
+ RET result1
+ else if result2
+ then (
+ println (msg_prefix +; " OOops - symmetry violation in bblock_simu_test => this is a bug of bblock_simu_test ??");;
+ RET false
+ ) else RET false
+ ).
Obligation 1.
- generalize (hCons_correct _ _ _ H0); clear H0.
+ generalize (hCons_correct _ _ _ H1); clear H1.
wlp_simplify.
Qed.
Obligation 2.
- generalize (hCons_correct _ _ _ H); clear H.
+ generalize (hCons_correct _ _ _ H0); clear H0.
wlp_simplify.
Qed.
Obligation 3.
- generalize (hCons_correct _ _ _ H0); clear H0.
+ generalize (hCons_correct _ _ _ H1); clear H1.
wlp_simplify.
Qed.
Obligation 4.
- generalize (hCons_correct _ _ _ H); clear H.
+ generalize (hCons_correct _ _ _ H0); clear H0.
wlp_simplify.
Qed.
diff --git a/kvx/lib/IterList.v b/kvx/lib/IterList.v
new file mode 100644
index 00000000..49beb1c5
--- /dev/null
+++ b/kvx/lib/IterList.v
@@ -0,0 +1,96 @@
+Require Import Coqlib.
+
+(** TODO: are these def and lemma already defined in the standard library ?
+
+In this case, it should be better to reuse those of the standard library !
+
+*)
+
+Fixpoint iter {A} (n:nat) (f: A -> A) (x: A) {struct n}: A :=
+ match n with
+ | O => x
+ | S n0 => iter n0 f (f x)
+ end.
+
+Lemma iter_S A (n:nat) (f: A -> A): forall x, iter (S n) f x = f (iter n f x).
+Proof.
+ induction n; simpl; auto.
+ intros; erewrite <- IHn; simpl; auto.
+Qed.
+
+Lemma iter_plus A (n m:nat) (f: A -> A): forall x, iter (n+m) f x = iter m f (iter n f x).
+Proof.
+ induction n; simpl; auto.
+Qed.
+
+Definition iter_tail {A} (n:nat) (l: list A) := iter n (@tl A) l.
+
+Lemma iter_tail_S {A} (n:nat) (l: list A): iter_tail (S n) l = tl (iter_tail n l).
+Proof.
+ apply iter_S.
+Qed.
+
+Lemma iter_tail_plus A (n m:nat) (l: list A): iter_tail (n+m) l = iter_tail m (iter_tail n l).
+Proof.
+ apply iter_plus.
+Qed.
+
+Lemma iter_tail_length A l1: forall (l2: list A), iter_tail (length l1) (l1 ++ l2) = l2.
+Proof.
+ induction l1; auto.
+Qed.
+
+Lemma iter_tail_nil A n: @iter_tail A n nil = nil.
+Proof.
+ unfold iter_tail; induction n; simpl; auto.
+Qed.
+
+Lemma iter_tail_reach_nil A (l: list A): iter_tail (length l) l = nil.
+Proof.
+ rewrite (app_nil_end l) at 2.
+ rewrite iter_tail_length.
+ auto.
+Qed.
+
+Lemma length_iter_tail {A} (n:nat): forall (l: list A), (n <= List.length l)%nat -> (List.length l = n + List.length (iter_tail n l))%nat.
+Proof.
+ unfold iter_tail; induction n; auto.
+ intros l; destruct l. { simpl; omega. }
+ intros; simpl. erewrite IHn; eauto.
+ simpl in *; omega.
+Qed.
+
+Lemma iter_tail_S_ex {A} (n:nat): forall (l: list A), (n < length l)%nat -> exists x, iter_tail n l = x::(iter_tail (S n) l).
+Proof.
+ unfold iter_tail; induction n; simpl.
+ - intros l; destruct l; simpl; omega || eauto.
+ - intros l H; destruct (IHn (tl l)) as (x & H1).
+ + destruct l; simpl in *; try omega.
+ + rewrite H1; eauto.
+Qed.
+
+Lemma iter_tail_inject1 {A} (n1 n2:nat) (l: list A): (n1 <= List.length l)%nat -> (n2 <= List.length l)%nat -> iter_tail n1 l = iter_tail n2 l -> n1=n2.
+Proof.
+ intros H1 H2 EQ; exploit (length_iter_tail n1 l); eauto.
+ rewrite EQ.
+ rewrite (length_iter_tail n2 l); eauto.
+ omega.
+Qed.
+
+Lemma iter_tail_nil_inject {A} (n:nat) (l: list A): iter_tail n l = nil -> (List.length l <= n)%nat.
+Proof.
+ destruct (le_lt_dec n (List.length l)); try omega.
+ intros; exploit (iter_tail_inject1 n (length l) l); try omega.
+ rewrite iter_tail_reach_nil. auto.
+Qed.
+
+Lemma list_length_z_nat (A: Type) (l: list A): list_length_z l = Z.of_nat (length l).
+Proof.
+ induction l; auto.
+ rewrite list_length_z_cons. simpl. rewrite Zpos_P_of_succ_nat. omega.
+Qed.
+
+Lemma list_length_nat_z (A: Type) (l: list A): length l = Z.to_nat (list_length_z l).
+Proof.
+ intros; rewrite list_length_z_nat, Nat2Z.id. auto.
+Qed.
diff --git a/kvx/lib/OptionMonad.v b/kvx/lib/OptionMonad.v
new file mode 100644
index 00000000..824a9c2f
--- /dev/null
+++ b/kvx/lib/OptionMonad.v
@@ -0,0 +1,49 @@
+(* Declare Scope option_monad_scope. *)
+
+Notation "'SOME' X <- A 'IN' B" := (match A with Some X => B | None => None end)
+ (at level 200, X ident, A at level 100, B at level 200)
+ : option_monad_scope.
+
+Notation "'ASSERT' A 'IN' B" := (if A then B else None)
+ (at level 200, A at level 100, B at level 200)
+ : option_monad_scope.
+
+Local Open Scope option_monad_scope.
+
+
+(** Simple tactics for option-monad *)
+
+Lemma destruct_SOME A B (P: option B -> Prop) (e: option A) (f: A -> option B):
+ (forall x, e = Some x -> P (f x)) -> (e = None -> P None) -> (P (SOME x <- e IN f x)).
+Proof.
+ intros; destruct e; simpl; auto.
+Qed.
+
+Lemma destruct_ASSERT B (P: option B -> Prop) (e: bool) (x: option B):
+ (e = true -> P x) -> (e = false -> P None) -> (P (ASSERT e IN x)).
+Proof.
+ intros; destruct e; simpl; auto.
+Qed.
+
+Ltac inversion_SOME x :=
+ try (eapply destruct_SOME; [ let x := fresh x in intro x | simpl; try congruence ]).
+
+Ltac inversion_ASSERT :=
+ try (eapply destruct_ASSERT; [ idtac | simpl; try congruence ]).
+
+Ltac simplify_someHyp :=
+ match goal with
+ | H: None = Some _ |- _ => inversion H; clear H; subst
+ | H: Some _ = None |- _ => inversion H; clear H; subst
+ | H: ?t = ?t |- _ => clear H
+ | H: Some _ = Some _ |- _ => inversion H; clear H; subst
+ | H: Some _ <> None |- _ => clear H
+ | H: None <> Some _ |- _ => clear H
+ | H: _ = Some _ |- _ => (try rewrite !H in * |- *); generalize H; clear H
+ end.
+
+Ltac simplify_someHyps :=
+ repeat (simplify_someHyp; simpl in * |- *).
+
+Ltac try_simplify_someHyps :=
+ try (intros; simplify_someHyps; eauto).
diff --git a/kvx/lib/PseudoAsmblock.v b/kvx/lib/PseudoAsmblock.v
new file mode 100644
index 00000000..b33ea1bd
--- /dev/null
+++ b/kvx/lib/PseudoAsmblock.v
@@ -0,0 +1,267 @@
+Require Import Coqlib Maps AST Integers Values Memory Events Globalenvs Smallstep.
+Require Import Op Machregs Locations Stacklayout Conventions.
+Require Import Mach Machblock OptionMonad.
+
+
+(** Registers and States *)
+
+Inductive preg: Type :=
+ | PC: preg (* program counter *)
+ | RA: preg (* return-address *)
+ | SP: preg (* stack-pointer *)
+ | preg_of: mreg -> preg.
+Coercion preg_of: mreg >-> preg.
+
+Lemma preg_eq: forall (x y: preg), {x=y} + {x<>y}.
+Proof.
+ decide equality.
+ apply mreg_eq.
+Defined.
+
+Module PregEq.
+ Definition t := preg.
+ Definition eq := preg_eq.
+End PregEq.
+
+Module Pregmap := EMap(PregEq).
+
+Definition regset := Pregmap.t val.
+
+Module AsmNotations.
+
+(* Declare Scope asm. *)
+Notation "a # b" := (a b) (at level 1, only parsing) : asm.
+Notation "a # b <- c" := (Pregmap.set b c a) (at level 1, b at next level) : asm.
+Open Scope asm.
+
+End AsmNotations.
+
+Import AsmNotations.
+
+Definition to_Machrs (rs: regset): Mach.regset :=
+ fun (r:mreg) => rs r.
+Coercion to_Machrs: regset >-> Mach.regset.
+
+Definition set_from_Machrs (mrs: Mach.regset) (rs: regset): regset :=
+ fun (r:preg) =>
+ match r with
+ | preg_of mr => mrs mr
+ | _ => rs r
+ end.
+
+Local Open Scope option_monad_scope.
+
+Record state: Type := State { _rs: regset; _m: mem }.
+Definition outcome := option state.
+Definition Next rs m: outcome := Some (State rs m).
+Definition Stuck: outcome := None.
+
+(* Asm semantic on Mach *)
+
+Section RELSEM.
+
+(** "oracle" stating the successive position (ie offset) of each block in the final assembly function *)
+Variable next: function -> Z -> Z.
+
+Inductive is_pos (f: function): Z -> code -> Prop :=
+ | First_pos: is_pos f 0 (fn_code f)
+ | Next_pos pos b c: is_pos f pos (b::c) -> is_pos f (next f pos) c.
+
+Fixpoint label_pos (f: function) (lbl: label) (pos: Z) (c: code) {struct c} : option Z :=
+ match c with
+ | nil => None
+ | b :: c' =>
+ if is_label lbl b then Some pos else label_pos f lbl (next f pos) c'
+ end.
+
+Definition goto_label (f: function) (lbl: label) (rs: regset) : option val :=
+ SOME pos <- label_pos f lbl 0 (fn_code f) IN
+ match rs#PC with
+ | Vptr b _ => Some (Vptr b (Ptrofs.repr pos))
+ | _ => None
+ end.
+
+Definition next_addr (f: function) (rs: regset): option val :=
+ match rs#PC with
+ | Vptr b ofs => Some (Vptr b (Ptrofs.repr (next f (Ptrofs.unsigned ofs))))
+ | _ => None
+ end.
+
+Variable ge:genv.
+
+Inductive basic_step (f: function) (rs: regset) (m:mem): basic_inst -> regset -> mem -> Prop :=
+ | exec_MBgetstack:
+ forall ofs ty dst v,
+ load_stack m (rs#SP) ty ofs = Some v ->
+ basic_step f rs m (MBgetstack ofs ty dst) (rs#dst <- v) m
+ | exec_MBsetstack:
+ forall (src: mreg) ofs ty m' rs',
+ store_stack m (rs#SP) ty ofs (rs src) = Some m' ->
+ rs' = set_from_Machrs (undef_regs (destroyed_by_setstack ty) rs) rs ->
+ basic_step f rs m (MBsetstack src ofs ty) rs' m'
+ | exec_MBgetparam:
+ forall ofs ty (dst: mreg) v rs' psp,
+ load_stack m (rs#SP) Tptr f.(fn_link_ofs) = Some psp ->
+ load_stack m psp ty ofs = Some v ->
+ rs' = (rs # temp_for_parent_frame <- Vundef # dst <- v) ->
+ basic_step f rs m (MBgetparam ofs ty dst) rs' m
+ | exec_MBop:
+ forall op args v rs' (res: mreg),
+ eval_operation ge (rs#SP) op (to_Machrs rs)##args m = Some v ->
+ rs' = (set_from_Machrs (undef_regs (destroyed_by_op op) rs) rs)#res <- v ->
+ basic_step f rs m (MBop op args res) rs' m
+ | exec_MBload:
+ forall addr args a v rs' trap chunk (dst: mreg),
+ eval_addressing ge (rs#SP) addr (to_Machrs rs)##args = Some a ->
+ Mem.loadv chunk m a = Some v ->
+ rs' = (set_from_Machrs (undef_regs (destroyed_by_load chunk addr) rs) rs)#dst <- v ->
+ basic_step f rs m (MBload trap chunk addr args dst) rs' m
+ | exec_MBload_notrap1:
+ forall addr args rs' chunk (dst: mreg),
+ eval_addressing ge (rs#SP) addr (to_Machrs rs)##args = None ->
+ rs' = (set_from_Machrs (undef_regs (destroyed_by_load chunk addr) rs) rs)#dst <- (default_notrap_load_value chunk) ->
+ basic_step f rs m (MBload NOTRAP chunk addr args dst) rs' m
+ | exec_MBload_notrap2:
+ forall addr args a rs' chunk (dst: mreg),
+ eval_addressing ge (rs#SP) addr (to_Machrs rs)##args = Some a ->
+ Mem.loadv chunk m a = None ->
+ rs' = (set_from_Machrs (undef_regs (destroyed_by_load chunk addr) rs) rs)#dst <- (default_notrap_load_value chunk) ->
+ basic_step f rs m (MBload NOTRAP chunk addr args dst) rs' m
+ | exec_MBstore:
+ forall chunk addr args (src: mreg) m' a rs',
+ eval_addressing ge (rs#SP) addr (to_Machrs rs)##args = Some a ->
+ Mem.storev chunk m a (rs src) = Some m' ->
+ rs' = set_from_Machrs (undef_regs (destroyed_by_store chunk addr) rs) rs ->
+ basic_step f rs m (MBstore chunk addr args src) rs' m'
+ .
+
+
+Inductive body_step (f: function) : bblock_body -> regset -> mem -> regset -> mem -> Prop :=
+ | exec_nil_body rs m:
+ body_step f nil rs m rs m
+ | exec_cons_body rs m bi p rs' m' rs'' m'':
+ basic_step f rs m bi rs' m' ->
+ body_step f p rs' m' rs'' m'' ->
+ body_step f (bi::p) rs m rs'' m''
+ .
+
+
+Definition find_function_ptr (ros: mreg + ident) (rs: regset) : option val :=
+ match ros with
+ | inl r => Some (rs#r)
+ | inr symb =>
+ SOME b <- Genv.find_symbol ge symb IN
+ Some (Vptr b Ptrofs.zero)
+ end.
+
+Definition exec_epilogue (f: function) (rs: regset) (m: mem) : outcome :=
+ SOME sp <- load_stack m rs#SP Tptr f.(fn_link_ofs) IN
+ SOME ra <- load_stack m rs#SP Tptr f.(fn_retaddr_ofs) IN
+ match rs#SP with
+ | Vptr stk ofs =>
+ SOME m' <- Mem.free m stk 0 f.(fn_stacksize) IN
+ Next (rs#SP <- sp #RA <- ra) m'
+ | _ => Stuck
+ end.
+
+Inductive cfi_step (f: function): control_flow_inst -> regset -> mem -> trace -> regset -> mem -> Prop :=
+ | exec_MBcall sig ros rs m pc:
+ find_function_ptr ros rs = Some pc ->
+ cfi_step f (MBcall sig ros) rs m E0 ((rs#RA <- (rs#PC))#PC <- pc) m
+ | exec_MBtailcall sig ros rs m rs' m' pc:
+ find_function_ptr ros rs = Some pc ->
+ exec_epilogue f rs m = Next rs' m' ->
+ cfi_step f (MBtailcall sig ros) rs m E0 (rs'#PC <- pc) m'
+ | exec_MBreturn rs m rs' m':
+ exec_epilogue f rs m = Next rs' m' ->
+ cfi_step f MBreturn rs m E0 (rs'#PC <- (rs'#RA)) m'
+ | exec_MBgoto lbl rs m pc:
+ goto_label f lbl rs = Some pc ->
+ cfi_step f (MBgoto lbl) rs m E0 (rs#PC <- pc) m
+ | exec_MBcond_true cond args lbl rs m pc rs':
+ eval_condition cond (to_Machrs rs)##args m = Some true ->
+ goto_label f lbl rs = Some pc ->
+ rs' = set_from_Machrs (undef_regs (destroyed_by_cond cond) rs) rs ->
+ cfi_step f (MBcond cond args lbl) rs m E0 (rs'#PC <- pc) m
+ | exec_MBcond_false cond args lbl rs m rs':
+ eval_condition cond (to_Machrs rs)##args m = Some false ->
+ rs' = set_from_Machrs (undef_regs (destroyed_by_cond cond) rs) rs ->
+ cfi_step f (MBcond cond args lbl) rs m E0 rs' m
+ | exec_MBjumptable arg tbl rs m index lbl pc rs':
+ to_Machrs rs arg = Vint index ->
+ list_nth_z tbl (Int.unsigned index) = Some lbl ->
+ goto_label f lbl rs = Some pc ->
+ rs' = set_from_Machrs (undef_regs destroyed_by_jumptable rs) rs ->
+ cfi_step f (MBjumptable arg tbl) rs m E0 (rs'#PC <- pc) m
+ | exec_MBbuiltin rs m ef args res vargs t vres rs' m':
+ eval_builtin_args ge (to_Machrs rs) (rs#SP) m args vargs ->
+ external_call ef ge vargs m t vres m' ->
+ rs' = set_from_Machrs (set_res res vres (undef_regs (destroyed_by_builtin ef) rs)) rs ->
+ cfi_step f (MBbuiltin ef args res) rs m t rs' m'
+ .
+
+Inductive exit_step f : option control_flow_inst -> regset -> mem -> trace -> regset -> mem -> Prop :=
+ | exec_Some_exit ctl rs m t rs' m':
+ cfi_step f ctl rs m t rs' m' ->
+ exit_step f (Some ctl) rs m t rs' m'
+ | exec_None_exit rs m:
+ exit_step f None rs m E0 rs m
+ .
+
+Inductive exec_bblock f: bblock -> regset -> mem -> trace -> regset -> mem -> Prop :=
+ | exec_bblock_all (bb: bblock) rs0 m0 rs1 m1 pc t rs2 m2:
+ body_step f (body bb) rs0 m0 rs1 m1 ->
+ next_addr f rs1 = Some pc ->
+ exit_step f (exit bb) (rs1#PC <- pc) m1 t rs2 m2 ->
+ exec_bblock f bb rs0 m0 t rs2 m2.
+
+Definition exec_prologue f (pos:Z) (rs: regset) (m:mem) : option state :=
+ if Z.eq_dec pos 0 then
+ let (m1, stk) := Mem.alloc m 0 f.(fn_stacksize) in
+ let sp := Vptr stk Ptrofs.zero in
+ SOME m2 <- store_stack m1 sp Tptr f.(fn_link_ofs) rs#SP IN
+ SOME m3 <- store_stack m2 sp Tptr f.(fn_retaddr_ofs) rs#RA IN
+ Next ((set_from_Machrs (undef_regs destroyed_at_function_entry rs) rs)#SP <- sp) m3
+ else
+ Next rs m.
+
+
+Inductive step: state -> trace -> state -> Prop :=
+ | exec_step_internal b ofs f bb c rs0 m0 rs1 m1 t rs2 m2:
+ rs0 PC = Vptr b ofs ->
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ is_pos f (Ptrofs.unsigned ofs) (bb::c) ->
+ exec_prologue f (Ptrofs.unsigned ofs) rs0 m0 = Next rs1 m1 ->
+ exec_bblock f bb rs1 m1 t rs2 m2 ->
+ step (State rs0 m0) t (State rs2 m2)
+ | exec_step_external:
+ forall b ef args res rs m t rs' m',
+ rs PC = Vptr b Ptrofs.zero ->
+ Genv.find_funct_ptr ge b = Some (External ef) ->
+ extcall_arguments (to_Machrs rs) m (rs#SP) (ef_sig ef) args ->
+ external_call ef ge args m t res m' ->
+ rs' = (set_from_Machrs (set_pair (loc_result (ef_sig ef)) res (undef_caller_save_regs rs)) rs) #PC <- (rs RA) ->
+ step (State rs m) t (State rs' m').
+
+End RELSEM.
+
+Inductive initial_state (p: program): state -> Prop :=
+ | initial_state_intro: forall m0,
+ let ge := Genv.globalenv p in
+ Genv.init_mem p = Some m0 ->
+ let rs0 :=
+ (Pregmap.init Vundef)
+ # PC <- (Genv.symbol_address ge p.(prog_main) Ptrofs.zero)
+ # SP <- Vnullptr
+ # RA <- Vnullptr in
+ initial_state p (State rs0 m0).
+
+Inductive final_state: state -> int -> Prop :=
+ | final_state_intro: forall rs m r retcode,
+ loc_result signature_main = One r ->
+ rs PC = Vnullptr ->
+ rs r = Vint retcode ->
+ final_state (State rs m) retcode.
+
+Definition semantics (next: function -> Z -> Z) (p: program) :=
+ Semantics (step next) (initial_state p) final_state (Genv.globalenv p).
diff --git a/kvx/lib/PseudoAsmblockproof.v b/kvx/lib/PseudoAsmblockproof.v
new file mode 100644
index 00000000..67308278
--- /dev/null
+++ b/kvx/lib/PseudoAsmblockproof.v
@@ -0,0 +1,1173 @@
+Require Import Coqlib Maps AST Integers Values Memory Events Globalenvs Smallstep.
+Require Import Op Machregs Locations Stacklayout Conventions.
+Require Import Mach Machblock OptionMonad.
+Require Import Errors Datatypes PseudoAsmblock IterList.
+
+(** Tiny translation from Machblock semantics to PseudoAsmblock semantics (needs additional checks)
+*)
+
+Section TRANSLATION.
+
+(* In the actual Asmblock code, the prologue will be inserted in the first block of the function.
+ But, this block should have an empty header.
+*)
+
+Definition has_header (c: code) : bool :=
+ match c with
+ | nil => false
+ | bb::_ => match header bb with
+ | nil => false
+ | _ => true
+ end
+ end.
+
+Definition insert_implicit_prologue c :=
+ if has_header c then {| header := nil; body := nil; exit := None |}::c else c.
+
+Definition transl_function (f: function) : function :=
+ {| fn_sig:=fn_sig f;
+ fn_code:=insert_implicit_prologue (fn_code f);
+ fn_stacksize := fn_stacksize f;
+ fn_link_ofs := fn_link_ofs f;
+ fn_retaddr_ofs := fn_retaddr_ofs f
+ |}.
+
+Definition transf_function (f: function) : res function :=
+ let tf := transl_function f in
+ (* removed because it is simpler or/and more efficient to perform this test in Asmblockgen !
+ if zlt Ptrofs.max_unsigned (max_pos tf)
+ then Error (msg "code size exceeded")
+ else *)
+ OK tf.
+
+Definition transf_fundef (f: fundef) : res fundef :=
+ transf_partial_fundef transf_function f.
+
+Definition transf_program (p: program) : res program :=
+ transform_partial_program transf_fundef p.
+
+End TRANSLATION.
+
+(** Proof of the translation
+*)
+
+Require Import Linking.
+Import PseudoAsmblock.AsmNotations.
+
+Section PRESERVATION.
+
+Definition match_prog (p: program) (tp: program) :=
+ match_program (fun _ f tf => transf_fundef f = OK tf) eq p tp.
+
+Lemma transf_program_match:
+ forall p tp, transf_program p = OK tp -> match_prog p tp.
+Proof.
+ intros. eapply match_transform_partial_program; eauto.
+Qed.
+
+Local Open Scope Z_scope.
+Local Open Scope option_monad_scope.
+
+Variable prog: program.
+Variable tprog: program.
+
+Hypothesis TRANSF: match_prog prog tprog.
+Let ge := Genv.globalenv prog.
+Let tge := Genv.globalenv tprog.
+
+Variable next: function -> Z -> Z.
+
+Hypothesis next_progress: forall (f:function) (pos:Z), (pos < (next f pos))%Z.
+
+Definition max_pos (f:function) := iter (S (length f.(fn_code))) (next f) 0.
+
+(* This hypothesis expresses that Asmgen checks for each tf
+ that (max_pos tf) represents a valid address
+*)
+Hypothesis functions_bound_max_pos: forall fb tf,
+ Genv.find_funct_ptr tge fb = Some (Internal tf) ->
+ (max_pos tf) <= Ptrofs.max_unsigned.
+
+(** * Agreement between Mach registers and PseudoAsm registers *)
+Record agree (ms: Mach.regset) (sp: val) (rs: regset) : Prop := mkagree {
+ agree_sp: rs#SP = sp;
+ agree_sp_def: sp <> Vundef;
+ agree_mregs: forall r: mreg, (ms r)=(rs#r)
+}.
+
+(** [transl_code_at_pc pc fb f tf c] holds if the code pointer [pc] points
+ within the code generated by Machblock function (originally [f] -- but translated as [tf]),
+ and [c] is the tail of the code at the position corresponding to the code pointer [pc].
+*)
+Inductive transl_code_at_pc (b:block) (f:function) (tf:function) (c:code): val -> Prop :=
+ transl_code_at_pc_intro ofs:
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ transf_function f = OK tf ->
+ (* we have passed the first block containing the prologue *)
+ (0 < (Ptrofs.unsigned ofs))%Z ->
+ (* the code is identical in the two functions *)
+ is_pos next tf (Ptrofs.unsigned ofs) c ->
+ transl_code_at_pc b f tf c (Vptr b ofs).
+
+Inductive match_stack: list stackframe -> Prop :=
+ | match_stack_nil:
+ match_stack nil
+ | match_stack_cons: forall fb sp ra c s f tf,
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transl_code_at_pc fb f tf c ra ->
+ sp <> Vundef ->
+ match_stack s ->
+ match_stack (Stackframe fb sp ra c :: s).
+
+(** Semantic preservation is proved using simulation diagrams
+ of the following form.
+<<
+ s1 ---------------- s2
+ | |
+ t| *|t
+ | |
+ v v
+ s1'---------------- s2'
+>>
+ The invariant is the [match_states] predicate below...
+
+*)
+
+Inductive match_states: Machblock.state -> state -> Prop :=
+ | match_states_internal s fb sp c ms m rs f tf
+ (STACKS: match_stack s)
+ (FIND: Genv.find_funct_ptr ge fb = Some (Internal f))
+ (AT: transl_code_at_pc fb f tf c (rs PC))
+ (AG: agree ms sp rs):
+ match_states (Machblock.State s fb sp c ms m)
+ (State rs m)
+ | match_states_prologue s sp fb ms rs0 m0 f rs1 m1
+ (STACKS: match_stack s)
+ (AG: agree ms sp rs1)
+ (ATPC: rs0 PC = Vptr fb Ptrofs.zero)
+ (ATLR: rs0 RA = parent_ra s)
+ (FIND: Genv.find_funct_ptr ge fb = Some (Internal f))
+ (PROL: exec_prologue f 0 rs0 m0 = Next rs1 m1):
+ match_states (Machblock.State s fb sp (fn_code f) ms m1)
+ (State rs0 m0)
+ | match_states_call s fb ms m rs
+ (STACKS: match_stack s)
+ (AG: agree ms (parent_sp s) rs)
+ (ATPC: rs PC = Vptr fb Ptrofs.zero)
+ (ATLR: rs RA = parent_ra s):
+ match_states (Machblock.Callstate s fb ms m)
+ (State rs m)
+ | match_states_return s ms m rs
+ (STACKS: match_stack s)
+ (AG: agree ms (parent_sp s) rs)
+ (ATPC: rs PC = parent_ra s):
+ match_states (Machblock.Returnstate s ms m)
+ (State rs m).
+
+Definition measure (s: Machblock.state) : nat :=
+ match s with
+ | Machblock.State _ _ _ _ _ _ => 0%nat
+ | Machblock.Callstate _ _ _ _ => 1%nat
+ | Machblock.Returnstate _ _ _ => 1%nat
+ end.
+
+Definition rao (f: function) (c: code) (ofs: ptrofs) : Prop :=
+ forall tf,
+ transf_function f = OK tf ->
+ is_pos next tf (Ptrofs.unsigned ofs) c.
+
+Lemma symbols_preserved:
+ forall (s: ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
+Proof (Genv.find_symbol_match TRANSF).
+
+Lemma senv_preserved:
+ Senv.equiv ge tge.
+Proof (Genv.senv_match TRANSF).
+
+Lemma functions_translated:
+ forall b f,
+ Genv.find_funct_ptr ge b = Some f ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some tf /\ transf_fundef f = OK tf.
+Proof (Genv.find_funct_ptr_transf_partial TRANSF).
+
+Lemma functions_transl fb f tf:
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ transf_function f = OK tf ->
+ Genv.find_funct_ptr tge fb = Some (Internal tf).
+Proof.
+ intros. exploit functions_translated; eauto. intros [tf' [A B]].
+ monadInv B. inv H0; auto.
+Qed.
+
+Lemma function_bound fb f tf:
+ Genv.find_funct_ptr ge fb = Some (Internal f) -> transf_function f = OK tf -> (max_pos tf) <= Ptrofs.max_unsigned.
+Proof.
+ intros; eapply functions_bound_max_pos; eauto.
+ eapply functions_transl; eauto.
+Qed.
+
+Lemma transf_function_def f tf:
+ transf_function f = OK tf -> tf.(fn_code) = insert_implicit_prologue f.(fn_code).
+Proof.
+ unfold transf_function.
+ intros EQ; inv EQ.
+ auto.
+Qed.
+
+Lemma stackinfo_preserved f tf:
+ transf_function f = OK tf ->
+ tf.(fn_stacksize) = f.(fn_stacksize)
+ /\ tf.(fn_retaddr_ofs) = f.(fn_retaddr_ofs)
+ /\ tf.(fn_link_ofs) = f.(fn_link_ofs).
+Proof.
+ unfold transf_function.
+ intros EQ0; inv EQ0. simpl; intuition.
+Qed.
+
+Lemma transf_initial_states st1: Machblock.initial_state prog st1 ->
+ exists st2, initial_state tprog st2 /\ match_states st1 st2.
+Proof.
+ intro H. inversion H. unfold ge0 in *.
+ econstructor; split.
+ - econstructor.
+ eapply (Genv.init_mem_transf_partial TRANSF); eauto.
+ - replace (Genv.symbol_address (Genv.globalenv tprog) (prog_main tprog) Ptrofs.zero)
+ with (Vptr fb Ptrofs.zero).
+ + econstructor; eauto.
+ * constructor.
+ * split; auto; simpl; unfold Vnullptr; destruct Archi.ptr64; congruence.
+ + unfold Genv.symbol_address.
+ rewrite (match_program_main TRANSF).
+ rewrite symbols_preserved.
+ unfold ge. simplify_someHyp. auto.
+Qed.
+
+Lemma transf_final_states st1 st2 r:
+ match_states st1 st2 -> Machblock.final_state st1 r -> final_state st2 r.
+Proof.
+ intros H H0. inv H0. inv H.
+ econstructor; eauto.
+ exploit agree_mregs; eauto.
+ erewrite H2. intro H3; inversion H3.
+ auto.
+Qed.
+
+(** Lemma on [is_pos]. *)
+
+Lemma is_pos_alt_def f pos code: is_pos next f pos code ->
+ exists n, (n <= List.length (fn_code f))%nat /\ pos = (iter n (next f) 0) /\ code = iter_tail n (fn_code f).
+Proof.
+ induction 1.
+ - unfold iter_tail; exists O; simpl; intuition.
+ - destruct IHis_pos as (n & H0 & H1 & H2).
+ exists (S n). repeat split.
+ + rewrite (length_iter_tail n); eauto.
+ rewrite <- H2; simpl; omega.
+ + rewrite iter_S; congruence.
+ + unfold iter_tail in *; rewrite iter_S, <- H2; auto.
+Qed.
+
+Local Hint Resolve First_pos Next_pos: core.
+
+Lemma is_pos_alt_def_recip f n: (n <= List.length (fn_code f))%nat ->
+ is_pos next f (iter n (next f) 0) (iter_tail n (fn_code f)).
+Proof.
+ induction n.
+ - unfold iter_tail; simpl; eauto.
+ - intros H; destruct (iter_tail_S_ex n (fn_code f)) as (x & H1); try omega.
+ rewrite iter_S; lapply IHn; try omega.
+ rewrite H1; eauto.
+Qed.
+
+Lemma is_pos_inject1 f pos1 pos2 code:
+ is_pos next f pos1 code -> is_pos next f pos2 code -> pos1=pos2.
+Proof.
+ intros H1 H2.
+ destruct (is_pos_alt_def f pos1 code) as (n1 & B1 & POS1 & CODE1); eauto.
+ destruct (is_pos_alt_def f pos2 code) as (n2 & B2 & POS2 & CODE2); eauto.
+ clear H1 H2; subst.
+ erewrite (iter_tail_inject1 n1 n2); eauto.
+Qed.
+
+Lemma iter_next_strict_monotonic f n m x: (n < m)%nat -> iter n (next f) x < iter m (next f) x.
+Proof.
+ induction 1; rewrite iter_S; auto.
+ generalize (next_progress f (iter m (next f) x)).
+ omega.
+Qed.
+
+Lemma iter_next_monotonic f n m x: (n <= m)%nat -> iter n (next f) x <= iter m (next f) x.
+Proof.
+ destruct 1.
+ - omega.
+ - generalize (iter_next_strict_monotonic f n (S m) x). omega.
+Qed.
+
+Lemma is_pos_bound_pos f pos code:
+ is_pos next f pos code -> 0 <= pos <= max_pos f.
+Proof.
+ intros H; exploit is_pos_alt_def; eauto.
+ intros (n & H1 & H2 & H3).
+ rewrite H2. unfold max_pos. split.
+ - cutrewrite (0 = iter O (next f) 0); auto.
+ apply iter_next_monotonic; omega.
+ - apply iter_next_monotonic; omega.
+Qed.
+
+Lemma is_pos_unsigned_repr f pos code:
+ is_pos next f pos code ->
+ max_pos f <= Ptrofs.max_unsigned ->
+ Ptrofs.unsigned (Ptrofs.repr pos) = pos.
+Proof.
+ intros; eapply Ptrofs.unsigned_repr.
+ exploit is_pos_bound_pos; eauto.
+ omega.
+Qed.
+
+Lemma is_pos_simplify f pos code:
+ is_pos next f pos code ->
+ max_pos f <= Ptrofs.max_unsigned ->
+ is_pos next f (Ptrofs.unsigned (Ptrofs.repr pos)) code.
+Proof.
+ intros; erewrite is_pos_unsigned_repr; eauto.
+Qed.
+
+Lemma find_label_label_pos f lbl c: forall pos c',
+ find_label lbl c = Some c' ->
+ exists n,
+ label_pos next f lbl pos c = Some (iter n (next f) pos)
+ /\ c' = iter_tail n c
+ /\ (n <= List.length c)%nat.
+Proof.
+ induction c.
+ - simpl; intros. discriminate.
+ - simpl; intros pos c'.
+ destruct (is_label lbl a).
+ + intro EQ; injection EQ; intro; subst c'.
+ exists O; simpl; intuition.
+ + intros. generalize (IHc (next f pos) c' H). intros (n' & A & B & C).
+ exists (S n'). intuition.
+Qed.
+
+Lemma find_label_insert_implicit_prologue lbl c:
+ find_label lbl c = find_label lbl (insert_implicit_prologue c).
+Proof.
+ unfold insert_implicit_prologue.
+ destruct (has_header c); simpl; auto.
+ unfold is_label; simpl.
+ destruct (in_dec lbl nil); auto.
+ simpl in *. tauto.
+Qed.
+
+Lemma no_header_insert_implicit_prologue c:
+ has_header (insert_implicit_prologue c) = false.
+Proof.
+ unfold insert_implicit_prologue.
+ destruct (has_header c) eqn: H; simpl; auto.
+Qed.
+
+Lemma find_label_has_header lbl c c':
+ find_label lbl c = Some c' ->
+ has_header c' = true.
+Proof.
+ induction c; simpl; try congruence.
+ destruct (is_label lbl a) eqn:LAB; auto.
+ intros X; inv X; simpl.
+ unfold is_label in LAB.
+ destruct (in_dec lbl (header a)); try congruence.
+ destruct (header a); try congruence.
+ simpl in *; tauto.
+Qed.
+
+Lemma find_label_label_pos_no_header f lbl c pos c':
+ (has_header c) = false ->
+ find_label lbl c = Some c' ->
+ exists n,
+ label_pos next f lbl pos c = Some (iter (S n) (next f) pos)
+ /\ c' = iter_tail (S n) c
+ /\ ((S n) <= List.length c)%nat.
+Proof.
+ intros H H0; exploit find_label_label_pos; eauto.
+ intros ([|n] & H1 & H2 & H3); try (exists n; intuition eauto).
+ unfold iter_tail in *; simpl in *; subst.
+ erewrite find_label_has_header in H; eauto.
+ congruence.
+Qed.
+
+Hint Resolve is_pos_simplify is_pos_alt_def_recip function_bound: core.
+
+Lemma find_label_goto_label f tf lbl rs c' b ofs:
+ Genv.find_funct_ptr ge b = Some (Internal f) ->
+ transf_function f = OK tf ->
+ Vptr b ofs = rs PC ->
+ find_label lbl f.(fn_code) = Some c' ->
+ exists pc,
+ goto_label next tf lbl rs = Some pc
+ /\ transl_code_at_pc b f tf c' pc.
+Proof.
+ intros FINDF T HPC FINDL.
+ erewrite find_label_insert_implicit_prologue, <- transf_function_def in FINDL; eauto.
+ exploit find_label_label_pos_no_header; eauto.
+ { erewrite transf_function_def; eauto.
+ apply no_header_insert_implicit_prologue.
+ }
+ intros (n & LAB & CODE & BOUND); subst.
+ exists (Vptr b (Ptrofs.repr (iter (S n) (next tf) 0))).
+ unfold goto_label; intuition.
+ - simplify_someHyps; rewrite <- HPC. auto.
+ - econstructor; eauto.
+ erewrite is_pos_unsigned_repr; eauto.
+ generalize (iter_next_strict_monotonic tf O (S n) 0); simpl.
+ omega.
+Qed.
+
+(** Preservation of register agreement under various assignments. *)
+
+Lemma agree_mregs_list ms sp rs:
+ agree ms sp rs ->
+ forall l, (ms##l)=(to_Machrs rs)##l.
+Proof.
+ unfold to_Machrs. intros AG; induction l; simpl; eauto.
+ erewrite agree_mregs; eauto.
+ congruence.
+Qed.
+
+Lemma agree_set_mreg ms sp rs r v rs':
+ agree ms sp rs ->
+ v=(rs'#(preg_of r)) ->
+ (forall r', r' <> preg_of r -> rs'#r' = rs#r') ->
+ agree (Regmap.set r v ms) sp rs'.
+Proof.
+ intros H H0 H1. destruct H. split; auto.
+ - rewrite H1; auto. destruct r; simpl; congruence.
+ - intros. unfold Regmap.set. destruct (RegEq.eq r0 r). congruence.
+ rewrite H1; auto. destruct r; simpl; congruence.
+Qed.
+
+Corollary agree_set_mreg_parallel:
+ forall ms sp rs r v,
+ agree ms sp rs ->
+ agree (Regmap.set r v ms) sp (Pregmap.set (preg_of r) v rs).
+Proof.
+ intros. eapply agree_set_mreg; eauto.
+ - rewrite Pregmap.gss; auto.
+ - intros; apply Pregmap.gso; auto.
+Qed.
+
+Corollary agree_set_mreg_parallel2:
+ forall ms sp rs r v ms',
+ agree ms sp (set_from_Machrs ms' rs)->
+ agree (Regmap.set r v ms) sp (set_from_Machrs (Regmap.set r v ms') rs).
+Proof.
+ intros. unfold set_from_Machrs in *. eapply agree_set_mreg; eauto.
+ - rewrite Regmap.gss; auto.
+ - intros r' X. destruct r'; try congruence. rewrite Regmap.gso; try congruence.
+Qed.
+
+Definition data_preg (r: preg) : bool :=
+ match r with
+ | preg_of _ | SP => true
+ | _ => false
+ end.
+
+Lemma agree_exten ms sp rs rs':
+ agree ms sp rs ->
+ (forall r, data_preg r = true -> rs'#r = rs#r) ->
+ agree ms sp rs'.
+Proof.
+ intros H H0. destruct H. split; intros; try rewrite H0; auto.
+Qed.
+
+Lemma agree_set_from_Machrs ms sp ms' rs:
+ agree ms sp rs ->
+ (forall (r:mreg), (ms' r) = rs#r) ->
+ agree ms sp (set_from_Machrs ms' rs).
+Proof.
+ unfold set_from_Machrs; intros.
+ eapply agree_exten; eauto.
+ intros r; destruct r; simpl; try congruence.
+Qed.
+
+Lemma agree_set_other ms sp rs r v:
+ agree ms sp rs ->
+ data_preg r = false ->
+ agree ms sp (rs#r <- v).
+Proof.
+ intros; apply agree_exten with rs; auto.
+ intros. apply Pregmap.gso. congruence.
+Qed.
+
+
+Lemma agree_next_addr f ms sp b pos rs:
+ agree ms sp rs ->
+ agree ms sp (rs#PC <- (Vptr b (Ptrofs.repr (next f pos)))).
+Proof.
+ intros. apply agree_set_other; auto.
+Qed.
+
+Local Hint Resolve agree_set_mreg_parallel2: core.
+
+Lemma agree_set_pair sp p v ms ms' rs:
+ agree ms sp (set_from_Machrs ms' rs) ->
+ agree (set_pair p v ms) sp (set_from_Machrs (set_pair p v ms') rs).
+Proof.
+ intros H; destruct p; simpl; auto.
+Qed.
+
+Lemma agree_undef_caller_save_regs:
+ forall ms sp ms' rs,
+ agree ms sp (set_from_Machrs ms' rs) ->
+ agree (undef_caller_save_regs ms) sp (set_from_Machrs (undef_caller_save_regs ms') rs).
+Proof.
+ intros. destruct H as [H0 H1 H2]. unfold undef_caller_save_regs. split; auto.
+ intros.
+ unfold set_from_Machrs in * |- *.
+ rewrite H2. auto.
+Qed.
+
+Lemma agree_change_sp ms sp rs sp':
+ agree ms sp rs -> sp' <> Vundef ->
+ agree ms sp' (rs#SP <- sp').
+Proof.
+ intros H H0. inv H. split; auto.
+Qed.
+
+Lemma agree_undef_regs ms sp rl ms' rs:
+ agree ms sp (set_from_Machrs ms' rs) ->
+ agree (Mach.undef_regs rl ms) sp (set_from_Machrs (Mach.undef_regs rl ms') rs).
+Proof.
+ unfold set_from_Machrs; intros H. destruct H; subst. split; auto.
+ intros. destruct (In_dec mreg_eq r rl).
+ + rewrite! undef_regs_same; auto.
+ + rewrite! undef_regs_other; auto.
+Qed.
+
+(** Translation of arguments and results to builtins. *)
+
+Remark builtin_arg_match:
+ forall ms rs sp m a v,
+ agree ms sp rs ->
+ eval_builtin_arg ge ms sp m a v ->
+ eval_builtin_arg ge (to_Machrs rs) sp m a v.
+Proof.
+ induction 2; simpl; eauto with barg.
+ unfold to_Machrs; erewrite agree_mregs; eauto.
+ econstructor.
+Qed.
+
+Lemma builtin_args_match:
+ forall ms sp rs m,
+ agree ms sp rs ->
+ forall al vl, eval_builtin_args ge ms sp m al vl ->
+ eval_builtin_args ge (to_Machrs rs) sp m al vl.
+Proof.
+ induction 2; intros; simpl; try (constructor; auto).
+ eapply eval_builtin_arg_preserved; eauto.
+ eapply builtin_arg_match; eauto.
+Qed.
+
+Lemma agree_set_res res: forall ms sp rs v ms',
+ agree ms sp (set_from_Machrs ms' rs) ->
+ agree (set_res res v ms) sp (set_from_Machrs (set_res res v ms') rs).
+Proof.
+ induction res; simpl; auto.
+Qed.
+
+Lemma find_function_ptr_agree ros ms rs sp b:
+ agree ms sp rs ->
+ Machblock.find_function_ptr ge ros ms = Some b ->
+ find_function_ptr tge ros rs = Some (Vptr b Ptrofs.zero).
+Proof.
+ intros AG; unfold Mach.find_function_ptr; destruct ros as [r|s]; simpl; auto.
+ - generalize (agree_mregs _ _ _ AG r). destruct (ms r); simpl; try congruence.
+ intros H; inv H; try congruence.
+ inversion_ASSERT. intros H; rewrite (Ptrofs.same_if_eq _ _ H); eauto.
+ try_simplify_someHyps.
+ - intros H; rewrite symbols_preserved, H. auto.
+Qed.
+
+Lemma parent_sp_def: forall s, match_stack s -> parent_sp s <> Vundef.
+Proof.
+ induction 1; simpl.
+ unfold Vnullptr; destruct Archi.ptr64; congruence.
+ auto.
+Qed.
+
+Lemma extcall_arg_match ms sp rs m l v:
+ agree ms sp rs ->
+ extcall_arg ms m sp l v ->
+ extcall_arg rs m (rs#SP) l v.
+Proof.
+ destruct 2.
+ - erewrite agree_mregs; eauto. constructor.
+ - unfold load_stack in *. econstructor; eauto.
+ erewrite agree_sp; eauto.
+Qed.
+
+Local Hint Resolve extcall_arg_match: core.
+
+Lemma extcall_arg_pair_match:
+ forall ms sp rs m p v,
+ agree ms sp rs ->
+ extcall_arg_pair ms m sp p v ->
+ extcall_arg_pair rs m (rs#SP) p v.
+Proof.
+ destruct 2; constructor; eauto.
+Qed.
+
+Local Hint Resolve extcall_arg_pair_match: core.
+
+Lemma extcall_args_match:
+ forall ms sp rs m, agree ms sp rs ->
+ forall ll vl,
+ list_forall2 (extcall_arg_pair ms m sp) ll vl ->
+ list_forall2 (extcall_arg_pair rs m rs#SP) ll vl.
+Proof.
+ induction 2; constructor; eauto.
+Qed.
+
+Lemma extcall_arguments_match:
+ forall ms m sp rs sg args,
+ agree ms sp rs ->
+ extcall_arguments ms m sp sg args ->
+ extcall_arguments rs m (rs#SP) sg args.
+Proof.
+ unfold extcall_arguments, extcall_arguments; intros.
+ eapply extcall_args_match; eauto.
+Qed.
+
+(** A few tactics *)
+
+Local Hint Resolve functions_transl symbols_preserved
+ agree_next_addr agree_mregs agree_set_mreg_parallel agree_undef_regs agree_set_other agree_change_sp
+ agree_sp_def agree_set_from_Machrs agree_set_pair agree_undef_caller_save_regs agree_set_res f_equal Ptrofs.repr_unsigned parent_sp_def
+ builtin_args_match external_call_symbols_preserved: core.
+
+Ltac simplify_regmap :=
+ repeat (rewrite ?Pregmap.gss; try (rewrite Pregmap.gso; try congruence)).
+
+Ltac simplify_next_addr :=
+ match goal with
+ | [ HPC: Vptr _ _ = _ PC |- _ ] => try (unfold next_addr, Val.offset_ptr); simplify_regmap; try (rewrite <- HPC)
+ end.
+
+Ltac discharge_match_states :=
+ econstructor; eauto; try ( simplify_next_addr; econstructor; eauto ).
+
+
+(** Instruction step simulation lemma: the simulation lemma for stepping one instruction
+
+<<
+ s1 ---------------- s2
+ | |
+ t| +|t
+ | |
+ v v
+ s1'---------------- s2'
+>>
+
+*)
+
+Lemma trivial_exec_prologue:
+ forall tf ofs rs m,
+ 0 < Ptrofs.unsigned ofs ->
+ exec_prologue tf (Ptrofs.unsigned ofs) rs m = Next rs m.
+Proof.
+ unfold exec_prologue. intros.
+ destruct (Z.eq_dec); eauto. omega.
+Qed.
+
+Lemma basic_step_simulation: forall ms sp rs s f tf fb ms' bi m m',
+ agree ms sp rs ->
+ match_stack s ->
+ transf_function f = OK tf ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ Machblock.basic_step ge s fb sp ms m bi ms' m' ->
+ exists rs', basic_step tge tf rs m bi rs' m' /\ agree ms' sp rs' /\ rs' PC = rs PC.
+Proof.
+ destruct 5.
+ (* MBgetstack *)
+ - eexists; split.
+ + econstructor; eauto. erewrite agree_sp; eauto.
+ + eauto.
+ (* MBsetstack *)
+ - eexists; split.
+ + econstructor; eauto.
+ erewrite agree_sp; eauto.
+ erewrite <- agree_mregs; eauto.
+ + rewrite H4; split; eauto.
+ (* MBgetparam *)
+ - eexists; split.
+ + econstructor; eauto.
+ erewrite agree_sp; eauto.
+ assert (f = f0). { rewrite H2 in H3. inversion H3. reflexivity. }
+ assert (fn_link_ofs tf = fn_link_ofs f0). {
+ rewrite <- H7.
+ eapply stackinfo_preserved. eauto.
+ }
+ rewrite H8. eauto.
+ + rewrite H6; split; eauto.
+ (* MBop *)
+ - eexists; split.
+ + econstructor; eauto.
+ erewrite agree_sp; eauto.
+ erewrite agree_mregs_list in H3.
+ * erewrite <- H3.
+ eapply eval_operation_preserved; trivial.
+ * eauto.
+ + rewrite H4; split; eauto.
+ (* MBload *)
+ - eexists; split.
+ + econstructor; eauto.
+ erewrite agree_sp; eauto. erewrite <- agree_mregs_list; eauto.
+ erewrite <- H3.
+ eapply eval_addressing_preserved; trivial.
+ + rewrite H5; split; eauto.
+ (* MBload notrap1 *)
+ - eexists; split.
+ + eapply exec_MBload_notrap1; eauto.
+ erewrite agree_sp; eauto.
+ erewrite agree_mregs_list in H3; eauto.
+ * erewrite eval_addressing_preserved; eauto.
+ + rewrite H4; eauto.
+ (* MBload notrap2 *)
+ - eexists; split.
+ + eapply exec_MBload_notrap2; eauto.
+ erewrite agree_sp; eauto.
+ erewrite agree_mregs_list in H3; eauto.
+ * erewrite eval_addressing_preserved; eauto.
+ + rewrite H5; eauto.
+ (* MBstore *)
+ - eexists; split.
+ + econstructor; eauto.
+ * erewrite agree_sp; eauto.
+ erewrite agree_mregs_list in H3.
+ erewrite eval_addressing_preserved; eauto.
+ eauto.
+ * erewrite <- agree_mregs; eauto.
+ + rewrite H5; eauto.
+Qed.
+
+Lemma body_step_simulation: forall ms sp s f tf fb ms' bb m m',
+ match_stack s ->
+ transf_function f = OK tf ->
+ Genv.find_funct_ptr ge fb = Some (Internal f) ->
+ Machblock.body_step ge s fb sp bb ms m ms' m' ->
+ forall rs, agree ms sp rs ->
+ exists rs', body_step tge tf bb rs m rs' m' /\ agree ms' sp rs' /\ rs' PC = rs PC.
+Proof.
+ induction 4.
+ - repeat (econstructor; eauto).
+ - intros. exploit basic_step_simulation; eauto.
+ intros (rs'0 & BASIC & AG1' & AGPC1).
+ exploit IHbody_step; eauto.
+ intros (rs'1 & BODY & AG2' & AGPC2).
+ repeat (econstructor; eauto).
+ congruence.
+Qed.
+
+Local Hint Resolve trivial_exec_prologue: core.
+
+Lemma exit_step_simulation s fb f sp c t bb ms m s1' tf rs pc
+ (STEP: Machblock.exit_step rao ge (exit bb) (Machblock.State s fb sp (bb :: c) ms m) t s1')
+ (STACKS: match_stack s)
+ (AG: agree ms sp rs)
+ (NXT: next_addr next tf rs = Some pc)
+ (AT: transl_code_at_pc fb f tf c pc):
+ exists rs' m', exit_step next tge tf (exit bb) (rs#PC <- pc) m t rs' m' /\ match_states s1' (State rs' m').
+Proof.
+ inv AT.
+ inv STEP.
+ (* cfi_step currently only defined for exec_MBcall, exec_MBreturn, and exec_MBgoto *)
+ - inversion H4; subst. clear H4. (* inversion_clear H4 does not work so well: it clears an important hypothesis about "sp" in the Mreturn case *)
+ (* MBcall *)
+ + eexists. eexists. split.
+ * apply exec_Some_exit.
+ apply exec_MBcall.
+ eapply find_function_ptr_agree; eauto.
+ * assert (f0 = f). { congruence. } subst.
+ assert (Ptrofs.unsigned ra = Ptrofs.unsigned ofs). {
+ eapply is_pos_inject1; eauto.
+ }
+ assert (ofs = ra). {
+ apply Ptrofs.same_if_eq. unfold Ptrofs.eq.
+ rewrite H4. rewrite zeq_true. reflexivity.
+ }
+ repeat econstructor; eauto.
+ -- unfold rao in *. congruence.
+ -- simpl. simplify_regmap.
+ erewrite agree_sp; eauto.
+ -- simpl. simplify_regmap. auto.
+ (* MBtailcall *)
+ + assert (f0 = f). { congruence. } subst.
+ eexists. eexists. split.
+ * repeat econstructor.
+ -- eapply find_function_ptr_agree; eauto.
+ -- unfold exec_epilogue. erewrite agree_sp; eauto.
+ apply stackinfo_preserved in H0 as ( SS & RA & LO ).
+ rewrite SS, RA, LO.
+ try_simplify_someHyps.
+ * repeat econstructor; eauto.
+ intros r.
+ eapply agree_mregs; eapply agree_set_other; eauto.
+ (* MBbuiltin *)
+ +eexists. eexists. split.
+ * repeat econstructor.
+ -- simplify_regmap. erewrite agree_sp; eauto.
+ eapply eval_builtin_args_preserved; eauto.
+ -- eapply external_call_symbols_preserved; eauto.
+ exact senv_preserved.
+ * repeat econstructor; eauto.
+ -- assert (transl_function f = tf). {
+ unfold transf_function in *. congruence.
+ }
+ erewrite H5. assumption.
+ -- eapply agree_sp. eapply agree_set_res. eapply agree_undef_regs.
+ eapply agree_set_from_Machrs; eauto.
+ -- intros; simpl.
+ eapply agree_set_res. eapply agree_undef_regs.
+ eapply agree_set_from_Machrs; eauto.
+ (* MBgoto *)
+ + simplify_someHyps. intros.
+ assert ((rs # PC <- (Vptr fb ofs)) PC = Vptr fb ofs). {
+ rewrite Pregmap.gss. reflexivity.
+ }
+ eassert (exists pc, goto_label next tf lbl rs # PC <- (Vptr fb ofs) = Some pc
+ /\ transl_code_at_pc fb f tf c' pc) as (pc & GOTO_LABEL & _). {
+ eapply find_label_goto_label; eauto.
+ }
+ eexists. eexists. split.
+ * apply exec_Some_exit.
+ apply exec_MBgoto.
+ rewrite GOTO_LABEL. trivial.
+ * repeat econstructor; eauto.
+ -- simplify_regmap.
+ exploit find_label_goto_label; eauto. intros (pc' & GOTO_LABEL' & TRANSL).
+ assert(pc' = pc). { congruence. } subst. eauto.
+ -- simplify_regmap. erewrite agree_sp; eauto.
+ (* MBcond true *)
+ (* Mostly copy and paste from MBgoto *)
+ + simplify_someHyps. intros.
+ assert ((rs # PC <- (Vptr fb ofs)) PC = Vptr fb ofs). {
+ rewrite Pregmap.gss. reflexivity.
+ }
+ eassert (exists pc, goto_label next tf lbl rs # PC <- (Vptr fb ofs) = Some pc
+ /\ transl_code_at_pc fb f tf c' pc) as (pc & GOTO_LABEL & _). {
+ eapply find_label_goto_label; eauto.
+ }
+ eexists. eexists. split.
+ * apply exec_Some_exit. eapply exec_MBcond_true; eauto.
+ erewrite agree_mregs_list in H14; eauto.
+ * repeat econstructor; eauto.
+ -- simplify_regmap.
+ exploit find_label_goto_label; eauto. intros (pc' & GOTO_LABEL' & TRANSL).
+ assert(pc' = pc). { congruence. } subst. eauto.
+ -- simplify_regmap. erewrite agree_sp; eauto.
+ (* MBcond false *)
+ + inv H0. eexists. eexists. split.
+ * apply exec_Some_exit. apply exec_MBcond_false.
+ -- erewrite agree_mregs_list in H15; eauto.
+ -- trivial.
+ * repeat econstructor; eauto. erewrite agree_sp; eauto.
+ (* MBjumptable *)
+ + simplify_someHyps. intros.
+ assert ((rs # PC <- (Vptr fb ofs)) PC = Vptr fb ofs). {
+ rewrite Pregmap.gss. reflexivity.
+ }
+ eassert (exists pc, goto_label next tf lbl rs # PC <- (Vptr fb ofs) = Some pc
+ /\ transl_code_at_pc fb f tf c' pc) as (pc & GOTO_LABEL & _). {
+ eapply find_label_goto_label; eauto.
+ }
+ eexists. eexists. split.
+ * repeat econstructor; eauto.
+ rewrite <- H14.
+ symmetry. eapply agree_mregs. eapply agree_set_other; eauto.
+ * repeat econstructor; eauto.
+ (* copy paste from MBgoto *)
+ -- simplify_regmap.
+ exploit find_label_goto_label; eauto. intros (pc' & GOTO_LABEL' & TRANSL).
+ assert(pc' = pc). { congruence. } subst. eauto.
+ -- simplify_regmap. erewrite agree_sp; eauto.
+ -- intros; simplify_regmap. eauto.
+ + (* MBreturn *)
+ try_simplify_someHyps.
+ eexists. eexists. split.
+ * apply exec_Some_exit.
+ apply exec_MBreturn.
+ unfold exec_epilogue.
+ erewrite agree_sp; eauto.
+ apply stackinfo_preserved in H0 as ( SS & RA & LO ).
+ rewrite SS, RA, LO.
+ try_simplify_someHyps.
+ * repeat econstructor; eauto. intros r.
+ simplify_regmap. eapply agree_mregs; eauto.
+ - inv H0; repeat econstructor; eauto.
+ erewrite agree_sp; eauto.
+Qed.
+
+Lemma inst_step_simulation s fb f sp c t ms m s1' tf rs
+ (STEP: Machblock.step rao ge (Machblock.State s fb sp c ms m) t s1')
+ (STACKS: match_stack s)
+ (AT: transl_code_at_pc fb f tf c (rs PC))
+ (AG: agree ms sp rs):
+ exists s2' : state, plus (step next) tge (State rs m) t s2' /\ match_states s1' s2'.
+Proof.
+ inv STEP.
+ inv AT.
+ exploit body_step_simulation; eauto. intros (rs0' & BODY & AG0 & AGPC).
+ assert (NXT: next_addr next tf rs0' = Some (Vptr fb (Ptrofs.repr (next tf (Ptrofs.unsigned ofs))))).
+ { unfold next_addr; rewrite AGPC, <- H; simpl; eauto. }
+ exploit exit_step_simulation; eauto.
+ { econstructor; eauto.
+ erewrite is_pos_unsigned_repr; eauto.
+ generalize (next_progress tf (Ptrofs.unsigned ofs)); omega. }
+ intros (rs2 & m2 & STEP & MS).
+ eexists.
+ split; eauto.
+ eapply plus_one.
+ eapply exec_step_internal; eauto.
+ econstructor; eauto.
+Qed.
+
+Lemma prologue_preserves_pc: forall f rs0 m0 rs1 m1,
+ exec_prologue f 0 rs0 m0 = Next rs1 m1 ->
+ rs1 PC = rs0 PC.
+Proof.
+ unfold exec_prologue; simpl;
+ intros f rs0 m0 rs1 m1 H.
+ destruct (Mem.alloc m0 0 (fn_stacksize f)) in H; unfold Next in H.
+ simplify_someHyps; inversion_SOME ignored; inversion_SOME ignored';
+ intros ? ? H'; inversion H'; trivial.
+Qed.
+
+Lemma is_pos_next_zero bb c fb f
+ (FIND : Genv.find_funct_ptr ge fb = Some (Internal f))
+ (FN_HEAD : bb :: c = fn_code f):
+ is_pos next (transl_function f) (next (transl_function f) (Ptrofs.unsigned Ptrofs.zero)) (if has_header (fn_code f) then bb::c else c).
+Proof.
+ exploit (transf_function_def f). unfold transf_function; auto.
+ unfold insert_implicit_prologue.
+ intros fn_code_tf; destruct (has_header (fn_code f));
+ eapply Next_pos; rewrite Ptrofs.unsigned_zero;
+ rewrite FN_HEAD; rewrite <- fn_code_tf; apply First_pos.
+Qed.
+
+Lemma prologue_simulation_no_header_step t s1' s sp fb ms f m1 rs0 m0 rs1
+ (STACKS : match_stack s)
+ (AG : agree ms sp rs1)
+ (ATPC : rs0 PC = Vptr fb Ptrofs.zero)
+ (ATLR : rs0 RA = parent_ra s)
+ (FIND : Genv.find_funct_ptr ge fb = Some (Internal f))
+ (PROL : exec_prologue f 0 rs0 m0 = Next rs1 m1)
+ (STEP : Machblock.step rao ge (Machblock.State s fb sp (fn_code f) ms m1) t s1')
+ (NO_HEADER: has_header (fn_code f) = false):
+ exists s2' : state, step next tge {| _rs := rs0; _m := m0 |} t s2' /\ match_states s1' s2'.
+Proof.
+ inv STEP.
+
+ exploit functions_translated; eauto;
+ intros (tf & FINDtf & TRANSf); monadInv TRANSf.
+ assert (fn_code f = fn_code (transl_function f)) as TF_CODE. {
+ unfold transl_function; simpl; unfold insert_implicit_prologue;
+ rewrite NO_HEADER; trivial.
+ }
+
+ exploit body_step_simulation; eauto; unfold transf_function; auto.
+ intros (rs0' & BODY & AG0 & AGPC).
+
+ exploit prologue_preserves_pc; eauto.
+ intros AGPC'.
+
+ exploit is_pos_next_zero; eauto; rewrite NO_HEADER.
+ intros IS_POS.
+
+ exploit transl_code_at_pc_intro; eauto; unfold transf_function; auto. {
+ rewrite Ptrofs.unsigned_zero; erewrite is_pos_unsigned_repr; eauto.
+ } intros TRANSL_CODE.
+
+ assert (next_addr next (transl_function f) rs0' =
+ Some (Vptr fb (Ptrofs.repr (next (transl_function f)
+ (Ptrofs.unsigned Ptrofs.zero))))) as NEXT_ADDR. {
+ unfold next_addr; rewrite AGPC; rewrite AGPC'; rewrite ATPC; reflexivity.
+ }
+
+ exploit exit_step_simulation; eauto.
+ intros (? & ? & EXIT_STEP & MATCH_EXIT).
+
+ exploit exec_bblock_all; eauto.
+ intros EXEC_BBLOCK.
+
+ exploit exec_step_internal; eauto.
+ apply is_pos_simplify; eauto. rewrite H3; rewrite TF_CODE; apply First_pos.
+Qed.
+
+Lemma prologue_simulation_header_step t s1' s sp fb ms f m1 rs0 m0 rs1
+ (STACKS : match_stack s)
+ (AG : agree ms sp rs1)
+ (ATPC : rs0 PC = Vptr fb Ptrofs.zero)
+ (ATLR : rs0 RA = parent_ra s)
+ (FIND : Genv.find_funct_ptr ge fb = Some (Internal f))
+ (PROL : exec_prologue f 0 rs0 m0 = Next rs1 m1)
+ (STEP : Machblock.step rao ge (Machblock.State s fb sp (fn_code f) ms m1) t s1')
+ (HEADER: has_header (fn_code f) = true):
+ exists s2' : state, plus (step next) tge {| _rs := rs0; _m := m0 |} t s2' /\ match_states s1' s2'.
+Proof.
+ inv STEP.
+
+ (* FIRST STEP *)
+ exploit functions_translated; eauto;
+ intros (tf & FINDtf & TRANSf); monadInv TRANSf.
+ exploit transf_function_def; eauto; unfold transf_function; auto;
+ unfold insert_implicit_prologue; rewrite HEADER; intros TF_CODE.
+
+ exploit is_pos_next_zero; eauto; rewrite HEADER; rewrite H3;
+ intros IS_POS.
+
+ exploit prologue_preserves_pc; eauto.
+ intros AGPC'.
+
+ assert ( next_addr next (transl_function f) rs1
+ = Some (Vptr fb (Ptrofs.repr (next (transl_function f) (Ptrofs.unsigned Ptrofs.zero))))
+ ) as NEXT_ADDR0. { unfold next_addr; rewrite AGPC'; rewrite ATPC; trivial. }
+
+ exploit exec_nil_body; intros BODY0.
+ assert ((body {| header := nil; body := nil; exit := None |}) = nil) as NIL; auto.
+ rewrite <- NIL in BODY0.
+
+ exploit exec_None_exit; intros EXIT0.
+ assert ((exit {| header := nil; body := nil; exit := None |}) = None) as NONE; auto.
+ rewrite <- NONE in EXIT0.
+
+ exploit exec_bblock_all; eauto;
+ intros BBLOCK0.
+
+ exploit exec_step_internal; eauto. rewrite <- TF_CODE; apply First_pos.
+ intros STEP0.
+
+ clear BODY0 BBLOCK0 EXIT0.
+
+ (* SECOND step *)
+
+ exploit (mkagree ms sp
+ (rs1 # PC <- (Vptr fb (Ptrofs.repr (next (transl_function f)
+ (Ptrofs.unsigned Ptrofs.zero)))))); eauto.
+ apply (agree_sp ms); apply agree_set_other; eauto.
+ intros AG'.
+
+ exploit body_step_simulation; eauto; unfold transf_function; auto.
+ intros (rs1' & BODY1 & AGRS1' & AGPC).
+
+ assert ( next_addr next (transl_function f) rs1'
+ = Some (Vptr fb (Ptrofs.repr (next (transl_function f) (Ptrofs.unsigned
+ (Ptrofs.repr (next (transl_function f) (Ptrofs.unsigned Ptrofs.zero)))))))
+ ) as NEXT_ADDR1. { unfold next_addr; rewrite AGPC; reflexivity. }
+
+ assert (IS_POS' := IS_POS).
+ rewrite <- H3 in IS_POS'; apply Next_pos in IS_POS'.
+ exploit transl_code_at_pc_intro; eauto; unfold transf_function; auto. {
+ rewrite Ptrofs.unsigned_zero; erewrite is_pos_unsigned_repr; eauto.
+ assert (0 < next (transl_function f) 0) as Z0. { apply next_progress. }
+ assert ( next (transl_function f) 0
+ < next (transl_function f) (next (transl_function f) 0)
+ ) as Z1. { apply next_progress. }
+ rewrite <- Z1. exact Z0.
+ } intros TRANSL_CODE1.
+
+ exploit exit_step_simulation; eauto.
+ rewrite Ptrofs.unsigned_repr.
+ 2: {
+ assert(max_pos (transl_function f) <= Ptrofs.max_unsigned) as MAX_POS. {
+ eapply functions_bound_max_pos; eauto.
+ }
+ rewrite <- MAX_POS.
+ eapply is_pos_bound_pos; eauto.
+ }
+ exact TRANSL_CODE1.
+ intros (? & ? & EXIT_STEP & MATCH_EXIT).
+
+ exploit (trivial_exec_prologue (transl_function f) (Ptrofs.repr (next (transl_function f) (Ptrofs.unsigned Ptrofs.zero)))). {
+ rewrite Ptrofs.unsigned_zero; erewrite is_pos_unsigned_repr; eauto.
+ } intros NO_PROL.
+
+ exploit exec_bblock_all; eauto; intros BBLOCK1.
+
+ clear AGPC.
+ rewrite <- H3 in IS_POS.
+ exploit (exec_step_internal next tge fb
+ (Ptrofs.repr (next (transl_function f) (Ptrofs.unsigned Ptrofs.zero)))
+ (transl_function f)
+ bb c); simplify_regmap; eauto.
+
+ intros STEP1.
+
+ eexists; split.
+ + eapply plus_two.
+ * exact STEP0.
+ * exact STEP1.
+ * trivial.
+ + assumption.
+Qed.
+
+Lemma step_simulation s1 t s1':
+ Machblock.step rao ge s1 t s1' ->
+ forall s2, match_states s1 s2 ->
+ (exists s2', plus (step next) tge s2 t s2' /\ match_states s1' s2') \/ ((measure s1' < measure s1)%nat /\ t = E0 /\ match_states s1' s2).
+Proof.
+ intros STEP s2 MATCH; destruct MATCH.
+ - exploit inst_step_simulation; eauto.
+ - left.
+ destruct (has_header (fn_code f)) eqn:NO_HEADER.
+ + eapply prologue_simulation_header_step; eauto.
+ + exploit prologue_simulation_no_header_step; eauto;
+ intros (s2' & NO_HEADER_STEP & MATCH_STATES).
+ eexists; split; eauto.
+ apply plus_one; eauto.
+ - inv STEP; simpl; exploit functions_translated; eauto;
+ intros (tf0 & FINDtf & TRANSf);
+ monadInv TRANSf.
+ * (* internal calls *)
+ right.
+ intuition.
+ econstructor; eauto.
+ -- exploit
+ (mkagree (undef_regs destroyed_at_function_entry ms)
+ sp
+ (set_from_Machrs (undef_regs destroyed_at_function_entry rs) rs) # SP <- sp
+ ); eauto.
+ ++ unfold sp; discriminate.
+ ++ intros mr; unfold undef_regs;
+ induction destroyed_at_function_entry as [ | ? ? IH].
+ ** inversion AG as [_ _ AG_MREGS]; apply AG_MREGS.
+ ** fold undef_regs in *;
+ unfold Regmap.set; simpl; rewrite IH; reflexivity.
+ -- unfold exec_prologue;
+ inversion AG as (RS_SP & ?); rewrite RS_SP; fold sp;
+ rewrite H4; fold sp; rewrite H7; rewrite ATLR; rewrite H8; eauto.
+ * (* external calls *)
+ left.
+ exploit extcall_arguments_match; eauto.
+ eexists; split.
+ + eapply plus_one.
+ eapply exec_step_external; eauto.
+ eapply external_call_symbols_preserved; eauto. apply senv_preserved.
+ + econstructor; eauto.
+ - (* Returnstate *)
+ inv STEP; simpl; right.
+ inv STACKS; simpl in *; subst.
+ repeat (econstructor; eauto).
+Qed.
+
+(** * The main simulation theorem *)
+
+Theorem transf_program_correct:
+ forward_simulation (Machblock.semantics rao prog) (semantics next tprog).
+Proof.
+ eapply forward_simulation_star with (measure := measure).
+ apply senv_preserved.
+ - eexact transf_initial_states.
+ - eexact transf_final_states.
+ - eexact step_simulation.
+Qed.
+
+End PRESERVATION.
diff --git a/multiple_labels_crash_test/check.c b/multiple_labels_crash_test/check.c
new file mode 100644
index 00000000..3c2ff89d
--- /dev/null
+++ b/multiple_labels_crash_test/check.c
@@ -0,0 +1,120 @@
+#include "init.h"
+
+unsigned long long int checksum () {
+ unsigned long long int seed = 0ULL;
+ hash(&seed, var_36);
+ hash(&seed, var_37);
+ hash(&seed, var_38);
+ hash(&seed, var_39);
+ hash(&seed, var_40);
+ hash(&seed, var_41);
+ hash(&seed, var_42);
+ hash(&seed, var_43);
+ hash(&seed, var_44);
+ hash(&seed, var_45);
+ hash(&seed, var_46);
+ hash(&seed, var_47);
+ hash(&seed, var_48);
+ hash(&seed, var_49);
+ hash(&seed, var_50);
+ hash(&seed, var_51);
+ hash(&seed, var_52);
+ hash(&seed, var_53);
+ hash(&seed, var_54);
+ hash(&seed, var_55);
+ hash(&seed, var_56);
+ hash(&seed, var_57);
+ hash(&seed, var_58);
+ hash(&seed, var_59);
+ hash(&seed, var_60);
+ hash(&seed, var_61);
+ hash(&seed, var_62);
+ hash(&seed, var_63);
+ hash(&seed, var_64);
+ hash(&seed, var_65);
+ hash(&seed, var_70);
+ hash(&seed, var_78);
+ hash(&seed, var_82);
+ hash(&seed, var_90);
+ hash(&seed, var_94);
+ hash(&seed, var_100);
+ hash(&seed, var_106);
+ hash(&seed, var_123);
+ hash(&seed, var_129);
+ hash(&seed, var_143);
+ hash(&seed, var_152);
+ hash(&seed, var_156);
+ hash(&seed, var_162);
+ hash(&seed, var_178);
+ hash(&seed, var_217);
+ hash(&seed, var_234);
+ hash(&seed, var_240);
+ hash(&seed, var_241);
+ hash(&seed, var_260);
+ hash(&seed, var_268);
+ hash(&seed, var_284);
+ hash(&seed, var_297);
+ hash(&seed, var_314);
+ hash(&seed, var_358);
+ hash(&seed, var_359);
+ hash(&seed, var_367);
+ hash(&seed, var_392);
+ hash(&seed, var_468);
+ hash(&seed, var_500);
+ hash(&seed, var_514);
+ hash(&seed, var_522);
+ hash(&seed, var_543);
+ hash(&seed, var_544);
+ hash(&seed, var_547);
+ hash(&seed, var_549);
+ hash(&seed, var_558);
+ hash(&seed, var_591);
+ hash(&seed, struct_obj_5.member_1_0);
+ hash(&seed, struct_obj_5.member_1_1);
+ hash(&seed, struct_obj_5.member_1_2);
+ hash(&seed, struct_obj_5.member_1_3);
+ hash(&seed, struct_obj_6.member_5_0);
+ hash(&seed, struct_obj_6.member_5_1);
+ hash(&seed, struct_obj_6.member_5_2);
+ hash(&seed, struct_obj_6.member_5_3);
+ hash(&seed, struct_obj_7.member_1_0);
+ hash(&seed, struct_obj_7.member_1_1);
+ hash(&seed, struct_obj_7.member_1_2);
+ hash(&seed, struct_obj_7.member_1_3);
+ hash(&seed, struct_obj_8.member_4_0);
+ hash(&seed, struct_obj_8.member_4_1.member_3_0);
+ hash(&seed, struct_obj_8.member_4_1.member_3_1.member_1_0);
+ hash(&seed, struct_obj_8.member_4_1.member_3_1.member_1_1);
+ hash(&seed, struct_obj_8.member_4_1.member_3_1.member_1_2);
+ hash(&seed, struct_obj_8.member_4_1.member_3_1.member_1_3);
+ hash(&seed, struct_obj_8.member_4_2);
+ hash(&seed, struct_obj_8.member_4_3);
+ hash(&seed, struct_obj_8.member_4_4);
+ hash(&seed, struct_obj_8.member_4_5);
+ hash(&seed, struct_obj_8.member_4_6);
+ hash(&seed, struct_obj_8.member_4_7);
+ hash(&seed, struct_obj_8.member_4_8);
+ hash(&seed, struct_obj_8.member_4_9.member_1_0);
+ hash(&seed, struct_obj_8.member_4_9.member_1_1);
+ hash(&seed, struct_obj_8.member_4_9.member_1_2);
+ hash(&seed, struct_obj_8.member_4_9.member_1_3);
+ hash(&seed, struct_obj_9.member_2_0);
+ hash(&seed, struct_obj_9.member_2_1.member_1_0);
+ hash(&seed, struct_obj_9.member_2_1.member_1_1);
+ hash(&seed, struct_obj_9.member_2_1.member_1_2);
+ hash(&seed, struct_obj_9.member_2_1.member_1_3);
+ hash(&seed, struct_obj_9.member_2_2);
+ hash(&seed, struct_obj_9.member_2_3.member_1_0);
+ hash(&seed, struct_obj_9.member_2_3.member_1_1);
+ hash(&seed, struct_obj_9.member_2_3.member_1_2);
+ hash(&seed, struct_obj_9.member_2_3.member_1_3);
+ hash(&seed, struct_obj_9.member_2_4);
+ hash(&seed, struct_obj_9.member_2_5);
+ hash(&seed, struct_obj_9.member_2_6);
+ hash(&seed, struct_obj_9.member_2_7);
+ hash(&seed, struct_obj_10.member_1_0);
+ hash(&seed, struct_obj_10.member_1_1);
+ hash(&seed, struct_obj_10.member_1_2);
+ hash(&seed, struct_obj_10.member_1_3);
+ return seed;
+} \ No newline at end of file
diff --git a/multiple_labels_crash_test/driver.c b/multiple_labels_crash_test/driver.c
new file mode 100644
index 00000000..3084e131
--- /dev/null
+++ b/multiple_labels_crash_test/driver.c
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include "init.h"
+
+extern void init ();
+extern void foo ();
+extern unsigned long long int checksum ();
+
+int main () {
+ init ();
+ foo ();
+ printf("%llu\n", checksum ()); return 0;
+} \ No newline at end of file
diff --git a/multiple_labels_crash_test/func.c b/multiple_labels_crash_test/func.c
new file mode 100644
index 00000000..cc9d3653
--- /dev/null
+++ b/multiple_labels_crash_test/func.c
@@ -0,0 +1,915 @@
+#include "init.h"
+
+void foo ()
+{
+ unsigned short var_66 = ~((int) ((((int) (((int) (((int) (-27782)) > ((int) (5913)))) <= ((int) ((signed char) (11720))))) | ((int) (30935))) <= (((~((int) (-17))) * (((int) (92)) * ((int) (7)))) * ((int) (56914)))));
+ if ((unsigned short) ((short) (((int) ((unsigned short) (((int) (-5211)) & ((int) (var_47))))) <= (((int) ((short) (15973))) & ((int) (17901))))))
+ {
+ var_58 = (signed char) (((int) ((((int) (-104)) | ((((int) (-16858)) ^ ((int) (var_24))) ^ ((int) ((signed char) (-45))))) <= ((int) ((signed char) (+((int) (struct_obj_4.member_2_5))))))) != (((int) (4536)) || ((int) (50251))));
+ if ((((((int) (63229)) && ((int) ((signed char) (115)))) - ((int) (struct_obj_4.member_2_3.member_1_0))) - (((!((int) (-7155))) || ((int) (-7))) << (((int) ((signed char) (-((int) (var_15))))) - (43)))) || (-((((int) ((signed char) (struct_obj_10.member_1_3))) - (((int) (-24985)) + ((int) (var_31)))) - ((+((int) (253))) + (((int) (-26639)) + ((int) (24190)))))))
+ {
+ short var_67 = (!((int) (((!((int) (6))) && (!((int) (21935)))) != ((int) ((unsigned short) (((int) (51591)) & ((int) (-41)))))))) << ((int) (((~((int) (-29500))) & (~(((int) (var_27)) & ((int) (struct_obj_6.member_5_2))))) <= ((int) (var_23))));
+ signed char var_68 = (short) ((~((int) ((unsigned short) (~((int) (var_28)))))) | (~((int) ((short) (~((int) (var_6)))))));
+ if (((((int) (struct_obj_7.member_1_1)) ^ ((((((int) (-12017)) + (2147483647)) >> (((int) (-5)) + (5))) >> ((((int) (struct_obj_4.member_2_7)) ^ ((int) (var_34))) - (9570))) >> ((int) ((~((int) ((short) (struct_obj_4.member_2_1.member_1_0)))) != (((int) ((signed char) (var_1))) | ((int) ((unsigned short) ((((int) (var_19)) & ((int) (struct_obj_1.member_5_2))) & (~((int) (-114))))))))))) + (2147483647)) >> ((((((int) (var_29)) & ((int) (var_8))) | ((int) ((unsigned short) (var_48)))) & ((~((int) (struct_obj_8.member_4_5))) << (((int) ((unsigned short) (struct_obj_8.member_4_6))) - (51692)))) << ((((((int) (49144)) << (((int) (struct_obj_5.member_1_1)) - (28946))) << (((-((int) ((signed char) ((((int) ((short) (-246))) ^ (((int) (var_30)) << (((int) (var_3)) - (49)))) || ((+((int) (var_9))) >> ((((int) (struct_obj_4.member_2_1.member_1_0)) | ((int) (53547))) - (53607))))))) + (20)) - (15))) ^ ((((int) (27896)) ^ ((int) (struct_obj_2.member_5_1))) << ((~((int) (var_56))) + (20190)))) - (100631155))))
+ {
+ unsigned short var_69 = ((int) (((int) (((int) ((((int) (struct_obj_3.member_5_1)) && ((int) (var_18))) < ((int) (((int) (14551)) <= ((int) (-206)))))) >= ((int) ((~((int) ((short) (struct_obj_4.member_2_1.member_1_0)))) != (((int) ((signed char) (var_1))) | ((int) ((unsigned short) ((((int) (var_19)) & ((int) (struct_obj_1.member_5_2))) & (~((int) (-114))))))))))) != (!(((((int) (-2718)) * ((int) (struct_obj_9.member_2_7))) + (2147483647)) >> (((int) ((unsigned short) (-122))) - (65411)))))) >> ((!((!((int) (-34))) && (!((int) (11439))))) || (((((int) (10371)) || ((int) (18010))) || (((int) (52917)) && ((int) (-118)))) || ((((int) (23)) || ((int) (15037))) && (((int) (93)) && ((int) (-12489))))));
+ var_70 = (signed char) (((((((int) (34812)) * ((int) (var_13))) / (((int) (struct_obj_1.member_5_1)) * ((int) (var_65)))) * (!(((int) (var_35)) * ((int) (62))))) * (-((int) ((~((int) ((short) (struct_obj_4.member_2_1.member_1_0)))) != (((int) ((signed char) (var_1))) | ((int) ((unsigned short) ((((int) (var_19)) & ((int) (struct_obj_1.member_5_2))) & (~((int) (-114))))))))))) ^ (-((int) ((signed char) ((((int) ((short) (-246))) ^ (((int) (var_30)) << (((int) (var_3)) - (49)))) || ((+((int) (var_9))) >> ((((int) (struct_obj_4.member_2_1.member_1_0)) | ((int) (53547))) - (53607))))))));
+ struct_obj_9.member_2_5 = (unsigned short) (((((-((int) ((signed char) ((((int) ((short) (-246))) ^ (((int) (var_30)) << (((int) (var_3)) - (49)))) || ((+((int) (var_9))) >> ((((int) (struct_obj_4.member_2_1.member_1_0)) | ((int) (53547))) - (53607))))))) ^ (((~((int) (44847))) + (2147483647)) >> (((int) ((short) (var_4))) - (3630)))) + (2147483647)) << (((int) ((unsigned short) ((~((int) (struct_obj_2.member_5_1))) | (~((int) (struct_obj_4.member_2_3.member_1_0)))))) - (65535))) ^ (~(~(((int) ((unsigned short) (var_41))) ^ (((int) (struct_obj_9.member_2_5)) << (((int) (struct_obj_9.member_2_4)) - (13536)))))));
+ unsigned short var_71 = (unsigned short) (~((int) ((signed char) ((((int) (15546)) << (((int) (58115)) - (58101))) >> ((~((int) (-17858))) - (17855))))));
+ unsigned short var_72 = ((int) ((((int) ((signed char) (((int) (var_53)) > ((int) (struct_obj_7.member_1_0))))) * ((int) (((int) (((int) (struct_obj_1.member_5_2)) <= ((int) (4016)))) > (((int) (23666)) % ((int) (-117)))))) <= (((int) ((((int) (struct_obj_4.member_2_6)) ^ ((int) (struct_obj_1.member_5_3))) <= ((int) (var_52)))) && (~((int) (58979)))))) * ((int) (struct_obj_1.member_5_0));
+ short var_73 = ((int) ((((~((int) (var_46))) | (((int) (struct_obj_9.member_2_1.member_1_1)) | ((int) (42879)))) | ((~((int) (var_55))) & (((int) (var_66)) & ((int) (struct_obj_10.member_1_3))))) <= ((int) ((~(!((int) (64290)))) > ((int) ((signed char) (((int) (struct_obj_1.member_5_3)) * ((int) (10324))))))))) >> (!((~(~((int) (var_30)))) >> (((((int) (struct_obj_9.member_2_4)) | ((int) (struct_obj_3.member_5_2))) & ((int) (struct_obj_9.member_2_0))) - (41371))));
+ unsigned short var_74 = (((int) (struct_obj_8.member_4_5)) + (2147483647)) << ((((((((int) ((short) (~((((int) ((short) ((short) (~(((int) (65)) << (((int) (-26039)) + (26049))))))) + (2147483647)) >> ((~((int) ((unsigned short) ((((int) (40110)) | ((int) (85))) << ((((int) ((short) (-45))) + (61)) - (14)))))) + (29723)))))) + (29)) - (26)) - (0)) - (0)) - (0)) - (1));
+ unsigned short var_75 = ((int) ((short) (23390))) + (((int) (((int) (((int) ((signed char) (struct_obj_10.member_1_3))) <= ((((int) ((short) ((short) (~(((int) (65)) << (((int) (-26039)) + (26049))))))) + (2147483647)) >> ((~((int) ((unsigned short) ((((int) (40110)) | ((int) (85))) << ((((int) ((short) (-45))) + (61)) - (14)))))) + (29723))))) < ((((int) (-41)) && ((int) (var_71))) && (!((int) (5)))))) ^ (((((int) (35578)) * ((int) (struct_obj_5.member_1_0))) * (((int) (var_69)) * ((int) (103)))) || ((int) (struct_obj_8.member_4_7))));
+ short var_76 = ((int) (-63)) + ((int) ((short) ((((int) (((int) (46788)) != ((int) (struct_obj_4.member_2_1.member_1_3)))) || (!((int) (-115)))) << (((((int) (struct_obj_4.member_2_1.member_1_1)) * ((int) (var_1))) - (((int) (20657)) + ((int) (struct_obj_9.member_2_0)))) + (1945793196)))));
+ short var_77 = +(((+(((int) (117)) * ((int) (-115)))) * ((((int) (57)) * ((int) (-8289))) / ((-((((int) (var_26)) || (((int) (1474)) && ((int) (var_34)))) || ((!((int) (95))) && (((int) (var_26)) || ((int) (7528)))))) - ((int) (struct_obj_4.member_2_0))))) * ((int) ((signed char) (var_65))));
+ }
+
+ var_78 = (short) (((((((int) (var_61)) | ((int) (var_15))) | (((int) (var_52)) & ((int) (5914)))) & (~((int) (struct_obj_2.member_5_0)))) | (~(~(((int) (31461)) | ((int) (var_24)))))) != ((int) ((signed char) ((~((int) (((int) (struct_obj_6.member_5_0)) < ((int) (struct_obj_9.member_2_6))))) * ((+((int) (21135))) && (!((int) (100))))))));
+ if (-((int) (struct_obj_8.member_4_0)))
+ {
+ signed char var_79 = var_12;
+ unsigned short var_80 = var_56;
+ short var_81 = !(((((int) (struct_obj_4.member_2_0)) || (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) && ((int) (45)))) || ((int) ((short) (((int) (struct_obj_1.member_5_1)) || ((int) (var_67)))))) || ((int) (var_31)));
+ var_54 = (short) ((((int) (var_54)) + (2147483647)) >> (((int) ((short) (((int) (var_62)) ^ ((int) (struct_obj_2.member_5_2))))) - (25016)));
+ var_82 = (unsigned short) ((~((int) (((~((int) (var_47))) * ((((int) (struct_obj_7.member_1_1)) + (2147483647)) >> (((int) (var_18)) - (75)))) <= ((!((int) (var_66))) % ((int) ((unsigned short) (8))))))) > (+((~((((int) (-22)) * ((int) (struct_obj_4.member_2_3.member_1_3))) / (((int) (-32289)) * ((int) (var_6))))) * (~((((int) (struct_obj_2.member_5_1)) * ((int) (var_4))) * (!((int) (var_7))))))));
+ short var_83 = (-(-((int) ((~((int) (struct_obj_10.member_1_3))) <= (((int) (struct_obj_8.member_4_2)) * ((int) (29850))))))) >> (((int) (((int) ((~((int) ((short) (struct_obj_4.member_2_1.member_1_0)))) != (((int) ((signed char) (var_1))) | ((int) ((unsigned short) ((((int) (var_19)) & ((int) (struct_obj_1.member_5_2))) & (~((int) (-114))))))))) <= (((int) (struct_obj_5.member_1_1)) * ((int) (var_51))))) & (((int) ((+((int) (struct_obj_9.member_2_1.member_1_0))) <= ((int) ((signed char) (21412))))) >> (((int) (var_13)) + (23934))));
+ signed char var_84 = !(-((int) (struct_obj_5.member_1_0)));
+ signed char var_85 = ((int) ((~((int) ((short) (struct_obj_4.member_2_1.member_1_0)))) != (((int) ((signed char) (var_1))) | ((int) ((unsigned short) ((((int) (var_19)) & ((int) (struct_obj_1.member_5_2))) & (~((int) (-114))))))))) * (((int) ((unsigned short) ((~((int) (var_15))) / (((int) (var_23)) * ((int) (var_15)))))) * (((int) ((short) (((int) (struct_obj_1.member_5_2)) * ((int) (struct_obj_3.member_5_0))))) * ((((int) (struct_obj_1.member_5_1)) * ((int) (struct_obj_4.member_2_6))) / (((int) (var_26)) * ((int) (60852))))));
+ short var_86 = -((int) (struct_obj_9.member_2_6));
+ }
+
+ short var_87 = ((int) ((short) ((((int) (((int) (-4380)) > ((int) (var_20)))) || (((int) (struct_obj_2.member_5_1)) >> (((int) (var_56)) - (20160)))) <= ((((int) (struct_obj_4.member_2_3.member_1_3)) && ((int) (struct_obj_2.member_5_2))) || (!((int) (struct_obj_6.member_5_2))))))) < (~(((int) (33)) || ((int) ((short) (((int) (var_12)) * ((int) (var_40)))))));
+ }
+
+ if ((~(((int) (((int) ((unsigned short) (83))) >= ((int) ((unsigned short) (29637))))) || ((((int) (10308)) && ((int) (struct_obj_3.member_5_0))) || (((int) (var_33)) || ((int) (var_28)))))) < ((int) ((signed char) (+((int) ((signed char) (((int) (var_2)) - ((int) (struct_obj_4.member_2_7)))))))))
+ {
+ signed char var_88 = (short) (!((int) ((unsigned short) (!(((int) (var_17)) || ((int) (struct_obj_8.member_4_7)))))));
+ if (((int) (((int) (((int) ((((int) (59)) && ((int) (var_47))) <= (((int) (17266)) - ((int) (3015))))) != ((int) (var_17)))) >= ((int) ((unsigned short) (struct_obj_4.member_2_7))))) ^ ((~((((int) (80)) >> (((int) (91)) - (69))) | ((int) ((unsigned short) (struct_obj_1.member_5_0))))) ^ (((~((int) (39542))) & ((int) (60573))) ^ ((((int) (-21393)) ^ ((int) (-10090))) << (((int) (-10709)) + (10717))))))
+ {
+ short var_89 = ~(!(((((int) (64831)) && ((int) (-102))) && (!((int) (-122)))) && (((int) ((signed char) (-26762))) && (((int) (92)) && ((int) (-82))))));
+ var_90 = (short) ((signed char) (((((int) ((short) (struct_obj_5.member_1_0))) ^ (((int) (11026)) | ((int) (1914)))) ^ (((int) (var_1)) ^ (((int) (struct_obj_10.member_1_3)) | ((int) (-10))))) & (((int) (struct_obj_8.member_4_9.member_1_0)) | ((int) (var_88)))));
+ signed char var_91 = ~(!(~(((int) ((signed char) (struct_obj_9.member_2_1.member_1_3))) & ((int) (var_9)))));
+ signed char var_92 = ~(~((~((((int) (63094)) | ((int) (struct_obj_4.member_2_2))) >> ((((int) (23595)) >> (((int) (struct_obj_4.member_2_0)) - (7603))) - (171)))) & ((int) ((unsigned short) (45532)))));
+ signed char var_93 = (signed char) (~(~((int) ((signed char) (struct_obj_3.member_5_3)))));
+ var_94 = (unsigned short) (((int) ((short) (((((int) (var_16)) ^ ((int) (56567))) & ((int) ((unsigned short) (struct_obj_7.member_1_0)))) | ((int) (var_8))))) & (~((((int) ((short) (var_5))) ^ (~((int) (var_32)))) | ((int) ((signed char) (((int) (var_34)) & ((int) (44163))))))));
+ unsigned short var_95 = ~((int) (var_52));
+ signed char var_96 = (~(!((int) ((!((int) (struct_obj_4.member_2_3.member_1_0))) > ((int) ((signed char) (19985))))))) <= ((int) ((unsigned short) (((-((int) (14064))) / (((int) (13781)) * ((int) (struct_obj_4.member_2_4)))) * ((((int) (-8630)) * ((int) (var_33))) / ((int) ((short) (struct_obj_2.member_5_2)))))));
+ unsigned short var_97 = ~(~(((int) (-7658)) | (!(((int) (-28143)) || ((int) (-16555))))));
+ }
+ else
+ {
+ short var_98 = (signed char) (~((int) ((signed char) ((((int) (-8)) * ((int) (38))) * (((int) (44)) * ((int) (-25899)))))));
+ short var_99 = ~((!((((int) (45811)) * ((int) (18866))) / (((int) (36128)) * ((int) (57))))) * ((int) (-15867)));
+ var_100 = (short) (struct_obj_6.member_5_3);
+ unsigned short var_101 = (short) (~(-((((int) (var_12)) * ((int) (struct_obj_4.member_2_4))) / (((int) (63446)) * ((int) (var_5))))));
+ unsigned short var_102 = ~(~(-(+((int) ((unsigned short) ((((int) (var_27)) + (((int) (struct_obj_4.member_2_7)) + ((int) (struct_obj_2.member_5_1)))) - (+((int) (22407)))))))));
+ unsigned short var_103 = ((int) (((((((int) (-103)) + (2147483647)) >> (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) + (103))) ^ ((int) ((unsigned short) (var_42)))) >> (((int) (struct_obj_7.member_1_0)) + (87))) < (+((int) ((unsigned short) ((((int) (var_27)) + (((int) (struct_obj_4.member_2_7)) + ((int) (struct_obj_2.member_5_1)))) - (+((int) (22407))))))))) | ((int) ((signed char) ((!(((int) (var_32)) * ((int) (struct_obj_8.member_4_9.member_1_2)))) << ((~((int) ((unsigned short) (121)))) + (152)))));
+ signed char var_104 = +(-((int) ((signed char) ((unsigned short) (((int) (-127)) > ((int) (-91)))))));
+ signed char var_105 = ((((-((int) (30661))) * ((int) ((unsigned short) (var_5)))) / ((int) ((signed char) (-((int) (struct_obj_2.member_5_3)))))) / (~(~(-(+((int) ((unsigned short) ((((int) (var_27)) + (((int) (struct_obj_4.member_2_7)) + ((int) (struct_obj_2.member_5_1)))) - (+((int) (22407))))))))))) * ((+((int) ((unsigned short) ((((int) (var_27)) + (((int) (struct_obj_4.member_2_7)) + ((int) (struct_obj_2.member_5_1)))) - (+((int) (22407))))))) * ((+(((int) (var_11)) * ((int) (struct_obj_8.member_4_3)))) * (((int) ((unsigned short) (struct_obj_1.member_5_2))) / (((int) (-95)) * ((int) (var_50))))));
+ }
+
+ var_106 = (short) ((signed char) (struct_obj_8.member_4_8));
+ unsigned short var_107 = ((((int) ((((int) (struct_obj_4.member_2_3.member_1_3)) % ((int) (43869))) < ((((int) (var_55)) + (2147483647)) >> (((int) (var_3)) - (28))))) / (((int) ((unsigned short) (var_29))) - ((int) ((signed char) (var_26))))) * ((int) ((signed char) ((short) (((int) (-65)) * ((int) (struct_obj_3.member_5_0))))))) != (+(~((int) ((signed char) ((((int) ((short) ((unsigned short) (struct_obj_1.member_5_1)))) / (-(((int) (var_32)) * ((int) (struct_obj_4.member_2_3.member_1_0))))) * ((~(-((int) (struct_obj_1.member_5_0)))) * ((int) (var_27))))))));
+ if (32515)
+ {
+ var_46 = (unsigned short) (!(((int) ((unsigned short) ((~((int) (var_3))) ^ (((int) (19146)) | ((int) (struct_obj_2.member_5_2)))))) & ((~(((int) (struct_obj_8.member_4_4)) ^ ((int) (var_2)))) & ((((int) (33293)) | ((int) (var_55))) ^ (~((int) (struct_obj_4.member_2_1.member_1_0)))))));
+ short var_108 = (short) ((((((int) (14)) & ((int) (var_53))) | (((int) (var_53)) & ((int) (var_19)))) | (~(~((int) (var_54))))) ^ (((((int) (-18302)) & ((int) (63))) & ((int) (struct_obj_1.member_5_2))) ^ (~((int) ((unsigned short) (8902))))));
+ unsigned short var_109 = (unsigned short) (+((int) ((+((int) ((unsigned short) (61136)))) != (-((int) ((signed char) (var_28)))))));
+ short var_110 = (signed char) (~(~((int) (struct_obj_4.member_2_5))));
+ var_40 = (signed char) ((((~((((int) (31124)) ^ ((int) (32575))) | ((((int) (-25599)) + (2147483647)) << ((((((((int) (43839)) - (43838)) - (0)) - (0)) - (0)) - (0)) - (1))))) + (2147483647)) << ((((~(((int) (56)) | ((int) (42861)))) + (2147483647)) << ((((((~((int) ((unsigned short) (29861)))) + (29886)) - (23)) - (0)) - (0)) - (1))) - (2147440759))) || ((int) ((short) (-(~((int) (((int) (struct_obj_9.member_2_2)) > ((int) (-28602)))))))));
+ unsigned short var_111 = ((int) ((signed char) (((int) ((((int) (var_14)) << (((int) (5053)) - (5042))) >= (~((int) ((unsigned short) (-(((int) (var_31)) * (!((int) (struct_obj_4.member_2_3.member_1_2)))))))))) & ((int) ((unsigned short) (4610)))))) << (((int) (var_20)) - (49510));
+ unsigned short var_112 = (unsigned short) (((((int) ((unsigned short) (var_7))) && (((int) (struct_obj_8.member_4_9.member_1_1)) && ((int) (var_11)))) && ((((int) (struct_obj_7.member_1_1)) || ((int) (var_17))) || (((int) (var_10)) || ((int) (24048))))) % (((int) ((unsigned short) (((int) (12332)) * ((int) (59))))) * (~(-((int) (var_17))))));
+ signed char var_113 = ~((((int) ((short) ((signed char) (44957)))) | ((~((int) (15636))) | (((int) (var_59)) ^ ((int) (var_109))))) & ((int) (13)));
+ short var_114 = ~((((~((int) (var_16))) | (~((int) (var_40)))) & (~(((int) (struct_obj_10.member_1_2)) & ((int) (struct_obj_8.member_4_9.member_1_0))))) ^ ((int) ((short) (((int) ((unsigned short) (struct_obj_8.member_4_2))) & (~((int) (7475)))))));
+ unsigned short var_115 = (-((int) (28145))) - (((((int) ((unsigned short) (25233))) + ((int) ((signed char) (110)))) - ((((int) (17997)) - ((int) (var_45))) + ((int) ((signed char) (29))))) + (((((int) (26576)) - ((int) (struct_obj_9.member_2_4))) - (((int) (var_47)) + ((int) (118)))) - (+((int) ((signed char) (-101))))));
+ }
+
+ }
+ else
+ {
+ unsigned short var_116 = ((((((int) (29480)) * ((int) (47))) * (~((int) (-106)))) * ((((int) (-5906)) * ((int) (var_47))) / (((int) (struct_obj_10.member_1_3)) * ((int) (var_49))))) * ((int) (var_17))) * (!((((int) (var_14)) * (((int) (var_22)) * ((int) (struct_obj_10.member_1_3)))) * ((((int) (9930)) * ((int) (-39))) / (((int) (var_50)) * ((int) (7597))))));
+ short var_117 = 23937;
+ var_37 = (signed char) (((int) ((((int) ((signed char) (((int) (struct_obj_4.member_2_1.member_1_3)) % ((int) (struct_obj_2.member_5_1))))) | ((int) (((int) ((unsigned short) (-10713))) >= (((int) (struct_obj_8.member_4_9.member_1_1)) || ((int) (struct_obj_4.member_2_1.member_1_1)))))) > (((int) ((unsigned short) (((~((((int) (var_15)) ^ ((int) (struct_obj_2.member_5_3))) | (((int) (-117)) & ((int) (struct_obj_4.member_2_0))))) & ((int) (var_9))) | ((int) (struct_obj_4.member_2_1.member_1_0))))) * ((int) (struct_obj_4.member_2_3.member_1_3))))) & ((((~((int) (var_21))) | ((int) ((signed char) (6873)))) | ((((int) (11866)) & ((int) (1866))) & (((int) (120)) | ((int) (51141))))) & ((~(((int) (var_23)) ^ ((int) (var_21)))) ^ (((int) (var_38)) & (~((int) (var_61)))))));
+ unsigned short var_118 = var_39;
+ short var_119 = (short) (((((int) ((signed char) (struct_obj_4.member_2_3.member_1_3))) || (!((int) (var_60)))) % ((int) (((int) (var_59)) != (((int) (var_42)) & ((int) (var_5)))))) - ((int) ((unsigned short) (+((int) (41572))))));
+ }
+
+ if ((short) ((((int) ((unsigned short) (145))) || (!((int) (struct_obj_8.member_4_8)))) || ((!(!((int) (52600)))) && (!(((int) (struct_obj_1.member_5_1)) || ((int) (-45)))))))
+ {
+ if (((int) (struct_obj_7.member_1_1)) || ((int) (var_14)))
+ {
+ short var_120 = (((int) (-25025)) * (((int) ((signed char) (((int) (var_41)) || ((int) (-6379))))) * ((int) ((((int) (struct_obj_2.member_5_1)) || ((int) (var_66))) >= ((int) (struct_obj_2.member_5_1)))))) != (((int) ((unsigned short) ((((int) (struct_obj_4.member_2_6)) % ((int) (var_58))) % (~((int) (var_27)))))) && (~((~((int) (14817))) | (((int) (struct_obj_9.member_2_6)) | ((int) (80))))));
+ unsigned short var_121 = ~((int) (40954));
+ unsigned short var_122 = (short) ((((int) ((signed char) (+((int) (38261))))) * ((int) ((unsigned short) (((int) (struct_obj_1.member_5_3)) * ((int) (var_14)))))) * ((!(-((int) (var_25)))) * ((((int) (var_21)) * ((int) (struct_obj_3.member_5_0))) * (!((int) (struct_obj_8.member_4_6))))));
+ var_123 = (unsigned short) (struct_obj_9.member_2_0);
+ signed char var_124 = ((int) ((+(~(((int) (1985)) * ((int) (104))))) <= ((int) (-17923)))) || ((~((((int) (struct_obj_8.member_4_1.member_3_0)) << (((int) (var_24)) + (4604))) >> (((int) ((signed char) (-29108))) - (70)))) | ((~((int) (46864))) | ((((int) (var_65)) + (2147483647)) >> (((((int) (struct_obj_10.member_1_3)) + (2147483647)) >> (((int) (var_25)) - (111))) - (32745)))));
+ unsigned short var_125 = ((int) (struct_obj_8.member_4_5)) * (+((+(~((int) (var_21)))) - ((int) ((unsigned short) ((unsigned short) (-12))))));
+ short var_126 = ((int) (struct_obj_4.member_2_1.member_1_0)) && ((((!((int) (60288))) || ((int) (96))) && ((((int) (-57)) || ((int) (19530))) || (((int) (17387)) && ((int) (48289))))) || (!((((int) (29335)) && ((int) (-23143))) || (((int) (-16)) && ((int) (9431))))));
+ short var_127 = (+((int) (((int) ((short) (((int) (struct_obj_1.member_5_1)) - ((int) (32370))))) < ((int) (60992))))) - ((int) ((((int) ((short) (((int) (var_8)) ^ ((int) (-54))))) & ((~((int) (32))) ^ (((int) (-29031)) | ((int) (126))))) != (((+(((int) (struct_obj_8.member_4_0)) ^ ((int) (struct_obj_5.member_1_0)))) + (2147483647)) >> ((~((int) (18))) || (((int) (struct_obj_4.member_2_2)) && ((int) (-39)))))));
+ unsigned short var_128 = !((int) ((((int) ((unsigned short) (~((int) (83))))) * ((int) ((((int) (-23)) ^ ((int) (62519))) >= ((int) (((int) (41099)) > ((int) (62255))))))) >= (~((~((int) (81))) * (((int) (-103)) * ((int) (23532)))))));
+ }
+ else
+ {
+ var_129 = (short) ((unsigned short) (var_20));
+ unsigned short var_130 = var_66;
+ unsigned short var_131 = ((int) ((unsigned short) (((~((int) (-45))) & (~((int) (30782)))) ^ ((((int) (52410)) ^ ((int) (-29797))) ^ (~((int) (23))))))) & ((((int) ((((int) (24037)) % ((int) (struct_obj_8.member_4_4))) <= ((int) ((short) (29870))))) | (((((int) (struct_obj_8.member_4_6)) + (2147483647)) >> (((int) (struct_obj_5.member_1_0)) + (105))) ^ (((int) (var_28)) - ((((+((int) (struct_obj_4.member_2_3.member_1_0))) - (+((int) (17696)))) - ((int) (var_22))) + (((int) ((short) ((unsigned short) (var_27)))) + (((int) (var_23)) + (-((int) (var_1))))))))) || (~((int) ((short) (~((int) (-31180)))))));
+ short var_132 = (+(((int) (var_58)) * ((((int) (struct_obj_1.member_5_3)) * ((int) (struct_obj_4.member_2_1.member_1_1))) / ((int) ((unsigned short) (struct_obj_8.member_4_1.member_3_1.member_1_2)))))) * ((int) ((signed char) ((!(((int) (var_28)) - ((((+((int) (struct_obj_4.member_2_3.member_1_0))) - (+((int) (17696)))) - ((int) (var_22))) + (((int) ((short) ((unsigned short) (var_27)))) + (((int) (var_23)) + (-((int) (var_1)))))))) * (!(((int) (var_28)) - ((((+((int) (struct_obj_4.member_2_3.member_1_0))) - (+((int) (17696)))) - ((int) (var_22))) + (((int) ((short) ((unsigned short) (var_27)))) + (((int) (var_23)) + (-((int) (var_1)))))))))));
+ signed char var_133 = ~(~(((((int) (var_31)) & ((int) (-6036))) | (((int) (struct_obj_8.member_4_1.member_3_0)) & ((int) (119)))) & ((int) ((short) (((int) (var_51)) & ((int) (struct_obj_6.member_5_1)))))));
+ signed char var_134 = ((int) (var_28)) - ((((+((int) (struct_obj_4.member_2_3.member_1_0))) - (+((int) (17696)))) - ((int) (var_22))) + (((int) ((short) ((unsigned short) (var_27)))) + (((int) (var_23)) + (-((int) (var_1))))));
+ unsigned short var_135 = (!((!(((int) (41271)) && ((int) (13731)))) || (((int) (25327)) || (!((int) (-8624)))))) && ((!((((int) (6099)) || ((int) (122))) && (((int) (39583)) || ((int) (32873))))) || (!((!((int) (16105))) || (((int) (var_28)) - ((((+((int) (struct_obj_4.member_2_3.member_1_0))) - (+((int) (17696)))) - ((int) (var_22))) + (((int) ((short) ((unsigned short) (var_27)))) + (((int) (var_23)) + (-((int) (var_1))))))))));
+ signed char var_136 = (signed char) (((int) (((int) ((((int) (var_35)) % ((int) (struct_obj_6.member_5_1))) <= ((int) ((signed char) (var_20))))) <= (~(((int) (-26722)) ^ ((int) (-5)))))) * ((!(((int) (struct_obj_2.member_5_2)) % ((int) (var_12)))) >> (!(!((int) (10583))))));
+ unsigned short var_137 = ~((int) ((signed char) (~(~((int) ((unsigned short) (var_8)))))));
+ }
+
+ signed char var_138 = ((~((((int) (struct_obj_9.member_2_4)) + ((int) (var_48))) - ((int) (((int) (25852)) > ((int) (32844)))))) || (((int) ((unsigned short) (((int) (12)) < ((int) (35004))))) + ((int) (20954)))) >= ((int) (struct_obj_4.member_2_6));
+ if (~(~(((int) (var_9)) ^ (~(((int) (var_56)) & ((int) (-97)))))))
+ {
+ unsigned short var_139 = ((int) (struct_obj_4.member_2_3.member_1_1)) < ((((((int) (59174)) ^ ((int) (-69))) & (~((int) (122)))) & ((((int) (24)) & ((int) (61565))) ^ (((int) (54007)) | ((int) (-60))))) & ((~(((int) (-1951)) | ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)))) & (~(((int) (var_55)) ^ ((int) (54148))))));
+ short var_140 = (((int) (struct_obj_3.member_5_1)) && ((int) ((unsigned short) ((((int) (var_18)) || ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))) > (((int) (23085)) & ((int) (-10998))))))) & (((!(((int) (var_64)) && ((int) (22)))) || ((!((int) (-372))) && (((int) (196)) || ((int) (28127))))) && (!((!((int) (var_28))) || (((int) (-3298)) || ((int) (86))))));
+ signed char var_141 = 32;
+ unsigned short var_142 = (short) (((int) (-91)) || (!(!(((int) (-2370)) || ((int) (-120))))));
+ var_143 = (signed char) ((unsigned short) ((~((int) (struct_obj_6.member_5_0))) & ((int) ((signed char) ((short) ((signed char) (struct_obj_4.member_2_6)))))));
+ short var_144 = 65519;
+ }
+
+ var_55 = (signed char) (((-((int) ((((int) (struct_obj_10.member_1_3)) - ((int) (struct_obj_8.member_4_9.member_1_1))) < ((((int) (struct_obj_5.member_1_3)) + (2147483647)) >> ((((int) (-2633)) + (2665)) - (21)))))) & (~(((int) (21384)) * (((int) (struct_obj_4.member_2_3.member_1_0)) * ((int) (struct_obj_4.member_2_1.member_1_3)))))) == ((~(~(((int) (var_11)) | ((int) (28869))))) | (((int) (struct_obj_10.member_1_2)) | (~(((int) (struct_obj_7.member_1_2)) & ((int) (var_31)))))));
+ short var_145 = (((int) (((int) ((unsigned short) (66))) == (~(((int) (-108)) & ((int) (var_50)))))) / (-(+((int) (((int) (var_49)) != ((int) (var_43))))))) == (((int) (var_60)) | (-(-(+((int) (-28574))))));
+ short var_146 = (((int) ((signed char) (((int) (((int) (struct_obj_6.member_5_2)) <= ((int) (var_51)))) && ((int) ((unsigned short) (var_23)))))) * ((int) (((int) (struct_obj_1.member_5_2)) == ((((int) (var_66)) & ((int) (37785))) & ((int) ((~((int) (var_15))) != (~((((((int) (struct_obj_4.member_2_7)) + (2147483647)) << ((((int) (var_30)) - (42704)) - (1))) | ((int) (var_18))) << (((int) ((unsigned short) (~((int) (struct_obj_3.member_5_3))))) - (26655)))))))))) % ((int) ((unsigned short) (((+((int) (var_20))) + (((int) (struct_obj_4.member_2_2)) * ((int) (var_52)))) + (+(+((int) (var_58)))))));
+ if ((signed char) ((((((int) (var_50)) ^ ((int) (58076))) ^ (((int) (struct_obj_2.member_5_1)) << (((int) (struct_obj_8.member_4_0)) - (17338)))) >> ((~(~((int) (var_8)))) - (14640))) << (((int) (((int) (((int) (27168)) < ((int) (var_45)))) < (((int) (41179)) & ((int) (-9862))))) >> (((int) (-56)) + (59)))))
+ {
+ unsigned short var_147 = var_7;
+ unsigned short var_148 = (((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_1)) + ((int) (-42))) - (((int) (struct_obj_8.member_4_9.member_1_2)) + ((int) (var_24)))))) - ((int) ((~((int) (var_15))) != (~((((((int) (struct_obj_4.member_2_7)) + (2147483647)) << ((((int) (var_30)) - (42704)) - (1))) | ((int) (var_18))) << (((int) ((unsigned short) (~((int) (struct_obj_3.member_5_3))))) - (26655))))))) % (((-(+((int) (struct_obj_2.member_5_0)))) >> ((((int) (19611)) << (((int) (7596)) - (7595))) >> (((int) ((short) (struct_obj_8.member_4_1.member_3_1.member_1_2))) + (90)))) % (-((int) (struct_obj_4.member_2_3.member_1_3))));
+ signed char var_149 = (signed char) (9177);
+ signed char var_150 = ~((((((int) (var_32)) >> (((int) (var_63)) - (21651))) >> ((((int) (var_52)) & ((int) (var_28))) - (9212))) << ((((int) ((short) (var_37))) << (((int) (var_59)) >> (((int) (struct_obj_8.member_4_0)) - (17332)))) - (924))) << ((~(~(((int) (struct_obj_1.member_5_1)) & ((int) (var_65))))) - (19726)));
+ short var_151 = ((int) (((int) ((~(~((int) (var_28)))) >= (((int) ((unsigned short) (45))) % ((int) ((unsigned short) (59243)))))) != ((int) ((unsigned short) (!((int) (2861))))))) && (-(((-((int) (struct_obj_6.member_5_0))) * ((int) (76))) / (~(~((int) (struct_obj_6.member_5_0))))));
+ var_152 = (short) ((short) ((!((((int) (-48)) && ((int) (var_29))) && (!((int) (27080))))) | ((int) ((signed char) (+(+((int) (var_47))))))));
+ short var_153 = ~(!(((int) ((~((int) (var_15))) != (~((((((int) (struct_obj_4.member_2_7)) + (2147483647)) << ((((int) (var_30)) - (42704)) - (1))) | ((int) (var_18))) << (((int) ((unsigned short) (~((int) (struct_obj_3.member_5_3))))) - (26655)))))) ^ ((int) ((short) (((int) (13313)) >> (((int) (4429)) - (4409)))))));
+ short var_154 = (signed char) (((int) ((signed char) (((~((int) (38068))) + (2147483647)) >> ((((int) (5010)) << ((((int) (-97)) + (120)) - (9))) - (82083818))))) & (((((int) (var_27)) >> (((int) (var_34)) + (88))) >> ((((int) (var_6)) ^ ((int) (struct_obj_4.member_2_1.member_1_0))) - (40569))) | ((int) (23074))));
+ }
+
+ }
+
+ short var_155 = ((~((int) ((signed char) ((short) (struct_obj_4.member_2_3.member_1_2))))) | (~(((((int) (var_8)) | ((int) (struct_obj_1.member_5_0))) + (2147483647)) << ((((int) (var_18)) << (((int) (struct_obj_2.member_5_3)) - (25447))) - (157696))))) > ((int) ((((!((int) (55608))) || (((int) (42069)) && ((int) (struct_obj_4.member_2_0)))) && (!((int) ((signed char) (struct_obj_8.member_4_1.member_3_1.member_1_0))))) == ((((int) (((int) (struct_obj_1.member_5_1)) <= ((int) (var_18)))) & ((int) (((int) (7701)) != ((int) (var_7))))) && ((int) ((((int) (struct_obj_9.member_2_2)) - ((int) (var_1))) <= (((int) (struct_obj_4.member_2_1.member_1_1)) ^ ((int) (struct_obj_10.member_1_3))))))));
+ if (((!((((int) (var_1)) || ((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) || (((int) (struct_obj_8.member_4_6)) || ((int) (var_49))))) && ((!(((int) (var_29)) || ((int) (95)))) && (!((int) ((short) (struct_obj_6.member_5_1)))))) || (!((!(((int) (var_48)) || ((int) (var_31)))) && (((int) ((unsigned short) (struct_obj_8.member_4_5))) && (!((int) (var_25)))))))
+ {
+ var_156 = (signed char) (+(((int) (struct_obj_4.member_2_2)) / (~((int) ((unsigned short) (~((int) (struct_obj_8.member_4_6))))))));
+ signed char var_157 = (short) (((int) (var_15)) << (((int) ((signed char) (((int) (struct_obj_8.member_4_9.member_1_0)) & ((int) (17017))))) >> ((((((int) (struct_obj_1.member_5_1)) << (((int) (var_39)) - (28162))) & ((int) (struct_obj_1.member_5_2))) - (55360)) - (15))));
+ signed char var_158 = ~((int) (struct_obj_9.member_2_7));
+ unsigned short var_159 = (((int) (((int) ((unsigned short) (((int) (var_14)) << ((int) (struct_obj_4.member_2_3.member_1_0))))) < (((int) (((int) (struct_obj_8.member_4_9.member_1_2)) > ((int) (5)))) * (((int) (-30137)) * ((int) (49178)))))) && (((int) ((short) (struct_obj_8.member_4_5))) & ((~((int) (var_39))) ^ (((int) (var_48)) & ((int) (struct_obj_1.member_5_0)))))) >> ((int) ((unsigned short) (!(((int) ((signed char) (42511))) & (((int) (struct_obj_8.member_4_2)) >> (((int) (struct_obj_4.member_2_3.member_1_2)) + (83)))))));
+ short var_160 = ((int) (((int) (30759)) < (~((int) ((short) (((int) (var_34)) ^ ((int) (struct_obj_8.member_4_1.member_3_0)))))))) <= ((-((int) ((((int) (-24352)) && ((int) (struct_obj_8.member_4_9.member_1_0))) < ((int) ((signed char) (struct_obj_3.member_5_2)))))) | (((((int) (struct_obj_8.member_4_6)) && ((int) (struct_obj_9.member_2_1.member_1_0))) ^ (((int) (-3094)) & ((int) (var_1)))) / ((int) ((signed char) (+((int) (var_42)))))));
+ short var_161 = (short) ((-((int) ((signed char) (((int) (struct_obj_8.member_4_5)) ^ ((int) (var_36)))))) > (((((int) (var_54)) & ((int) (-24453))) | (~((int) (struct_obj_9.member_2_1.member_1_3)))) | ((((int) (struct_obj_8.member_4_7)) | ((int) (var_159))) & (((int) (var_63)) & ((int) (var_13))))));
+ if (-((int) ((unsigned short) (!((int) (16141))))))
+ {
+ var_162 = (signed char) ((short) (19938));
+ var_38 = (signed char) (((int) ((signed char) ((((int) ((unsigned short) (struct_obj_4.member_2_3.member_1_3))) << ((((int) (var_16)) ^ ((int) (66))) - (7830))) & ((((int) (16)) << (((int) (28592)) - (28568))) ^ (((int) (14689)) ^ ((int) (-24415))))))) & ((int) (struct_obj_4.member_2_3.member_1_2)));
+ unsigned short var_163 = (signed char) (((~((int) ((unsigned short) (var_50)))) - ((((int) (55181)) >> (((int) (-105)) + (108))) | (((int) (50003)) << ((((int) (var_30)) - (42689)) - (15))))) & ((int) (struct_obj_8.member_4_0)));
+ unsigned short var_164 = struct_obj_10.member_1_3;
+ unsigned short var_165 = struct_obj_4.member_2_7;
+ unsigned short var_166 = ((int) (var_56)) >> ((int) (((~(((int) (var_33)) ^ ((int) (2184)))) & ((int) ((((int) (var_30)) ^ ((int) (13945))) != ((((int) (-25)) + (2147483647)) >> (((int) (struct_obj_1.member_5_1)) - (32568)))))) <= ((int) (struct_obj_4.member_2_7))));
+ }
+ else
+ {
+ short var_167 = (short) (~(((((int) (-125)) & ((int) (var_55))) | (((int) (30445)) | ((int) (var_14)))) | ((((int) (struct_obj_4.member_2_6)) | ((int) (struct_obj_3.member_5_1))) | (((int) (struct_obj_4.member_2_1.member_1_3)) ^ ((int) (42952))))));
+ unsigned short var_168 = (((int) ((unsigned short) ((~((int) (36216))) | ((int) (-29579))))) >> ((~((((int) (10544)) & ((int) (11868))) << ((((int) (26935)) | ((int) (struct_obj_8.member_4_1.member_3_0))) - (27566)))) + (5251073))) << ((((((~((int) (struct_obj_10.member_1_2))) ^ (((int) (77)) << (((int) (var_66)) - (65517)))) << ((((((int) (-78)) + (2147483647)) << (((int) (var_60)) - (21585))) << ((((int) ((signed char) (struct_obj_4.member_2_4))) + (15)) - (10))) - (2147483563))) | (~((int) ((signed char) (((int) (73)) >> (((int) (6327)) - (6305))))))) + (18)) - (13));
+ short var_169 = ((((int) (var_23)) & ((((int) (var_54)) + (2147483647)) << (((((((int) (-6568)) + (2147483647)) >> (((int) (-25044)) + (25060))) - (32766)) - (0)) - (1)))) >> (((int) ((signed char) ((signed char) (~((int) (32011)))))) + (12))) && (((!(((int) (var_11)) || ((int) (struct_obj_9.member_2_6)))) || ((!((int) (struct_obj_9.member_2_0))) || (((int) (struct_obj_4.member_2_3.member_1_2)) || ((int) (struct_obj_2.member_5_2))))) || (!((int) ((short) (((int) (-29488)) && ((int) (struct_obj_4.member_2_3.member_1_2)))))));
+ signed char var_170 = (unsigned short) (var_26);
+ signed char var_171 = !(((int) ((signed char) ((((int) (struct_obj_6.member_5_3)) - ((int) (var_65))) - (((int) (struct_obj_8.member_4_9.member_1_0)) << (((int) (struct_obj_4.member_2_2)) - (30774)))))) || (((int) (var_158)) * ((int) ((short) (((int) (var_157)) && ((int) (var_27)))))));
+ unsigned short var_172 = (~((int) ((signed char) ((((int) (13)) % ((int) (struct_obj_8.member_4_7))) > ((int) ((unsigned short) (-112))))))) >= (~((((int) (struct_obj_8.member_4_3)) ^ (((int) (var_155)) << (((int) (struct_obj_7.member_1_2)) + (146)))) >> ((~(((int) (var_46)) >> (((int) (struct_obj_2.member_5_2)) - (41436)))) + (80))));
+ short var_173 = -(-(-(-((int) (struct_obj_1.member_5_2)))));
+ }
+
+ if (((int) (((int) (((int) (struct_obj_2.member_5_2)) >= ((((int) (var_45)) | ((int) (15962))) | (((int) (struct_obj_9.member_2_6)) ^ ((int) (64811)))))) <= ((int) ((unsigned short) (~(((int) (var_39)) || ((int) (struct_obj_4.member_2_7)))))))) >> ((int) ((signed char) (((int) ((~((int) (struct_obj_8.member_4_8))) <= (((int) (struct_obj_2.member_5_1)) * ((int) (var_43))))) == (-(+((int) (22055))))))))
+ {
+ signed char var_174 = ((int) (var_47)) ^ (((((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_0)) >> (((int) (var_17)) - (32638))) % (((int) (var_3)) && ((int) (var_3)))))) * (((int) ((short) (!((int) (struct_obj_2.member_5_3))))) * ((((int) (var_12)) * ((int) (76))) / (((int) (struct_obj_2.member_5_3)) * ((int) (var_35)))))) + (~((int) (var_33)))) & ((int) (struct_obj_4.member_2_6)));
+ short var_175 = (~((((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_0)) >> (((int) (var_17)) - (32638))) % (((int) (var_3)) && ((int) (var_3)))))) * (((int) ((short) (!((int) (struct_obj_2.member_5_3))))) * ((((int) (var_12)) * ((int) (76))) / (((int) (struct_obj_2.member_5_3)) * ((int) (var_35)))))) + (~((int) (var_33))))) <= (((((int) (var_31)) & ((int) ((unsigned short) (43682)))) & ((int) ((short) (((int) (var_9)) | ((int) (var_18)))))) ^ (~(((int) (struct_obj_4.member_2_1.member_1_3)) ^ (~((int) (52103))))));
+ short var_176 = (((((((int) (-75)) ^ ((int) (31369))) + (2147483647)) >> (((int) ((unsigned short) (-29))) - (65506))) & ((int) (2146))) << (((((int) (var_2)) * ((int) (struct_obj_3.member_5_3))) / ((((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_0)) >> (((int) (var_17)) - (32638))) % (((int) (var_3)) && ((int) (var_3)))))) * (((int) ((short) (!((int) (struct_obj_2.member_5_3))))) * ((((int) (var_12)) * ((int) (76))) / (((int) (struct_obj_2.member_5_3)) * ((int) (var_35)))))) + (~((int) (var_33))))) * ((((int) (var_24)) * ((int) (var_47))) / (((int) (var_5)) * ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)))))) * ((int) ((unsigned short) ((((int) (27537)) / (((int) (-15573)) * ((int) (struct_obj_9.member_2_0)))) * (!(((int) (12)) * ((int) (struct_obj_8.member_4_0)))))));
+ unsigned short var_177 = ((((((int) (40535)) * ((int) (var_30))) * (!((int) (struct_obj_6.member_5_1)))) * ((((int) (var_50)) / ((int) (58121))) * (((int) (54878)) * ((int) (struct_obj_8.member_4_0))))) * ((((int) ((short) (53))) * (((int) (32)) * ((int) (var_175)))) * (((int) ((signed char) (19151))) * (~((int) (16207)))))) * ((int) (var_16));
+ var_178 = (short) ((~(~((int) ((signed char) (~((int) (4771))))))) >> ((((!(((int) (64904)) && ((int) (-98)))) * ((int) ((signed char) (~((int) (34931)))))) - (((int) (struct_obj_7.member_1_1)) & (((int) (((int) (struct_obj_9.member_2_0)) < ((int) (40)))) || (((int) (struct_obj_6.member_5_0)) % ((int) (struct_obj_5.member_1_1)))))) + (32)));
+ unsigned short var_179 = ~((int) ((unsigned short) (((((int) (var_174)) | ((int) (struct_obj_2.member_5_0))) | (((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)) ^ ((int) (struct_obj_8.member_4_7)))) ^ (~(~((int) (struct_obj_8.member_4_6)))))));
+ signed char var_180 = ((int) (((int) ((!((int) ((unsigned short) (47545)))) <= (~(~((int) (2410)))))) >= ((int) (((((int) (1)) ^ ((int) (13528))) | ((int) ((signed char) (var_65)))) == ((+((int) (var_175))) & ((int) ((unsigned short) (14219)))))))) <= (((int) ((signed char) (((int) (((int) (var_6)) <= ((int) (var_23)))) <= ((int) ((signed char) (var_58)))))) + (((((int) (struct_obj_4.member_2_1.member_1_1)) ^ ((int) (var_4))) ^ ((int) (struct_obj_9.member_2_1.member_1_3))) && ((((int) (-3265)) & ((int) (12497))) * ((int) (((int) (struct_obj_9.member_2_0)) == ((int) (struct_obj_9.member_2_1.member_1_1)))))));
+ signed char var_181 = (+((((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_0)) >> (((int) (var_17)) - (32638))) % (((int) (var_3)) && ((int) (var_3)))))) * (((int) ((short) (!((int) (struct_obj_2.member_5_3))))) * ((((int) (var_12)) * ((int) (76))) / (((int) (struct_obj_2.member_5_3)) * ((int) (var_35)))))) + (~((int) (var_33))))) + ((((~((int) (7403))) & (((int) (struct_obj_4.member_2_0)) ^ ((int) (var_58)))) & (((((int) ((signed char) ((((int) (struct_obj_4.member_2_3.member_1_0)) >> (((int) (var_17)) - (32638))) % (((int) (var_3)) && ((int) (var_3)))))) * (((int) ((short) (!((int) (struct_obj_2.member_5_3))))) * ((((int) (var_12)) * ((int) (76))) / (((int) (struct_obj_2.member_5_3)) * ((int) (var_35)))))) + (~((int) (var_33)))) & (((int) (struct_obj_8.member_4_5)) & ((int) (struct_obj_3.member_5_3))))) * (~((int) ((+((int) (struct_obj_8.member_4_7))) <= (((int) (-24292)) - ((int) (38418)))))));
+ var_46 = (unsigned short) (~(!((int) ((signed char) (((int) (((int) (55161)) < ((int) (var_36)))) + (+((int) (var_55))))))));
+ }
+ else
+ {
+ signed char var_182 = (~(~((~((int) (struct_obj_1.member_5_1))) & (((int) (13831)) | ((int) (struct_obj_4.member_2_1.member_1_0)))))) | (~(((((int) (97)) | ((int) (struct_obj_4.member_2_3.member_1_3))) & ((int) ((signed char) (var_4)))) & ((((int) (119)) ^ ((int) (-1))) | ((int) (struct_obj_9.member_2_0)))));
+ signed char var_183 = ~(((!(!((int) (var_20)))) | ((int) ((short) (((int) (struct_obj_6.member_5_1)) >> (((int) (12242)) - (12212)))))) || (~((((int) (var_32)) & ((int) (var_63))) ^ (((int) (29262)) & ((int) (var_3))))));
+ short var_184 = ((((int) ((signed char) ((unsigned short) (43)))) & (~(((int) (struct_obj_4.member_2_3.member_1_3)) ^ ((int) (52))))) ^ (~((int) (struct_obj_10.member_1_2)))) << (((int) (struct_obj_4.member_2_7)) + (9528));
+ unsigned short var_185 = ~((int) (struct_obj_3.member_5_1));
+ short var_186 = ((int) ((short) (-((((int) (struct_obj_8.member_4_5)) - ((int) (var_65))) - (((int) (28254)) - ((int) (struct_obj_6.member_5_3))))))) * ((+((-((int) (struct_obj_8.member_4_7))) + ((int) ((signed char) (struct_obj_4.member_2_3.member_1_3))))) + ((int) ((short) (struct_obj_4.member_2_1.member_1_3))));
+ short var_187 = struct_obj_5.member_1_3;
+ }
+
+ if (~((+(!((int) ((signed char) (struct_obj_9.member_2_1.member_1_0))))) * ((int) ((short) ((short) (~((int) (var_19))))))))
+ {
+ unsigned short var_188 = (~(-((int) (((int) ((unsigned short) (-23))) <= (((int) (struct_obj_4.member_2_1.member_1_0)) || ((int) (24497))))))) | ((+(~(((int) (var_43)) * ((int) (struct_obj_4.member_2_1.member_1_1))))) + ((int) (struct_obj_8.member_4_3)));
+ unsigned short var_189 = (unsigned short) ((~((~((int) (97))) & (+((int) ((unsigned short) (+(((int) (((int) (var_21)) < ((int) (var_19)))) / (+((int) (-23249)))))))))) | (((int) ((short) (-15924))) ^ ((((int) (31)) ^ ((int) (var_7))) ^ (~((int) (struct_obj_6.member_5_1))))));
+ signed char var_190 = ((((((int) (14001)) | ((int) (73))) & ((int) ((unsigned short) (12149)))) & ((((int) (-78)) | ((int) (39))) | (+((int) ((unsigned short) (+(((int) (((int) (var_21)) < ((int) (var_19)))) / (+((int) (-23249)))))))))) | ((int) (((int) (24297)) <= (+((int) ((unsigned short) (+(((int) (((int) (var_21)) < ((int) (var_19)))) / (+((int) (-23249))))))))))) != ((int) ((unsigned short) (18898)));
+ signed char var_191 = (~(((~((int) (-11939))) & (~((int) (var_26)))) >> (((((int) (struct_obj_4.member_2_6)) >> (((int) (10058)) - (10057))) & (((int) (struct_obj_9.member_2_1.member_1_3)) << (((int) (var_10)) - (21745)))) - (10531)))) | ((((~((int) (var_1))) | (((int) (struct_obj_6.member_5_2)) << (((int) (-15680)) + (15686)))) | (((int) ((signed char) (60447))) | (((int) (-11899)) & ((int) (var_15))))) & ((((int) (var_43)) >> ((~((int) (struct_obj_4.member_2_0))) + (7623))) ^ ((~((int) (struct_obj_7.member_1_0))) | (((int) (30163)) & ((int) (var_21))))));
+ signed char var_192 = ((!((int) ((unsigned short) (((int) (28)) && ((int) (var_40)))))) || (!((int) ((signed char) (((int) (var_48)) || ((int) (struct_obj_9.member_2_0))))))) ^ ((int) (((int) (((int) (-113)) <= ((((int) (12)) || ((int) (52))) ^ (((int) (2031)) * ((int) (8257)))))) == ((int) ((signed char) ((((int) (struct_obj_3.member_5_1)) & ((int) (var_11))) & (((int) (var_2)) ^ ((int) (struct_obj_8.member_4_4))))))));
+ signed char var_193 = 18614;
+ }
+
+ short var_194 = ~((((int) (47259)) ^ (+((int) ((unsigned short) (+(((int) (((int) (var_21)) < ((int) (var_19)))) / (+((int) (-23249))))))))) & ((((int) (57390)) << ((((int) (25700)) << ((int) (14))) - (421068788))) << (((int) (var_27)) - (15318))));
+ }
+
+ signed char var_195 = ((~(~(~((int) (struct_obj_8.member_4_9.member_1_0))))) ^ ((~(((int) (struct_obj_8.member_4_3)) ^ ((int) (8)))) & (((int) (-23)) | ((int) (5564))))) ^ (+(~((int) ((-((int) (118))) != ((int) (((int) (-117)) != ((int) (34786))))))));
+ if ((((~((((int) (struct_obj_8.member_4_2)) | ((int) (struct_obj_9.member_2_2))) & ((int) ((unsigned short) (var_11))))) + (2147483647)) >> (((!((int) (struct_obj_7.member_1_1))) && (((int) (-27411)) && ((int) (var_57)))) * (((int) (((int) (var_53)) > ((int) (struct_obj_8.member_4_0)))) * (-((int) (var_11)))))) & (((((int) (120)) & ((int) ((unsigned short) (struct_obj_8.member_4_1.member_3_0)))) & ((int) ((signed char) (-((int) (2523)))))) && (!((int) ((short) (((int) (var_1)) - ((int) (struct_obj_2.member_5_3))))))))
+ {
+ if ((~((int) ((short) ((((int) (-7247)) ^ ((int) (96))) & (((int) (115)) | ((int) (42355))))))) & ((((int) (63543)) & ((int) ((unsigned short) (((int) (17803)) ^ ((int) (11828)))))) | (((int) (-29)) | ((int) ((short) (~((int) (10016))))))))
+ {
+ short var_196 = var_1;
+ unsigned short var_197 = ((((int) ((unsigned short) (((int) (struct_obj_9.member_2_1.member_1_0)) ^ ((int) (struct_obj_7.member_1_1))))) | (((int) (struct_obj_9.member_2_1.member_1_0)) | (((int) (-51)) ^ ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))))) & (((((int) (110)) & ((int) (-28957))) | ((int) (struct_obj_9.member_2_1.member_1_0))) & ((~((int) (var_21))) & ((int) ((signed char) (-15740)))))) & ((~((~((int) (struct_obj_8.member_4_9.member_1_1))) & (((int) (var_38)) | ((int) (-4512))))) & (((int) ((signed char) (26344))) ^ (((int) (23010)) | ((int) (21555)))));
+ short var_198 = ((int) (((int) ((short) (-((int) (21555))))) <= ((int) (((int) ((((int) (59115)) || ((int) (73))) <= ((int) ((short) (var_1))))) <= (~(((int) (struct_obj_7.member_1_1)) * ((int) (var_15)))))))) <= ((int) ((((((int) (struct_obj_4.member_2_7)) || ((int) (var_42))) & ((int) (21555))) + ((int) ((unsigned short) (21555)))) <= ((int) (((int) ((unsigned short) (-((int) (var_57))))) != ((int) ((signed char) (~((int) (struct_obj_5.member_1_3)))))))));
+ var_39 = (unsigned short) (+((int) (21555)));
+ short var_199 = ((int) (((int) (struct_obj_6.member_5_3)) > (((((int) (55447)) - ((int) (121))) - (((int) (124)) + ((int) (23562)))) + ((int) (67))))) == ((int) (21555));
+ var_46 = (unsigned short) (-((int) (var_196)));
+ short var_200 = (-((int) (struct_obj_3.member_5_0))) - (~((int) (var_55)));
+ unsigned short var_201 = ((int) ((((((int) (var_65)) && ((int) (var_7))) && ((int) ((unsigned short) (29456)))) && ((((int) (-11627)) || ((int) (var_62))) || ((int) ((unsigned short) (struct_obj_8.member_4_4))))) <= ((int) ((((int) (((int) (39895)) == ((int) (struct_obj_4.member_2_0)))) - ((int) (((int) (18541)) <= ((int) (var_197))))) == ((((int) (-6609)) | ((int) (-118))) * (((int) (var_195)) >> (((int) (50558)) - (50551)))))))) < (((int) ((short) (((int) ((unsigned short) (var_5))) || (((int) (struct_obj_2.member_5_1)) && ((int) (var_43)))))) || (((!((int) (51194))) && (!((int) (41084)))) && (((int) ((signed char) (struct_obj_4.member_2_0))) || (!((int) (var_42))))));
+ signed char var_202 = ((~((int) ((short) (((int) (-6444)) | ((int) (17)))))) | ((int) ((signed char) ((((int) (var_49)) ^ ((int) (120))) | (((int) (struct_obj_2.member_5_2)) | ((int) (-10264))))))) ^ (((((int) ((short) (struct_obj_1.member_5_2))) & (((int) (var_34)) & ((int) (64379)))) | ((((int) (-20555)) & ((int) (struct_obj_8.member_4_3))) & (((int) (struct_obj_8.member_4_4)) & ((int) (20891))))) | (((((int) (struct_obj_2.member_5_3)) & ((int) (30905))) | ((int) (21555))) ^ (~(((int) (struct_obj_4.member_2_3.member_1_3)) & ((int) (var_52))))));
+ short var_203 = (!((((int) ((signed char) (~((!(((int) (27437)) && ((int) (-123)))) / (~((int) (((int) (var_31)) <= ((int) (var_26))))))))) * (((int) (23332)) * ((int) (var_23)))) / ((int) ((short) (((int) (43615)) * ((int) (var_56))))))) != (-((int) ((unsigned short) (((int) ((short) (struct_obj_9.member_2_6))) & (((int) (var_36)) ^ ((int) (var_45)))))));
+ }
+
+ var_49 = (signed char) (~(~(~(((~((int) (var_66))) + (2147483647)) << (((((int) (-6282)) | ((int) (var_4))) + (4231)) - (5))))));
+ if (((int) ((signed char) (~((((int) (var_54)) ^ ((int) (struct_obj_8.member_4_0))) ^ (~((int) (var_54))))))) & ((int) ((short) (((~((int) (20559))) | (~((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)))) & ((int) (-27))))))
+ {
+ signed char var_204 = ((~((int) (var_54))) ^ (((((int) (var_32)) & ((int) (var_11))) | (((int) (-113)) ^ ((int) (var_28)))) ^ (~(((int) (struct_obj_8.member_4_1.member_3_0)) & ((int) (var_51)))))) & ((int) ((unsigned short) ((unsigned short) (var_44))));
+ short var_205 = (signed char) ((+((int) ((short) (((int) (-7851)) + ((int) (struct_obj_5.member_1_1)))))) + ((int) ((short) ((((int) (5103)) - ((int) (var_22))) - (((int) (var_7)) - ((int) (struct_obj_10.member_1_0)))))));
+ short var_206 = (~((int) ((unsigned short) (~((int) ((short) (43004))))))) > ((int) ((signed char) (((int) ((short) (((int) (-4829)) | ((int) (struct_obj_9.member_2_5))))) >= ((int) (((int) (struct_obj_10.member_1_3)) <= ((int) ((unsigned short) (-29121))))))));
+ unsigned short var_207 = ~((int) (var_49));
+ short var_208 = (short) (((int) ((unsigned short) (~((int) ((short) (((int) (struct_obj_3.member_5_2)) ^ ((int) (var_18)))))))) ^ ((((((int) (20589)) >> (((int) (-20937)) + (20947))) ^ ((int) (47282))) | (~(~((int) (23))))) & (((((int) (struct_obj_3.member_5_1)) << (((int) (var_7)) - (42))) << (((int) (var_33)) >> (((int) (struct_obj_2.member_5_1)) - (25738)))) << (((int) ((short) (var_34))) + (89)))));
+ }
+
+ if (((int) (struct_obj_9.member_2_6)) << ((int) (((int) ((!((int) ((unsigned short) (var_43)))) <= ((int) (var_7)))) > (((int) (72)) ^ ((((int) (var_28)) & ((int) (24924))) | (~((int) (struct_obj_7.member_1_0))))))))
+ {
+ unsigned short var_209 = ~((((~((int) (18314))) | ((int) ((unsigned short) (var_14)))) & ((((int) (struct_obj_9.member_2_2)) & ((int) (struct_obj_8.member_4_9.member_1_0))) ^ (~((int) (-31087))))) ^ (((int) (80)) | ((((int) (struct_obj_8.member_4_9.member_1_0)) & ((int) (struct_obj_4.member_2_5))) ^ (((int) (47697)) | ((int) (53))))));
+ signed char var_210 = var_38;
+ unsigned short var_211 = ((int) ((unsigned short) ((~((int) (-10493))) < (!(-((int) (var_3))))))) <= (!(~((~((int) (var_36))) | (((int) (struct_obj_3.member_5_2)) | ((int) (struct_obj_4.member_2_3.member_1_3))))));
+ signed char var_212 = ((((int) ((signed char) (((int) (16621)) ^ ((int) (17647))))) | ((((int) (var_7)) | ((int) (-95))) | (((int) (var_64)) & ((int) (struct_obj_1.member_5_0))))) | (((int) (struct_obj_8.member_4_4)) ^ ((~((int) (-19306))) | (((int) (-8522)) ^ ((int) (7284)))))) ^ ((~(((int) ((short) (struct_obj_10.member_1_3))) ^ (((int) (struct_obj_5.member_1_3)) ^ ((int) (struct_obj_9.member_2_0))))) ^ (((int) (var_5)) | ((~((int) (35989))) | (((int) (125)) ^ ((int) (struct_obj_4.member_2_1.member_1_1))))));
+ signed char var_213 = (((int) (var_41)) & (((((int) (struct_obj_1.member_5_3)) ^ ((int) (6820))) ^ (~((int) (var_41)))) ^ (~(((int) (16070)) ^ ((int) (struct_obj_1.member_5_0)))))) ^ (~(((((int) (var_56)) << ((((int) (var_54)) + (24931)) - (19))) | (((int) (9)) & ((int) (46955)))) << (((~((int) ((signed char) (var_12)))) + (63)) - (19))));
+ short var_214 = ((!((((int) (var_41)) || ((int) (var_4))) || (!((int) (var_1))))) && (!(((int) (struct_obj_10.member_1_3)) || (((int) (21126)) || ((int) (var_210)))))) && ((((int) ((unsigned short) (var_42))) || ((int) ((short) (struct_obj_4.member_2_1.member_1_1)))) && ((int) (struct_obj_5.member_1_1)));
+ unsigned short var_215 = (((int) (struct_obj_7.member_1_2)) + (2147483647)) >> ((~(((int) (((int) (-30700)) != ((int) (struct_obj_10.member_1_2)))) - ((int) (var_58)))) || (~(((int) ((short) (4835))) ^ ((int) (struct_obj_9.member_2_1.member_1_0)))));
+ }
+
+ signed char var_216 = +((int) ((signed char) ((short) ((((int) (29926)) - ((int) (struct_obj_4.member_2_1.member_1_1))) + (-((int) (var_9)))))));
+ var_217 = (signed char) (~(~(-((~((int) (11848))) & (((int) (-110)) & ((int) (struct_obj_3.member_5_1)))))));
+ signed char var_218 = (~((~(~((int) (struct_obj_8.member_4_0)))) << ((((int) (5903)) ^ ((int) (var_10))) >> ((((int) (var_4)) & ((int) (-13690))) - (2545))))) > (-(-(~(~((int) (struct_obj_9.member_2_1.member_1_1))))));
+ unsigned short var_219 = (~((int) ((short) (((int) (((int) (var_195)) <= ((int) (struct_obj_1.member_5_1)))) | ((int) (-70)))))) <= ((int) ((unsigned short) ((unsigned short) ((((int) (-126)) & ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))) ^ (((int) (struct_obj_9.member_2_0)) ^ ((int) (var_19)))))));
+ signed char var_220 = (unsigned short) ((((int) (-23)) ^ (((int) ((unsigned short) (var_42))) | ((int) (-27960)))) & (((~((int) (62588))) ^ (((int) (struct_obj_4.member_2_2)) | ((int) (struct_obj_4.member_2_3.member_1_3)))) & (~((int) (struct_obj_10.member_1_2)))));
+ if (((((((int) (3)) && ((int) (var_54))) && (((int) (struct_obj_10.member_1_3)) || ((int) (struct_obj_8.member_4_8)))) || (!(((int) (struct_obj_8.member_4_6)) && ((int) (struct_obj_3.member_5_2))))) && (((int) ((signed char) (!((int) (struct_obj_4.member_2_1.member_1_0))))) || ((int) (32382)))) <= (((~(((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))) ^ ((int) ((signed char) (-21650))))) + (2147483647)) >> ((int) (((int) (((int) (((int) (struct_obj_8.member_4_4)) <= ((int) (-601)))) != (!((int) (struct_obj_8.member_4_0))))) > ((int) (((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))) < (!((int) (9829)))))))))
+ {
+ short var_221 = ((((-((int) (var_17))) - (((int) (var_30)) + ((int) (struct_obj_4.member_2_2)))) / (((int) (struct_obj_8.member_4_3)) - (((int) (var_5)) * ((int) (var_3))))) * (((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))) + (-(((int) (14421)) + ((int) (23698)))))) + ((((((int) (struct_obj_9.member_2_2)) + ((int) (25482))) - (((int) (-46)) - ((int) (struct_obj_5.member_1_1)))) / ((-((int) (var_216))) + (+((int) (64628))))) - ((((int) ((signed char) (-7))) - (+((int) (var_54)))) - ((int) (struct_obj_8.member_4_1.member_3_1.member_1_1))));
+ var_65 = (short) ((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159)))))))));
+ unsigned short var_222 = ((int) ((unsigned short) (((int) (var_63)) ^ (~((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))))))) & ((((int) ((signed char) (~(((int) (var_12)) & ((int) (109)))))) + (2147483647)) << (((((int) ((unsigned short) (var_27))) - (15320)) - (0)) - (1)));
+ unsigned short var_223 = ((((int) (struct_obj_4.member_2_3.member_1_2)) + (2147483647)) >> (((~(~((int) (var_18)))) << (((((int) (68)) | ((int) (struct_obj_4.member_2_1.member_1_3))) & (((int) (struct_obj_1.member_5_2)) ^ ((int) (-16242)))) + (58826))) - (5046248))) || (((int) ((unsigned short) ((-((int) (9390))) / (((int) (31664)) * ((int) (-70)))))) << ((((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))) | ((int) ((unsigned short) ((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159)))))))))))) - (15329)));
+ unsigned short var_224 = ((int) (((int) (-11433)) > ((int) (-13855)))) || (~(((int) ((short) (((int) (struct_obj_6.member_5_3)) && ((int) (struct_obj_4.member_2_3.member_1_3))))) ^ (~((int) (((int) (32)) <= ((int) (11233)))))));
+ signed char var_225 = (((~(((int) (-26)) | ((int) (-117)))) & ((((int) (111)) & ((int) (22599))) ^ (((int) (10345)) << ((((int) (-66)) + (88)) - (12))))) >> (((int) (-3619)) + (3621))) >> ((~((int) (struct_obj_6.member_5_1))) + (44653));
+ unsigned short var_226 = ((int) ((((~((int) (struct_obj_9.member_2_5))) | ((int) (22048))) & ((((int) (struct_obj_4.member_2_3.member_1_1)) & ((int) (var_4))) | (((int) (struct_obj_3.member_5_1)) | ((int) (27648))))) <= ((int) (((int) ((signed char) ((((int) (struct_obj_7.member_1_0)) + (2147483647)) >> (((int) (var_15)) - (38610))))) != ((int) ((signed char) ((short) (struct_obj_1.member_5_3)))))))) > (((int) (var_44)) >> ((int) ((unsigned short) (((int) (struct_obj_6.member_5_2)) >> ((~((int) (-18530))) - (18509))))));
+ signed char var_227 = ((int) (18755)) * ((int) (((int) ((unsigned short) ((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))))) > ((~(~((int) (37454)))) & ((~((int) (-7983))) | (((int) (-31547)) & ((int) (22310)))))));
+ signed char var_228 = !(~((int) ((((int) (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) != ((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)))) || (-((int) (42)))) >= ((int) ((short) (((int) (var_195)) ^ ((int) (struct_obj_8.member_4_4))))))));
+ unsigned short var_229 = (-(~(~(((int) (var_32)) & ((int) (-23)))))) && ((int) ((signed char) ((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159)))))))))));
+ }
+ else
+ {
+ short var_230 = (short) (struct_obj_4.member_2_5);
+ unsigned short var_231 = ((int) ((signed char) (((int) ((short) (((int) (struct_obj_9.member_2_1.member_1_3)) << (((int) (struct_obj_8.member_4_5)) + (1331))))) & ((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159)))))))))))) % ((int) ((short) ((unsigned short) (~((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159)))))))))))));
+ short var_232 = (unsigned short) ((((int) (49)) || ((!((int) (7))) || ((int) ((short) (struct_obj_3.member_5_1))))) && (!((int) (52603))));
+ signed char var_233 = (~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))));
+ var_234 = (short) ((((int) ((signed char) ((unsigned short) (~((int) (var_50)))))) & (~((int) ((short) (((int) (6)) | ((int) (var_40))))))) <= (((-((((int) (struct_obj_8.member_4_4)) & ((int) (struct_obj_9.member_2_4))) | ((int) (61009)))) + (2147483647)) >> (!(((~((~(((int) (32286)) ^ ((int) (99)))) ^ (~(((int) (6)) ^ ((int) (-93)))))) & ((int) ((short) (((((int) (43755)) ^ ((int) (struct_obj_1.member_5_0))) & (((int) (var_29)) ^ ((int) (124)))) ^ ((int) ((signed char) (~((int) (12159))))))))) * (((int) (struct_obj_1.member_5_3)) * ((int) (-53)))))));
+ signed char var_235 = !(!((int) ((signed char) ((!((int) (var_23))) && (((int) (var_2)) && ((int) (-40)))))));
+ short var_236 = ((~((int) (((int) (-9)) != ((int) (((int) (-6685)) <= ((int) (-51))))))) || ((((int) (((int) (var_9)) >= ((int) (struct_obj_9.member_2_1.member_1_0)))) || (((int) (var_233)) - ((int) (var_28)))) && ((int) (15198)))) || (((-(((int) (8864)) - ((int) (struct_obj_4.member_2_3.member_1_3)))) - ((((int) (-81)) - ((int) (struct_obj_4.member_2_0))) - ((int) ((signed char) (67))))) && (-((int) (((int) ((unsigned short) (29545))) < (((int) (var_54)) / ((int) (23)))))));
+ }
+
+ }
+
+ }
+
+ if ((((int) (-30504)) ^ (((int) (struct_obj_9.member_2_0)) & ((~((int) (16009))) & (((int) (59488)) ^ ((int) (-25101)))))) & ((int) ((unsigned short) ((signed char) ((((int) (-70)) ^ ((int) ((-127 - 1)))) ^ (~((int) (-18198))))))))
+ {
+ short var_237 = ((int) ((unsigned short) (~(~(((int) (32724)) & ((int) (-57))))))) > (~((int) (((int) (var_15)) <= (((int) ((unsigned short) (var_65))) + (((int) (var_16)) && ((int) (var_37)))))));
+ short var_238 = ((int) (-1594)) <= (((int) (var_37)) + ((int) (var_237)));
+ signed char var_239 = (((~(((((int) (var_65)) ^ ((int) (56889))) + (2147483647)) >> ((((int) (var_37)) << (((int) (struct_obj_9.member_2_4)) - (13527))) - (15204328)))) + (2147483647)) << (((int) ((unsigned short) ((((int) (-29413)) | ((int) (struct_obj_1.member_5_3))) | (~((int) (var_61)))))) - (36863))) | ((((((int) (var_22)) & ((int) (-10107))) << ((((int) (-7266)) | ((int) (struct_obj_10.member_1_0))) + (7232))) << (((int) ((signed char) (var_28))) & (((int) (var_238)) >> (((int) (struct_obj_9.member_2_5)) - (26951))))) << (((((int) ((short) (((int) (31750)) ^ ((int) (struct_obj_8.member_4_8))))) + (2147483647)) << ((((((~((int) ((signed char) (struct_obj_4.member_2_5)))) + (139)) - (25)) - (0)) - (0)) - (1))) - (2147463623)));
+ var_49 = (signed char) ((~((~((int) (struct_obj_1.member_5_0))) | ((~((int) (var_38))) ^ (~((int) (var_18)))))) * (~(((int) ((short) ((((int) (-74)) + (2147483647)) << (((((int) (-7673)) + (7685)) - (11)) - (1))))) | ((int) ((short) ((unsigned short) (struct_obj_8.member_4_1.member_3_1.member_1_1)))))));
+ if (var_30)
+ {
+ if ((-(((((int) (struct_obj_10.member_1_0)) * ((int) (4200))) * (~((int) (-32)))) * (~(-((int) (var_40)))))) >= ((int) (((~(((int) (7439)) & ((int) (var_33)))) && ((int) (((int) (var_27)) != (((int) (struct_obj_9.member_2_6)) << (((int) (43587)) - (43579)))))) < ((int) ((!((int) ((signed char) (struct_obj_8.member_4_5)))) >= ((~((int) (9170))) & (((int) (18966)) & ((int) (var_36)))))))))
+ {
+ var_240 = (signed char) ((+(((((int) (39678)) + ((int) (-20537))) + (((int) (-20330)) - ((int) (-35)))) * ((+((int) (-32053))) + ((int) (-29363))))) >> ((((int) (var_8)) || ((!((int) (22))) || (((int) (53763)) || ((int) (11024))))) && (((((int) (struct_obj_9.member_2_2)) && ((int) (var_20))) || ((int) (62563))) || (((int) ((short) (-28548))) && ((int) (struct_obj_9.member_2_5))))));
+ var_241 = (unsigned short) (-((int) ((((((int) (90)) / ((int) (var_14))) >> ((-((int) (-3575))) - (3547))) | ((int) ((((int) (var_10)) * ((int) (61679))) > (((int) (var_3)) % ((int) (-39)))))) < (((int) (((int) ((signed char) (21447))) <= ((int) (((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)) > ((int) (struct_obj_9.member_2_2)))))) / (~(((int) (5083)) | ((int) (var_62))))))));
+ short var_242 = ((int) (((int) ((signed char) ((((int) (-123)) && ((int) (20950))) < ((int) (((int) (26747)) < ((int) (-37))))))) >= ((int) ((((int) (58514)) && ((int) (-20862))) != (!(!((int) (struct_obj_10.member_1_3)))))))) % (((((int) ((signed char) (var_55))) * (~((int) (var_40)))) % (~(((int) (struct_obj_5.member_1_3)) + ((int) (19833))))) ^ (~((((int) (6964)) || ((int) (struct_obj_5.member_1_0))) & ((int) ((short) (var_62))))));
+ unsigned short var_243 = +((((int) ((unsigned short) (+((int) (struct_obj_4.member_2_7))))) / ((-((int) (struct_obj_9.member_2_1.member_1_0))) * (+((int) (struct_obj_9.member_2_1.member_1_1))))) * (+((int) ((short) (+((int) (23962)))))));
+ unsigned short var_244 = ((int) ((((int) ((unsigned short) (~((int) (var_54))))) ^ (~(((int) (var_38)) ^ ((int) (struct_obj_8.member_4_6))))) >= ((int) ((short) (((int) (25080)) >> ((((int) (var_21)) * ((int) (struct_obj_8.member_4_8))) + (3109978))))))) < ((int) (struct_obj_9.member_2_4));
+ struct_obj_9.member_2_2 = (unsigned short) (((int) (((int) (((int) (var_33)) >= ((~((int) (27357))) | ((int) (58514))))) < ((((((int) (-24728)) + (2147483647)) >> ((((int) (-12450)) + (12482)) - (29))) >> ((((int) (57)) * ((int) (14104))) - (803923))) / ((int) (((int) (58514)) != ((int) (((int) (struct_obj_4.member_2_0)) != ((int) (struct_obj_8.member_4_5))))))))) != ((int) ((unsigned short) ((((int) ((signed char) (((int) (48)) | ((int) (var_59))))) + (2147483647)) << (((~(((int) (struct_obj_4.member_2_7)) & ((int) (var_239)))) + (102)) - (26))))));
+ signed char var_245 = ((int) ((signed char) (-22439))) << ((((int) ((signed char) (((int) (var_22)) >> (((int) (var_33)) - (40281))))) / ((int) (25526))) || ((((int) ((short) (var_60))) / (((int) (-53)) * ((int) (24333)))) * ((((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)) * ((int) (struct_obj_6.member_5_0))) / (((int) (7947)) * ((int) (struct_obj_9.member_2_4))))));
+ var_57 = (signed char) ((short) (~((((int) ((unsigned short) (struct_obj_8.member_4_1.member_3_1.member_1_0))) | (((int) (struct_obj_6.member_5_2)) | ((int) (-127)))) ^ ((~((int) (-18008))) & (((int) (var_7)) & ((int) (var_1)))))));
+ signed char var_246 = (((!(((int) (-31124)) && ((int) (42538)))) / ((((int) (-26184)) & ((int) (-6497))) | (((int) (1782)) & ((int) (111))))) ^ (-((int) ((unsigned short) (((int) (10177)) > ((int) (8727))))))) - (-((int) (((int) (-72)) < (((int) ((unsigned short) (63))) ^ (((int) (-13275)) & ((int) (-32755)))))));
+ signed char var_247 = ((int) (((int) ((signed char) ((~((int) (var_44))) || ((int) ((signed char) (59533)))))) < ((int) (((-((int) (var_11))) & (((int) (-951)) ^ ((int) (struct_obj_8.member_4_9.member_1_1)))) != ((((int) (37950)) >> (((int) (19587)) - (19587))) && ((int) (((int) (24323)) == ((int) (var_41))))))))) >> ((int) (((!((int) (struct_obj_9.member_2_4))) && ((!((int) (-25737))) && (((int) (var_59)) || ((int) (struct_obj_9.member_2_1.member_1_0))))) == ((int) (((((int) (var_40)) | ((int) (46921))) | ((int) (struct_obj_4.member_2_3.member_1_2))) <= ((int) ((!((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) <= (((int) (119)) & ((int) (-31)))))))));
+ }
+
+ if ((-((int) ((short) ((signed char) ((short) (var_20)))))) <= (((int) (((((int) (struct_obj_8.member_4_1.member_3_0)) ^ ((int) (struct_obj_9.member_2_1.member_1_0))) << ((((int) (58)) ^ ((int) (var_45))) + (128))) == ((int) (var_31)))) ^ ((int) (((((int) (struct_obj_1.member_5_1)) | ((int) (37360))) | (~((int) (var_5)))) <= ((int) (8))))))
+ {
+ unsigned short var_248 = (unsigned short) (((((int) (struct_obj_4.member_2_3.member_1_2)) * ((int) ((short) (26360)))) / (((int) ((signed char) (8410))) * (((int) (957)) * ((int) (16064))))) * (-((-((int) (1))) * ((int) ((unsigned short) (-15383))))));
+ short var_249 = (signed char) (((((int) ((short) ((((int) (-15020)) + (2147483647)) << (((int) (var_12)) - (29985))))) + (2147483647)) << ((((((int) (var_25)) | ((int) (struct_obj_7.member_1_1))) ^ (((int) (var_7)) ^ ((int) (struct_obj_2.member_5_3)))) + (31452)) - (3))) << (((int) (106)) - (106)));
+ short var_250 = (signed char) ((~((((int) (var_249)) * ((int) (26))) * ((int) ((signed char) (var_44))))) * (~((int) (-6112))));
+ short var_251 = ~((int) ((short) (((((int) (var_60)) * ((int) (var_14))) * ((int) ((signed char) (var_35)))) * (-(((int) (struct_obj_8.member_4_3)) / ((int) (var_44)))))));
+ short var_252 = (~((int) ((((int) ((unsigned short) (68))) ^ (~((int) (28040)))) >= ((int) ((signed char) ((signed char) (struct_obj_8.member_4_0))))))) * ((!((((int) (var_8)) || ((int) (struct_obj_9.member_2_1.member_1_3))) && ((int) ((short) (var_59))))) && (!((((int) (21061)) && ((int) (-24998))) && (((int) (var_51)) || ((int) (var_9))))));
+ short var_253 = ((int) ((signed char) (var_48))) <= ((int) (struct_obj_8.member_4_6));
+ }
+ else
+ {
+ unsigned short var_254 = ((((((int) (102)) * ((int) (15365))) / (-((int) (-17680)))) * (-(((int) (-27940)) * ((int) (-40))))) / (((int) ((short) (-63))) * (~(((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)) * ((int) (var_58)))))) & ((int) ((((int) (var_22)) + (((int) (31276)) & (~((int) (-102))))) < ((int) (((int) (struct_obj_4.member_2_6)) > ((int) ((short) (((int) (var_58)) && ((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)))))))));
+ signed char var_255 = +((int) (var_52));
+ short var_256 = var_7;
+ short var_257 = (((int) ((signed char) ((short) ((unsigned short) (struct_obj_9.member_2_5))))) >> ((int) ((((int) (35251)) / ((int) ((unsigned short) (var_255)))) <= ((int) ((unsigned short) (((int) (struct_obj_9.member_2_6)) > ((int) (var_42)))))))) < ((int) (var_52));
+ struct_obj_9.member_2_6 = (unsigned short) (((((int) ((short) (((int) (struct_obj_4.member_2_7)) - ((int) (13943))))) + (-(-((int) (-16676))))) + (((int) (-38)) - ((-((int) (struct_obj_9.member_2_1.member_1_1))) + (-((int) (69)))))) ^ ((int) ((signed char) ((~(((int) (-28)) ^ ((int) (var_254)))) | ((int) ((unsigned short) (((int) (-28119)) ^ ((int) (-71)))))))));
+ unsigned short var_258 = (~((!((int) ((signed char) (11992)))) || ((((int) (15514)) && ((int) (-73))) || (((int) (26696)) && ((int) (-5402)))))) > ((((int) ((short) ((unsigned short) ((signed char) (var_63))))) + (2147483647)) << ((((((int) ((short) (~(~((int) (-81)))))) + (103)) - (21)) - (0)) - (1)));
+ signed char var_259 = (short) ((((((int) (struct_obj_8.member_4_9.member_1_0)) * ((int) (var_16))) - ((int) (var_7))) + (+(((int) (struct_obj_4.member_2_7)) - ((int) (struct_obj_5.member_1_3))))) * ((int) (15489)));
+ var_260 = (signed char) ((unsigned short) (((int) (((((int) (var_58)) >> (((int) (struct_obj_4.member_2_2)) - (30767))) >> ((((int) (var_16)) << ((int) (var_254))) - (7881))) > ((int) (-17)))) / (((int) (((int) ((unsigned short) (22400))) != (((int) (struct_obj_8.member_4_4)) & ((int) (-7838))))) ^ ((int) ((signed char) (~((int) (var_255))))))));
+ }
+
+ if ((signed char) ((short) (((((int) (-10196)) ^ ((int) (var_39))) ^ ((int) ((signed char) (19637)))) & ((int) ((unsigned short) (((int) (33)) ^ ((int) (var_14))))))))
+ {
+ signed char var_261 = ((int) ((signed char) (~((int) ((short) (((int) (9625)) ^ ((int) (var_66)))))))) && (((int) (((~((int) (struct_obj_4.member_2_3.member_1_3))) ^ (((int) (var_14)) | ((int) (var_64)))) <= ((int) ((unsigned short) (-((int) (41740))))))) | ((int) (struct_obj_2.member_5_2)));
+ unsigned short var_262 = struct_obj_8.member_4_6;
+ short var_263 = struct_obj_8.member_4_9.member_1_2;
+ signed char var_264 = struct_obj_6.member_5_2;
+ signed char var_265 = (unsigned short) (~(-(-((int) (((int) (47121)) > ((int) (30366)))))));
+ unsigned short var_266 = -((int) ((signed char) (((((int) (-9)) * ((int) (struct_obj_6.member_5_1))) / (((int) (var_61)) * ((int) (var_11)))) * ((int) ((signed char) ((short) (48373)))))));
+ short var_267 = (((int) (var_46)) & (~((~((int) (struct_obj_8.member_4_3))) | ((int) ((unsigned short) (29846)))))) / (((int) ((short) (((int) ((unsigned short) (var_51))) || (((int) (struct_obj_8.member_4_4)) && ((int) (var_62)))))) && (((int) ((signed char) ((signed char) (-32)))) && ((((int) (var_8)) || ((int) (struct_obj_4.member_2_3.member_1_0))) && ((int) (-103)))));
+ var_268 = (signed char) (((int) (var_21)) - ((-((((int) (struct_obj_8.member_4_9.member_1_1)) - ((int) (var_14))) + (-((int) (var_17))))) + ((int) (struct_obj_9.member_2_5))));
+ unsigned short var_269 = (~((int) ((~((int) ((unsigned short) (~((~((int) (var_27))) & (((int) (var_8)) & ((int) (-26607)))))))) != (+(!((int) (31000))))))) * (((int) (((int) (256)) >= ((int) (9376)))) % (((((int) (6933)) ^ ((int) (43243))) & (((int) (21486)) >> (((int) (-17065)) + (17068)))) << ((((int) ((short) (100))) & ((int) ((signed char) (-13)))) - (95))));
+ signed char var_270 = (short) (((int) (((((int) (35227)) && ((int) (var_61))) && (!((int) (14283)))) > ((int) ((((int) (15621)) ^ ((int) (24148))) <= (((int) (struct_obj_8.member_4_9.member_1_2)) || ((int) (11653))))))) < (-((int) ((short) (((int) (struct_obj_5.member_1_3)) | ((int) (-10)))))));
+ }
+ else
+ {
+ unsigned short var_271 = (~((int) ((unsigned short) ((((int) (var_17)) & ((int) (var_4))) ^ (((int) (13016)) & ((int) (struct_obj_2.member_5_0))))))) & ((!(~(!((int) (var_17))))) / ((((int) ((signed char) (var_35))) ^ (~((int) (struct_obj_4.member_2_3.member_1_1)))) & ((~((int) (var_12))) | ((((int) (-29314)) + (2147483647)) << ((((int) (62)) - (61)) - (1))))));
+ short var_272 = ((int) ((unsigned short) (((~((int) (84))) | (~((int) (110)))) & (~(((int) (115)) | ((int) (-76))))))) - ((int) (var_23));
+ signed char var_273 = (signed char) ((((((int) (-16844)) | ((int) (17775))) ^ (((int) (7963)) | ((int) (12142)))) | ((~((int) (15627))) ^ (((int) (26739)) ^ ((int) (-125))))) && (((int) (((int) (((int) (var_24)) <= ((-((int) (var_16))) * ((int) ((short) (var_34)))))) < ((int) (struct_obj_3.member_5_3)))) | ((int) (((int) ((signed char) (~(((int) (var_4)) + ((int) (25973)))))) <= ((int) (-123))))));
+ struct_obj_8.member_4_1.member_3_1.member_1_0 = (signed char) (~((int) ((unsigned short) (+((int) ((short) ((short) (var_62))))))));
+ signed char var_274 = (-(((int) ((~((int) (var_15))) <= ((int) ((signed char) (var_271))))) % (~(~((int) (var_28)))))) * ((((int) (((int) (((int) (var_24)) <= ((-((int) (var_16))) * ((int) ((short) (var_34)))))) < ((int) (struct_obj_3.member_5_3)))) | ((int) (((int) ((signed char) (~(((int) (var_4)) + ((int) (25973)))))) <= ((int) (-123))))) ^ ((~(((int) (-19317)) & ((int) (65)))) & (!((int) (((int) (8677)) <= ((int) (12375)))))));
+ short var_275 = ((~(((int) (((((int) (var_65)) + (2147483647)) >> (((int) (-16890)) + (16891))) != (~((int) (17071))))) % ((int) ((unsigned short) (~((int) (var_38))))))) + (2147483647)) >> (((int) ((unsigned short) (-(((int) (struct_obj_9.member_2_1.member_1_3)) * ((int) (struct_obj_9.member_2_2)))))) && ((~(((int) (struct_obj_8.member_4_9.member_1_0)) * ((int) (var_46)))) & ((int) (struct_obj_4.member_2_0))));
+ signed char var_276 = (((((int) (((int) (((int) (var_24)) <= ((-((int) (var_16))) * ((int) ((short) (var_34)))))) < ((int) (struct_obj_3.member_5_3)))) | ((int) (((int) ((signed char) (~(((int) (var_4)) + ((int) (25973)))))) <= ((int) (-123))))) || (-(~((int) (51098))))) % (((((int) (struct_obj_4.member_2_7)) & ((int) (-112))) & ((int) ((short) (25098)))) ^ ((~((int) (-101))) | (((int) (var_28)) & ((int) (-7003)))))) * ((int) ((short) (((int) ((-((int) (27204))) != (-((int) (63928))))) || ((((int) (-43)) * ((int) (-26382))) / (((int) (83)) * ((int) (14127)))))));
+ short var_277 = (~((int) ((short) (((int) (((int) (((int) (var_24)) <= ((-((int) (var_16))) * ((int) ((short) (var_34)))))) < ((int) (struct_obj_3.member_5_3)))) | ((int) (((int) ((signed char) (~(((int) (var_4)) + ((int) (25973)))))) <= ((int) (-123)))))))) || (~((int) (var_56)));
+ signed char var_278 = (~((int) ((signed char) ((((int) (var_56)) ^ ((int) (var_64))) ^ (((int) (struct_obj_1.member_5_2)) & ((int) (struct_obj_8.member_4_7))))))) >= (((int) (((int) (((int) (var_24)) <= ((-((int) (var_16))) * ((int) ((short) (var_34)))))) < ((int) (struct_obj_3.member_5_3)))) | ((int) (((int) ((signed char) (~(((int) (var_4)) + ((int) (25973)))))) <= ((int) (-123)))));
+ }
+
+ short var_279 = (unsigned short) (((+((int) (var_1))) + ((int) ((signed char) (~((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)))))) / (((int) (struct_obj_9.member_2_5)) && (~((int) ((signed char) (struct_obj_7.member_1_1))))));
+ if (~(~((int) ((unsigned short) (~(((int) (43)) >> (((int) (39844)) - (39841))))))))
+ {
+ short var_280 = (-(-(!((int) (16816))))) > ((((((int) (-20572)) | ((int) (struct_obj_8.member_4_0))) & (((int) (struct_obj_9.member_2_1.member_1_3)) | ((int) (30439)))) & ((((int) (-98)) ^ ((int) (-27720))) | (((int) (struct_obj_2.member_5_2)) & ((int) (7077))))) << (((int) (var_28)) - (13388)));
+ signed char var_281 = (short) ((signed char) (!(!(((int) (17428)) || ((int) (27105))))));
+ unsigned short var_282 = (((-(((int) (56239)) | ((int) (4)))) * ((int) (((int) (((int) (23297)) <= ((int) (-220)))) > (((int) (-17097)) * ((int) (-121)))))) || ((int) (((int) (-14340)) != ((int) (((int) (20335)) < (((int) (59459)) && ((int) (-107)))))))) - (((((int) (((~(-((int) (217)))) >> (((int) (-24993)) + (25001))) <= (!((int) ((~((int) (23529))) < (((int) (105)) + ((int) (-6170)))))))) >> ((((int) (-54)) ^ ((int) ((signed char) ((unsigned short) (((int) (-3615)) ^ ((int) (struct_obj_4.member_2_1.member_1_0))))))) - (115))) & ((int) ((unsigned short) (((int) (-87)) & ((int) (-83)))))) && ((int) (((int) (-2)) != (+(((int) (17715)) & ((int) (22)))))));
+ unsigned short var_283 = ((~(~((int) ((short) (40109))))) | ((int) (57193))) ^ (((~((int) ((signed char) (var_239)))) ^ ((((int) (1415)) & ((int) (13531))) | (((int) (struct_obj_3.member_5_2)) | ((int) (-7807))))) & (((~((int) (23824))) ^ (~((int) (-50)))) & ((int) (-23004))));
+ var_284 = (short) (!((int) ((short) ((((int) (53609)) ^ ((int) (((int) (var_29)) != ((int) (var_26))))) >= ((((int) (var_48)) / ((int) (11584))) | (((int) (-96)) ^ ((int) (23703))))))));
+ struct_obj_8.member_4_5 = (short) ((short) (((~(((int) ((unsigned short) ((~(((int) (((~(-((int) (217)))) >> (((int) (-24993)) + (25001))) <= (!((int) ((~((int) (23529))) < (((int) (105)) + ((int) (-6170)))))))) >> ((((int) (-54)) ^ ((int) ((signed char) ((unsigned short) (((int) (-3615)) ^ ((int) (struct_obj_4.member_2_1.member_1_0))))))) - (115)))) ^ ((int) ((short) (((int) ((signed char) (18462))) | (((int) (var_30)) & ((int) (var_5))))))))) & ((int) (-23)))) + (2147483647)) << (((((int) (struct_obj_9.member_2_1.member_1_3)) | (((int) (52011)) | ((int) (29618)))) >> (((((int) (-17)) ^ ((int) (struct_obj_8.member_4_6))) | (((int) (struct_obj_2.member_5_2)) & ((int) (46991)))) - (46995))) - (4091))));
+ }
+
+ unsigned short var_285 = (signed char) (~(((int) ((signed char) (((int) (48619)) * ((int) (struct_obj_9.member_2_2))))) * (((int) (((~(-((int) (217)))) >> (((int) (-24993)) + (25001))) <= (!((int) ((~((int) (23529))) < (((int) (105)) + ((int) (-6170)))))))) >> ((((int) (-54)) ^ ((int) ((signed char) ((unsigned short) (((int) (-3615)) ^ ((int) (struct_obj_4.member_2_1.member_1_0))))))) - (115)))));
+ }
+ else
+ {
+ struct_obj_8.member_4_0 = (unsigned short) (!(-(!((((int) (58592)) & ((int) (var_17))) ^ (((int) (32236)) ^ ((int) (struct_obj_8.member_4_5)))))));
+ if (-((int) (21770)))
+ {
+ unsigned short var_286 = (~((int) ((signed char) ((((int) (7)) & ((int) (struct_obj_4.member_2_4))) ^ ((int) ((signed char) (var_64))))))) <= (((~((int) (35976))) * ((((int) (struct_obj_2.member_5_1)) * ((int) (16694))) / (((int) (var_39)) * ((int) (struct_obj_2.member_5_1))))) * (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))));
+ unsigned short var_287 = var_237;
+ signed char var_288 = (((~(((int) (10329)) | ((int) (-70)))) << (((int) ((short) (((int) (struct_obj_8.member_4_3)) >> (((int) (var_41)) - (48528))))) - (431))) & ((((int) ((signed char) (((int) (21261)) | ((int) (41469))))) + (2147483647)) << (((((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (24)) - (14)) - (0)) - (1)))) ^ ((((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (2147483647)) << (((((int) ((signed char) (~((int) (18910))))) - (32)) - (0)) - (1))) ^ (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))));
+ signed char var_289 = ((int) (((int) ((unsigned short) ((((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)) ^ ((int) (var_238))) & (((int) (struct_obj_9.member_2_1.member_1_0)) & ((int) (-14985)))))) < (+(+((int) (struct_obj_4.member_2_6)))))) == (-((int) (((~((int) (var_26))) - ((int) ((short) (struct_obj_8.member_4_7)))) != ((((int) (var_52)) >> (((int) (var_9)) - (13476))) % ((int) (((int) (var_32)) > ((int) (struct_obj_9.member_2_6))))))));
+ short var_290 = ~((int) (var_46));
+ short var_291 = ((-(-(((int) (4132)) * ((int) (var_6))))) * (!(((int) (var_5)) / (((int) (struct_obj_4.member_2_5)) * ((int) (struct_obj_10.member_1_3)))))) / (((-(((int) (11642)) * ((int) (var_28)))) / ((((int) (var_30)) * ((int) (struct_obj_1.member_5_1))) / ((int) (108)))) * (+(-(((int) (36557)) * ((int) (-91))))));
+ short var_292 = ((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))));
+ short var_293 = (((int) ((short) ((~((int) (43459))) & ((((int) (var_292)) + (2147483647)) >> (((int) (44780)) - (44767)))))) && ((int) ((!(((int) (var_44)) || ((int) (-117)))) < ((int) (14679))))) ^ (-((int) (11578)));
+ }
+
+ if (~((int) ((unsigned short) ((unsigned short) (((int) ((signed char) (var_17))) & (((int) (struct_obj_8.member_4_9.member_1_0)) & ((int) (struct_obj_9.member_2_6))))))))
+ {
+ short var_294 = (((((~((int) (47532))) + (2147483647)) >> (((int) ((short) (140))) - (114))) ^ (~((int) (10977)))) & (((int) ((signed char) (((int) (var_16)) & ((int) (var_58))))) | ((int) (-29488)))) && ((int) ((unsigned short) ((((int) ((short) (((int) (struct_obj_7.member_1_2)) | ((int) (31723))))) + (2147483647)) << (((int) (var_49)) >> (~((int) (var_61)))))));
+ signed char var_295 = (unsigned short) (var_58);
+ short var_296 = ((int) (((((int) (45)) ^ (((int) (-12922)) & ((int) (struct_obj_8.member_4_6)))) - (-(((int) (var_46)) % ((int) (var_66))))) > ((((int) ((unsigned short) (var_64))) || (((int) (struct_obj_4.member_2_3.member_1_3)) || ((int) (var_10)))) || (((int) (struct_obj_4.member_2_1.member_1_0)) && (((int) (9298)) || ((int) (var_43))))))) <= ((((int) ((signed char) (((int) (-1967)) * ((int) (var_32))))) / (-(((int) (var_1)) * ((int) (struct_obj_4.member_2_1.member_1_3))))) >> ((((((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) * ((int) (-27550))) / (((int) (var_31)) - ((int) (var_34)))) - ((((int) (23777)) * ((int) (-12271))) - ((int) (var_32)))) - (291814241)));
+ var_297 = (unsigned short) ((~(((int) ((signed char) ((signed char) (-27)))) & ((((int) (-12274)) ^ ((int) (50858))) | (((int) (-24967)) | ((int) (-117)))))) >> ((((int) (29155)) << (((((int) ((signed char) (32757))) + (2147483647)) >> ((~((int) (14434))) + (14457))) - (509))) >> ((~((int) (-118))) - (98))));
+ short var_298 = -((int) ((~((((int) (var_63)) - ((int) (21024))) & (((int) (var_53)) || ((int) (var_21))))) != ((int) (struct_obj_2.member_5_1))));
+ var_65 = (short) (var_42);
+ short var_299 = ((int) ((signed char) ((!(((int) (9107)) | ((int) (36489)))) != ((((int) ((((int) (var_6)) | (~((int) (var_15)))) > (((int) (-91)) ^ ((int) (var_8))))) && ((((int) (-53)) & (((int) (struct_obj_3.member_5_1)) * ((int) (struct_obj_3.member_5_1)))) * ((int) ((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) > (!((int) (62742))))))) * ((int) (((int) ((unsigned short) (-2983))) <= (((int) ((short) (((int) (44)) | ((int) (var_28))))) % ((((int) (22182)) & ((int) (77))) ^ (((int) (struct_obj_3.member_5_3)) ^ ((int) (var_5))))))))))) * ((((int) ((((int) (var_6)) | (~((int) (var_15)))) > (((int) (-91)) ^ ((int) (var_8))))) && ((((int) (-53)) & (((int) (struct_obj_3.member_5_1)) * ((int) (struct_obj_3.member_5_1)))) * ((int) ((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) > (!((int) (62742))))))) * ((int) (((int) ((unsigned short) (-2983))) <= (((int) ((short) (((int) (44)) | ((int) (var_28))))) % ((((int) (22182)) & ((int) (77))) ^ (((int) (struct_obj_3.member_5_3)) ^ ((int) (var_5))))))));
+ unsigned short var_300 = ~(((int) ((short) ((~((int) (-2669))) ^ (~((int) (var_29)))))) | (((((int) (var_16)) | ((int) (struct_obj_8.member_4_5))) ^ (((int) (var_57)) & ((int) (var_33)))) | (~((int) (struct_obj_6.member_5_2)))));
+ }
+ else
+ {
+ short var_301 = (!((((int) (struct_obj_8.member_4_5)) || (!((int) (13152)))) && ((((int) (struct_obj_2.member_5_3)) && ((int) (var_20))) || (((int) (32258)) || ((int) (var_49)))))) || (!((!((int) ((signed char) (var_24)))) || (!(((int) (var_32)) && ((int) (var_23))))));
+ signed char var_302 = ~((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + ((+((int) ((unsigned short) (-6620)))) + (+((int) ((signed char) (struct_obj_4.member_2_1.member_1_0))))));
+ short var_303 = ((int) (((int) ((~(((int) (26)) | ((int) (38463)))) != ((int) ((short) (((int) (24326)) && ((int) (-59))))))) <= ((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) / (-(((int) (7532)) || ((int) (19696))))))) & ((int) ((signed char) (~(~(((int) (57632)) << (((int) (-7168)) + (7176)))))));
+ signed char var_304 = (unsigned short) ((unsigned short) ((((-((int) (54))) + (2147483647)) >> (((int) ((short) (-9386))) + (9392))) & ((int) (((int) ((short) (struct_obj_7.member_1_0))) <= (((int) (-25666)) & ((int) (var_27)))))));
+ short var_305 = (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) * (-(-(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))));
+ short var_306 = ~((((~((((int) (var_302)) + (2147483647)) >> (((int) (var_61)) + (30)))) + (2147483647)) >> ((((int) (var_2)) << ((((int) ((short) (struct_obj_6.member_5_2))) + (19600)) - (29))) - (142254))) << (((((~((int) (29941))) | (~((int) (-12126)))) + (2147483647)) >> (((((int) (62210)) | ((int) (48372))) >> ((((int) (57460)) ^ ((int) (-31908))) + (40156))) - (4074))) - (1016)));
+ signed char var_307 = ~(((~((int) ((signed char) (-12247)))) | ((int) ((unsigned short) (~((int) (13491)))))) & ((int) ((short) ((((int) (var_54)) | ((int) (27838))) | (((((int) ((short) ((signed char) (((int) (var_33)) | ((int) (struct_obj_4.member_2_3.member_1_2)))))) + (2147483647)) >> (((~((int) (var_10))) | (~((int) (var_21)))) & (((((int) (-42)) + (2147483647)) >> ((((int) (var_32)) - (46768)) - (9))) >> ((~((int) (var_21))) - (48))))) / ((-(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) >> ((int) ((signed char) (((int) (struct_obj_4.member_2_3.member_1_1)) && (((int) (99)) || ((int) (var_9))))))))))));
+ short var_308 = struct_obj_4.member_2_1.member_1_3;
+ signed char var_309 = (unsigned short) (((int) ((signed char) ((+((int) (-43))) - ((int) ((unsigned short) (21945)))))) + ((int) ((signed char) ((((int) (var_41)) - ((int) (77))) + (((((int) ((short) ((signed char) (((int) (var_33)) | ((int) (struct_obj_4.member_2_3.member_1_2)))))) + (2147483647)) >> (((~((int) (var_10))) | (~((int) (var_21)))) & (((((int) (-42)) + (2147483647)) >> ((((int) (var_32)) - (46768)) - (9))) >> ((~((int) (var_21))) - (48))))) / ((-(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) >> ((int) ((signed char) (((int) (struct_obj_4.member_2_3.member_1_1)) && (((int) (99)) || ((int) (var_9))))))))))));
+ }
+
+ if ((~(((~((int) (var_12))) & (((int) (struct_obj_6.member_5_0)) & ((int) (var_239)))) << (((~((int) (-74))) ^ (~((int) (114)))) + (75)))) && ((int) ((((((int) (13630)) ^ ((int) (19614))) >> (((int) (-34)) + (44))) | (((((int) (-65)) + (2147483647)) << (((int) (38398)) - (38398))) & (((int) (28940)) ^ ((int) (14947))))) > ((int) (((int) ((signed char) (((int) (var_48)) * ((int) (1346))))) != ((int) (var_239)))))))
+ {
+ signed char var_310 = ((((int) (struct_obj_10.member_1_2)) | ((~((int) (-28776))) & (~((int) (struct_obj_9.member_2_4))))) & ((~(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) & ((((int) (-84)) ^ ((int) (20424))) ^ ((int) ((unsigned short) (-14767)))))) ^ (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))));
+ unsigned short var_311 = (unsigned short) (var_28);
+ unsigned short var_312 = ((-((int) ((unsigned short) (54857)))) * ((int) (((~((int) (struct_obj_3.member_5_3))) & (((int) (var_7)) || ((int) (struct_obj_4.member_2_1.member_1_0)))) < (-((int) (var_1)))))) * (~(((int) (-38)) ^ ((((int) (0)) & ((int) (-104))) & (((int) (-110)) & ((int) (-92))))));
+ signed char var_313 = (unsigned short) (~((int) ((short) ((~((int) (struct_obj_9.member_2_1.member_1_3))) ^ (~((int) (102)))))));
+ var_314 = (signed char) (!(((((int) ((signed char) (-18731))) * (((int) (struct_obj_4.member_2_3.member_1_0)) * ((int) (struct_obj_8.member_4_4)))) * ((((int) (struct_obj_6.member_5_0)) * ((int) (86))) / (((int) (45398)) * ((int) (1603))))) << ((~((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) & (((int) (37)) & ((int) (55829))))) + (30))));
+ signed char var_315 = struct_obj_4.member_2_3.member_1_0;
+ signed char var_316 = (~((int) ((short) (((int) ((signed char) (struct_obj_7.member_1_1))) < (((int) (13)) || ((int) (struct_obj_8.member_4_6))))))) || (+((int) (((((int) (var_66)) >> (((int) (struct_obj_1.member_5_3)) - (710))) | (((int) (var_5)) & ((int) (8143)))) >= (-(((int) (5864)) & ((int) (var_63)))))));
+ unsigned short var_317 = ((int) ((unsigned short) (~(((~((int) (44320))) + (2147483647)) >> ((((int) (20877)) & ((int) (-14066))) - (16645)))))) || ((int) (struct_obj_5.member_1_3));
+ short var_318 = !((int) ((~(~(((int) (var_25)) | ((int) (struct_obj_1.member_5_0))))) <= ((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) | (((int) ((unsigned short) (struct_obj_5.member_1_0))) << ((((int) (23789)) ^ ((int) (struct_obj_3.member_5_1))) - (56480))))));
+ short var_319 = -(((int) ((unsigned short) ((((int) (-6974)) && ((int) (11892))) && (((int) (-3845)) || ((int) (-41)))))) || ((!(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) && ((int) (-19831))));
+ }
+ else
+ {
+ short var_320 = struct_obj_4.member_2_5;
+ unsigned short var_321 = struct_obj_6.member_5_0;
+ unsigned short var_322 = ~((int) (struct_obj_8.member_4_4));
+ unsigned short var_323 = ((int) (var_41)) >> ((int) (((int) (((int) (((int) ((short) (var_27))) == (~(~((int) (struct_obj_4.member_2_5)))))) < (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (2147483647)) << (((int) ((((int) (var_28)) || ((int) (struct_obj_2.member_5_0))) != (((int) (var_19)) & ((int) (struct_obj_4.member_2_1.member_1_1))))) >> (!((int) (struct_obj_2.member_5_3))))))) != ((int) (((int) ((signed char) (((int) (var_36)) - ((int) (struct_obj_2.member_5_1))))) != (!((int) (struct_obj_6.member_5_3)))))));
+ unsigned short var_324 = ((int) (((int) ((short) (var_27))) == (~(~((int) (struct_obj_4.member_2_5)))))) < (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (2147483647)) << (((int) ((((int) (var_28)) || ((int) (struct_obj_2.member_5_0))) != (((int) (var_19)) & ((int) (struct_obj_4.member_2_1.member_1_1))))) >> (!((int) (struct_obj_2.member_5_3)))));
+ short var_325 = ((((int) (((int) (((int) ((short) (var_27))) == (~(~((int) (struct_obj_4.member_2_5)))))) < (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (2147483647)) << (((int) ((((int) (var_28)) || ((int) (struct_obj_2.member_5_0))) != (((int) (var_19)) & ((int) (struct_obj_4.member_2_1.member_1_1))))) >> (!((int) (struct_obj_2.member_5_3))))))) ^ ((((int) (-122)) | ((int) (11927))) ^ (((int) (-62)) & ((int) (118))))) ^ (~((~((int) (25738))) & (~((int) (39921)))))) & ((int) ((signed char) (~(~((int) ((unsigned short) (struct_obj_3.member_5_0)))))));
+ signed char var_326 = (-((int) ((short) ((~((int) (-4583))) == (-((int) (var_36))))))) - ((int) (((((((int) (var_66)) >> (((int) (var_39)) - (28144))) ^ (~((int) (var_1)))) + (2147483647)) << (((((((int) (struct_obj_6.member_5_1)) << (((int) (var_8)) - (14653))) | (((int) (struct_obj_8.member_4_2)) | ((int) (101)))) - (22861934)) - (0)) - (1))) > (((int) (((int) (((int) (2)) >= ((int) (-8179)))) > (((int) (26581)) >> (((int) (-19231)) + (19234))))) >> ((int) (((int) (struct_obj_1.member_5_1)) <= (((int) (var_324)) << (((int) (var_22)) - (100))))))));
+ unsigned short var_327 = ((int) ((short) (~((((int) (26866)) ^ ((int) (var_325))) & ((int) (struct_obj_3.member_5_3)))))) & ((int) ((signed char) (~((((int) (-5)) & ((int) (43))) & (((int) (var_51)) | ((int) (var_62)))))));
+ unsigned short var_328 = ((((((int) (var_58)) & ((int) (struct_obj_2.member_5_1))) ^ (~((int) (struct_obj_4.member_2_4)))) >> ((((int) (17357)) << (((~((int) (var_41))) + (48559)) - (8))) - (568754148))) | ((int) ((unsigned short) (((((int) (struct_obj_7.member_1_0)) + (2147483647)) >> (((int) (var_32)) - (46780))) & (((int) (var_9)) | ((int) (-22456))))))) <= (-(~((int) ((-((int) (var_43))) < (((int) (var_62)) | ((int) (struct_obj_3.member_5_1)))))));
+ }
+
+ signed char var_329 = ((int) ((unsigned short) (!(!(!((int) (struct_obj_2.member_5_1))))))) != (-((int) (((int) ((((int) (9111)) * ((int) (45153))) <= (!((int) (17457))))) <= (~(((int) (77)) | ((int) (119)))))));
+ if (((int) ((unsigned short) (((((int) (var_12)) ^ ((int) (var_62))) | (((int) (struct_obj_10.member_1_3)) | ((int) (struct_obj_2.member_5_0)))) | (((int) ((signed char) (-7510))) ^ (((int) (-22547)) | ((int) (24754))))))) & (((~(((int) (struct_obj_3.member_5_3)) | ((int) (8)))) ^ (~(((int) (56)) ^ ((int) (3137))))) | (~((~((int) (12881))) & (((int) (var_8)) & ((int) (var_25)))))))
+ {
+ signed char var_330 = ((int) ((unsigned short) (~((((int) (39713)) * ((int) (var_65))) * ((int) ((signed char) (struct_obj_4.member_2_1.member_1_1))))))) <= (!(~((((int) (struct_obj_4.member_2_1.member_1_0)) + ((int) (var_50))) * ((int) ((short) (29769))))));
+ short var_331 = ~(((~(((int) (4598)) & ((int) (2017)))) | (((int) ((signed char) (32350))) | (((int) (-20556)) & ((int) (-79))))) ^ (((~((int) (-515))) & (((int) (61)) & ((int) (43194)))) | (((int) ((unsigned short) (11581))) & (~((int) (13360))))));
+ signed char var_332 = (+(-(!(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))))) <= (((~(((int) (var_28)) * ((int) (struct_obj_5.member_1_0)))) / ((((int) (var_24)) * ((int) (-103))) * (-((int) (var_58))))) * (~(((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))));
+ unsigned short var_333 = (signed char) ((~((((int) (struct_obj_4.member_2_3.member_1_2)) | ((int) (var_10))) & (~((int) (var_31))))) & ((int) (((int) ((unsigned short) (((int) (-65)) * ((int) (-23009))))) < ((((int) (14)) >> (((int) (9306)) - (9299))) % ((int) (((int) (-1206)) != ((int) (96))))))));
+ unsigned short var_334 = !(((~(((int) (-23006)) & ((int) (39022)))) ^ (~(((int) (14922)) | ((int) (-15058))))) | (((((int) (6629)) >> (((int) (35537)) - (35535))) & ((((int) (-16560)) + (2147483647)) >> (((int) (122)) - (118)))) >> (((((int) (16902)) >> ((int) (0))) ^ (~((int) (12194)))) + (28097))));
+ short var_335 = ((((((int) (3251)) && ((int) (55))) || (((int) (49719)) && ((int) (-65)))) || (!(((int) (11)) || ((int) (1092))))) && ((int) (52871))) * (!((int) ((short) (struct_obj_3.member_5_1))));
+ signed char var_336 = (((int) (((!((int) (20447))) || (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) < (((int) ((signed char) (var_49))) >> ((((int) (var_23)) % ((int) (var_331))) - (2293))))) % ((int) ((unsigned short) (~((int) (struct_obj_2.member_5_1)))))) <= (~((int) ((short) ((((int) (var_21)) && ((int) (29492))) && (!((int) (var_332)))))));
+ }
+ else
+ {
+ unsigned short var_337 = (signed char) ((-((((int) (struct_obj_8.member_4_3)) * ((int) (struct_obj_5.member_1_0))) * (~((int) (struct_obj_4.member_2_1.member_1_0))))) & ((int) ((unsigned short) ((((int) (var_7)) >> (((int) (struct_obj_4.member_2_5)) - (10080))) <= (((int) (70)) & ((int) (-14194)))))));
+ signed char var_338 = (-((int) (((((int) (struct_obj_8.member_4_6)) ^ ((int) (53070))) ^ (((int) (struct_obj_4.member_2_1.member_1_3)) | ((int) (var_59)))) < ((((int) (var_46)) & ((int) (-73))) && (((int) (var_39)) ^ ((int) (var_63))))))) <= ((int) (((((int) ((short) (struct_obj_8.member_4_1.member_3_0))) ^ (((int) (var_40)) % ((int) (var_22)))) && ((int) ((short) ((unsigned short) (var_19))))) < (((((int) (-62)) * ((int) (struct_obj_4.member_2_3.member_1_3))) * (!((int) (var_44)))) * (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))))));
+ unsigned short var_339 = (((~((int) (struct_obj_9.member_2_1.member_1_3))) ^ (~((int) ((short) (var_238))))) & (((int) ((signed char) (((int) (-12841)) | ((int) (var_37))))) ^ ((int) ((short) (~((int) (var_49))))))) | ((int) ((short) ((unsigned short) (var_4))));
+ unsigned short var_340 = ((((int) (-11424)) | (~(~((int) (46432))))) & (((int) (-2781)) * ((((int) (64292)) & ((int) (-22641))) * ((int) (((int) (23837)) <= ((int) (61))))))) - ((int) (25957));
+ short var_341 = ((int) ((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) > (((int) ((short) (((int) (struct_obj_4.member_2_0)) & ((int) (struct_obj_9.member_2_2))))) >> ((int) ((((int) (struct_obj_10.member_1_3)) * ((int) (4087))) <= (~((int) (var_13)))))))) + ((int) (struct_obj_8.member_4_2));
+ }
+
+ signed char var_342 = ~(((~((int) (struct_obj_3.member_5_3))) | ((((int) (struct_obj_9.member_2_1.member_1_1)) | ((int) (struct_obj_8.member_4_1.member_3_0))) | (((int) (854)) | ((int) (struct_obj_2.member_5_0))))) | (~((~((int) (var_21))) & ((int) (struct_obj_1.member_5_3)))));
+ if (!((int) ((((int) ((signed char) (-19215))) / ((!((int) (354))) | (((int) (10)) * ((int) (47875))))) > ((-(((int) (18345)) >> ((((int) (14143)) - (14111)) - (6)))) >> (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) - (((int) (12698)) + ((int) (20337)))) + (33070))))))
+ {
+ signed char var_343 = (unsigned short) (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) * (!((int) (var_34))));
+ unsigned short var_344 = (~(~((((int) (-7563)) ^ ((int) (19679))) & (((int) (var_51)) | ((int) (var_60)))))) < ((int) ((short) (!(!(((int) (var_41)) || ((int) (var_42)))))));
+ short var_345 = (signed char) ((signed char) (!(((int) (9488)) || (((int) (struct_obj_4.member_2_3.member_1_2)) && ((int) (struct_obj_1.member_5_2))))));
+ signed char var_346 = var_20;
+ short var_347 = (((int) (28581)) / (~((((int) (-39)) ^ ((int) (66))) ^ (((int) (-11597)) & ((int) (58452)))))) >> ((int) ((-(~((int) (((int) (83)) <= ((int) (26306)))))) > ((int) (((int) ((!((int) (-99))) <= (((int) (12533)) * ((int) (7321))))) > ((~((int) (26337))) | ((int) ((short) (36444))))))));
+ unsigned short var_348 = ((int) (struct_obj_4.member_2_6)) + ((int) (((((~((int) (struct_obj_8.member_4_1.member_3_0))) & (~((int) (struct_obj_9.member_2_6)))) + (2147483647)) >> ((~(((int) (-11)) ^ ((int) (var_52)))) - (9858))) < (!(!(((int) (struct_obj_1.member_5_3)) || ((int) (3)))))));
+ signed char var_349 = (~(((int) (2973)) ^ ((int) (57652)))) | (~(((int) ((short) (~((int) (46420))))) & ((int) ((signed char) (~((int) (5937)))))));
+ signed char var_350 = ((int) (((-(((int) (var_36)) * ((int) (struct_obj_9.member_2_1.member_1_0)))) / ((+((int) (var_5))) - ((int) (struct_obj_9.member_2_2)))) > (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))))) != (~((int) (((~((int) (var_30))) & (~((int) (13)))) == (~(((int) (struct_obj_10.member_1_3)) && ((int) (struct_obj_7.member_1_1)))))));
+ }
+ else
+ {
+ short var_351 = ((((int) ((short) (28973))) ^ ((((int) (5)) & ((int) (-25148))) & ((((int) (-4462)) + (2147483647)) << ((((int) (-95)) + (112)) - (17))))) | (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) + (2147483647)) >> ((((int) ((short) (-32))) | (((int) (58)) >> (((int) (83)) - (53)))) + (59)))) < ((int) (((((int) (-14523)) && (((int) (24739)) >> (((int) (6042)) - (6039)))) + ((int) (-9773))) >= (((!((int) (34844))) || (((int) (50)) && ((int) (108)))) && (((int) ((unsigned short) (52136))) && (((int) (63576)) || ((int) (-30405)))))));
+ unsigned short var_352 = (((int) (((int) ((signed char) ((unsigned short) (var_27)))) < ((int) ((((int) (-12442)) / ((int) (10549))) != (((int) (18542)) * ((int) (struct_obj_2.member_5_1))))))) / (-((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) * (((int) (7)) * ((int) (struct_obj_1.member_5_3)))))) | ((int) ((signed char) (((((int) (struct_obj_9.member_2_6)) * ((int) (var_17))) / ((int) (var_23))) / (((int) ((short) (var_32))) * (~((int) (struct_obj_1.member_5_3)))))));
+ short var_353 = (signed char) ((short) (((((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172)))))) && (!((int) (31901)))) && (!(((int) (24490)) && ((int) (var_14))))));
+ unsigned short var_354 = ~((((~((int) ((unsigned short) (struct_obj_7.member_1_2)))) + (2147483647)) >> (((((int) ((short) (-16611))) + (2147483647)) >> ((int) (((int) (var_237)) < ((int) (-59))))) - (2147467024))) & ((((int) (2632)) << ((~((int) (-70))) - (60))) | (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))));
+ short var_355 = ~(((int) ((signed char) ((((int) (var_238)) | ((int) (-28688))) | (~((int) (struct_obj_8.member_4_7)))))) & (-((int) (-18035))));
+ unsigned short var_356 = -(~((-(((int) (var_239)) ^ ((int) (struct_obj_4.member_2_5)))) % (!(!((int) (struct_obj_3.member_5_3))))));
+ }
+
+ short var_357 = ((((int) ((short) (((int) (struct_obj_9.member_2_0)) & ((int) (15110))))) | ((~((int) (var_8))) ^ (((int) (struct_obj_8.member_4_7)) | ((int) (var_66))))) ^ ((((int) ((unsigned short) (-163))) & ((int) ((short) (-51)))) ^ ((~((int) (struct_obj_8.member_4_0))) ^ ((int) ((unsigned short) (var_5)))))) < ((((((int) (struct_obj_9.member_2_1.member_1_3)) ^ ((int) (var_43))) >> ((~((int) (-19756))) - (19725))) & (~(((int) (var_60)) << ((int) (var_237))))) & ((((((int) (-91)) & ((int) (-28291))) + (2147483647)) >> ((((int) (51254)) << ((((int) (var_53)) - (13724)) - (13))) - (410005))) & ((int) (var_45))));
+ var_358 = (unsigned short) (((int) (((int) ((((int) (var_2)) ^ ((int) ((unsigned short) (var_16)))) < ((int) ((signed char) (((int) (40083)) & ((int) (var_16))))))) <= ((int) (14594)))) != ((int) ((signed char) (((int) (((int) ((((int) (-5)) & ((int) (-31721))) != ((int) ((signed char) (var_35))))) <= (((int) ((unsigned short) (55455))) / (((int) (struct_obj_4.member_2_3.member_1_0)) && ((int) (struct_obj_4.member_2_6)))))) >> (((-((int) ((signed char) (var_8)))) % (((int) (-9)) + (-(((-((int) (-23416))) - ((int) ((unsigned short) (55908)))) / ((((int) (-24160)) - ((int) (28547))) * ((int) (19172))))))) + (10))))));
+ }
+
+ var_359 = (short) (!((~((int) ((unsigned short) (((int) (8977)) ^ ((int) (-2109)))))) ^ ((int) ((signed char) ((unsigned short) (~((int) (22))))))));
+ if ((((int) ((short) (~(~((int) (var_43)))))) | (((~((int) (struct_obj_4.member_2_2))) + (2147483647)) >> ((((((int) (struct_obj_2.member_5_0)) & ((int) (-15349))) + (2147483647)) << (((((((((int) (-4)) + (2147483647)) >> (((int) (var_66)) - (65529))) - (67108862)) - (0)) - (0)) - (0)) - (1))) - (2147451885)))) & (((((int) (var_7)) ^ (((int) (struct_obj_4.member_2_5)) << (((int) (36)) - (31)))) << ((((int) (38)) & ((int) (var_60))) << (((int) (struct_obj_9.member_2_2)) >> (((int) (var_50)) - (46957))))) & (~((((int) (struct_obj_8.member_4_9.member_1_0)) << (((int) (7420)) - (7409))) | (~((int) (76)))))))
+ {
+ short var_360 = (((int) (var_17)) ^ (~((int) (39)))) - (~(((((int) (struct_obj_1.member_5_3)) & ((int) (struct_obj_5.member_1_3))) >> ((((int) (var_58)) & ((int) (struct_obj_4.member_2_3.member_1_1))) - (25))) | (~(((int) (struct_obj_10.member_1_3)) ^ ((int) (var_40))))));
+ unsigned short var_361 = (!(((((int) (-22027)) | ((int) (struct_obj_2.member_5_3))) | (((int) (-7382)) ^ ((int) (var_35)))) & ((int) ((signed char) (~((int) (var_6))))))) & ((int) (((int) (struct_obj_9.member_2_1.member_1_3)) > (~(((~((int) (var_41))) + (2147483647)) >> ((((int) (-5606)) + (2147483647)) >> (((int) (-10)) + (38)))))));
+ if (109)
+ {
+ signed char var_362 = (short) ((signed char) ((((int) (24460)) + ((int) (14314))) * ((((int) (54241)) - ((int) (18419))) + (((int) (struct_obj_10.member_1_3)) + ((int) (struct_obj_2.member_5_3))))));
+ unsigned short var_363 = ((((((int) (3103)) | ((int) (var_60))) << ((((int) (var_22)) | ((int) (struct_obj_8.member_4_5))) - (1270))) >> ((~(~((int) (var_36)))) - (27384))) >> (((int) ((short) (struct_obj_8.member_4_5))) - (1174))) * ((((int) ((((int) (35729)) || ((int) (var_38))) <= (!((int) (var_26))))) - (!(((int) (20238)) << (((int) (struct_obj_9.member_2_2)) - (40620))))) ^ ((int) (var_361)));
+ unsigned short var_364 = ((~(((int) ((unsigned short) (-12425))) & ((int) ((short) (52122))))) ^ (((~((int) (22591))) ^ (((int) (-14345)) & ((int) (51874)))) ^ ((((int) (51549)) ^ ((int) (3763))) ^ (((int) (43867)) ^ ((int) (-14)))))) & ((int) ((signed char) (14314)));
+ signed char var_365 = ((int) ((short) (~((int) (14314))))) >= (-(+((int) ((short) (((int) (struct_obj_5.member_1_3)) - ((int) (struct_obj_10.member_1_2)))))));
+ short var_366 = ((int) ((unsigned short) ((short) ((((int) (26517)) || ((int) (-9710))) && (((int) (struct_obj_9.member_2_1.member_1_0)) || ((int) (var_60))))))) >> ((int) (((int) (14314)) != ((((int) ((short) (struct_obj_6.member_5_3))) & (((int) (struct_obj_9.member_2_5)) & ((int) (-37)))) ^ (~((int) ((signed char) (struct_obj_8.member_4_9.member_1_2)))))));
+ var_367 = (signed char) (((int) (18490)) << ((~(~((~((int) (var_56))) ^ (((int) (-35)) | ((int) (var_50)))))) - (20202)));
+ short var_368 = (~((int) ((short) ((-((int) (struct_obj_4.member_2_1.member_1_3))) || ((int) ((signed char) (40213))))))) <= ((int) ((~((int) ((signed char) (((int) (var_60)) & ((int) (43)))))) <= ((~(((int) (var_12)) | ((int) (var_6)))) | ((int) ((signed char) (((int) (var_42)) & ((int) (var_66))))))));
+ short var_369 = ((int) (struct_obj_4.member_2_3.member_1_1)) & (~((int) ((unsigned short) (((int) (14314)) ^ (((int) (-90)) & ((int) (74)))))));
+ short var_370 = ((int) ((-((int) (var_11))) < (((int) (var_46)) >> ((((((int) (var_3)) ^ ((int) (struct_obj_3.member_5_0))) + (2147483647)) >> (((~((int) (var_54))) - (24876)) - (30))) - (536863949))))) >= (!(((int) (14314)) << ((int) ((~((int) (var_38))) == (((int) (var_8)) & ((int) (struct_obj_9.member_2_2)))))));
+ short var_371 = ((int) (14314)) % ((int) (122));
+ }
+
+ var_46 = (unsigned short) (((int) (((int) ((~(((int) (17)) << (((int) (var_56)) - (20181)))) > ((((int) (var_35)) || ((int) (struct_obj_4.member_2_3.member_1_3))) || (((int) (struct_obj_9.member_2_2)) || ((int) (struct_obj_5.member_1_0)))))) <= (((((int) (struct_obj_8.member_4_9.member_1_0)) ^ ((int) (struct_obj_1.member_5_3))) ^ (((int) (var_46)) ^ ((int) (-14806)))) && ((~((int) (struct_obj_5.member_1_3))) & (((int) (struct_obj_1.member_5_3)) & ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))))))) || ((int) (((((int) (((int) (42)) >= ((int) (43439)))) & ((int) ((unsigned short) (var_360)))) % ((int) ((unsigned short) (~((int) (var_239)))))) <= ((int) (14314)))));
+ signed char var_372 = !((int) ((signed char) (!(!(((int) (var_20)) || ((int) (struct_obj_9.member_2_0)))))));
+ short var_373 = (((int) (((int) (var_59)) != ((int) ((unsigned short) (-((int) (var_39))))))) & (!(~((int) (struct_obj_8.member_4_2))))) > (+(((((int) (13707)) & ((int) (7604))) | (((int) (-25846)) & ((int) (-16556)))) & (~(~((int) (-31893))))));
+ signed char var_374 = (((int) ((unsigned short) ((((int) (var_24)) - ((int) (-19514))) + ((int) ((unsigned short) (struct_obj_8.member_4_6)))))) % (~((((int) (struct_obj_3.member_5_1)) & ((int) (24836))) ^ ((int) (14314))))) && (((((int) ((unsigned short) (var_22))) * ((int) ((signed char) (-16118)))) / ((+((int) (32053))) * (((int) (var_46)) * ((int) (struct_obj_9.member_2_5))))) * (!(((int) ((unsigned short) (-21342))) / (((int) (-24)) * ((int) (44779))))));
+ }
+
+ if (-((((int) ((~((int) (-2283))) > ((int) (30538)))) & ((~((int) (-122))) | (((int) (20509)) | ((int) (-30753))))) ^ ((int) (struct_obj_8.member_4_2))))
+ {
+ short var_375 = (((int) ((signed char) ((((int) (-5376)) | ((int) (33396))) & (~((int) (52)))))) | (~(~((int) (struct_obj_8.member_4_1.member_3_0))))) & (~(((((int) (struct_obj_3.member_5_2)) | ((int) (51))) ^ (((int) (struct_obj_8.member_4_9.member_1_2)) | ((int) (5146)))) ^ ((((int) (var_47)) ^ ((int) (var_59))) ^ (((int) (var_53)) ^ ((int) (var_61))))));
+ short var_376 = ((int) ((short) (((int) ((signed char) (~((int) (struct_obj_7.member_1_2))))) ^ (~(((int) (struct_obj_4.member_2_7)) | ((int) (53512))))))) ^ (~((int) (struct_obj_8.member_4_3)));
+ if (!((((((int) (18612)) * ((int) (11102))) / (((int) (-10215)) * ((int) (14601)))) * ((int) ((unsigned short) (((int) (9895)) * ((int) (37183)))))) * ((((int) ((signed char) (5985))) * ((int) (-79))) * ((((int) (29091)) * ((int) (54881))) * (!((int) (8671)))))))
+ {
+ unsigned short var_377 = ~((((((int) (-37)) ^ ((int) (struct_obj_2.member_5_1))) & (~((int) (107)))) & ((((int) (var_26)) | ((int) (4730))) & (((int) (-82)) & ((int) (22312))))) & (((int) (struct_obj_9.member_2_4)) | ((~((int) (121))) & (((int) (struct_obj_7.member_1_2)) & ((int) (struct_obj_8.member_4_5))))));
+ signed char var_378 = ~(((((int) (var_239)) | (((int) (struct_obj_8.member_4_4)) | ((int) (var_54)))) & ((int) (var_31))) | (((int) ((unsigned short) (4132))) ^ ((((int) (var_239)) | ((int) (var_27))) & ((int) ((unsigned short) (36))))));
+ short var_379 = (signed char) (var_23);
+ signed char var_380 = !((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145))))))));
+ short var_381 = (short) (((int) (struct_obj_3.member_5_0)) * (~((((int) (var_50)) / ((int) (var_1))) * ((int) ((short) (var_34))))));
+ unsigned short var_382 = !((int) ((((int) ((short) (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145))))))))))) * (~(~((int) (struct_obj_4.member_2_1.member_1_3))))) != ((int) (((((int) (32580)) - ((int) (var_19))) - (((int) (var_57)) - ((int) (20)))) > ((((int) (var_31)) * ((int) (var_21))) / (((int) (var_16)) * ((int) (var_24))))))));
+ signed char var_383 = -(((~((int) (62))) || ((!((int) (struct_obj_10.member_1_0))) || ((int) (var_43)))) >> (((~(((int) (var_20)) ^ ((int) (struct_obj_4.member_2_7)))) | ((((int) (9112)) ^ ((int) (var_12))) | (~((int) (struct_obj_4.member_2_1.member_1_1))))) - (63223)));
+ }
+ else
+ {
+ signed char var_384 = +((!((int) (var_15))) || (((((int) (var_22)) || ((int) (var_30))) || (((int) (var_56)) || ((int) (var_25)))) && (((int) ((short) (var_46))) && (((int) (var_14)) && ((int) (var_1))))));
+ signed char var_385 = (~((int) ((-(!((int) (var_10)))) > ((int) ((((int) (7176)) || ((int) (struct_obj_3.member_5_3))) < (((int) (var_9)) ^ ((int) (var_4)))))))) & ((((((int) (var_66)) ^ ((int) (struct_obj_8.member_4_6))) ^ ((int) (var_25))) & (((int) ((signed char) (var_63))) & (((int) (41306)) ^ ((int) (-112))))) | (~(~(((int) (struct_obj_6.member_5_1)) | ((int) (20554))))));
+ signed char var_386 = ((int) ((short) (((((int) (struct_obj_8.member_4_7)) | ((int) (var_23))) << (((int) ((unsigned short) (struct_obj_4.member_2_3.member_1_0))) - (10))) & ((((int) (78)) | ((int) (struct_obj_8.member_4_2))) << (((~((int) (struct_obj_8.member_4_0))) + (17374)) - (3)))))) ^ ((((int) (var_43)) << ((~((int) (struct_obj_5.member_1_0))) & (((int) (33)) >> (((int) (90)) - (76))))) & ((int) (48)));
+ short var_387 = ((((int) ((short) (~((int) (37783))))) & ((int) ((unsigned short) (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))))))) / ((int) (64))) * ((int) (((int) ((!((int) (((int) (66)) != ((int) (61361))))) <= ((int) ((((int) (var_4)) || ((int) (var_45))) >= ((int) (((int) (10596)) == ((int) (struct_obj_3.member_5_2)))))))) != (((((int) (var_54)) * ((int) (115))) - (((int) (struct_obj_4.member_2_2)) >> (((int) (struct_obj_5.member_1_3)) + (20999)))) * ((int) (((int) ((signed char) (-2450))) == ((int) (((int) (6285)) <= ((int) (struct_obj_10.member_1_2)))))))));
+ short var_388 = ((int) (struct_obj_4.member_2_3.member_1_0)) >> (((((~(~((int) (struct_obj_8.member_4_6)))) ^ (~(((int) (var_62)) ^ ((int) (-20398))))) + (2147483647)) << (((!((~((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) >> ((((int) (17689)) & ((int) (58630))) - (17642)))) - (0)) - (1))) - (2147436043));
+ }
+
+ signed char var_389 = (((~((~((int) (-13180))) % ((int) ((signed char) (982))))) + (2147483647)) >> ((int) ((unsigned short) (((int) (((int) (41013)) < ((int) (struct_obj_8.member_4_9.member_1_0)))) > (((int) (-114)) % ((int) (var_52))))))) >> ((((int) (var_48)) * (!(~((int) (struct_obj_4.member_2_3.member_1_2))))) & ((-((int) ((unsigned short) (struct_obj_8.member_4_6)))) * (+(((int) (6318)) + ((int) (var_8))))));
+ short var_390 = ~(((~(!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))))) + (2147483647)) << (((~(!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))))) + (5)) - (3)));
+ signed char var_391 = (short) (((~((int) ((unsigned short) (-29)))) ^ ((int) (-21318))) != (((int) (var_52)) >> ((((int) ((signed char) (var_41))) ^ (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))))) + (109))));
+ var_392 = (unsigned short) (-(+((int) ((signed char) ((short) (~((int) (var_239))))))));
+ if (~(((int) (-14799)) * ((~(((int) (struct_obj_5.member_1_3)) * ((int) (-23808)))) * ((!((int) (-20034))) * (((int) (struct_obj_9.member_2_0)) * ((int) (struct_obj_10.member_1_2)))))))
+ {
+ unsigned short var_393 = ~((int) (((int) (var_14)) != (((~((int) (var_16))) | ((~(((int) (var_28)) ^ ((int) (struct_obj_4.member_2_3.member_1_0)))) ^ ((((int) (8520)) | ((int) (struct_obj_4.member_2_7))) ^ ((int) ((signed char) (32145)))))) & (((int) ((short) (var_5))) * ((int) (((int) (struct_obj_3.member_5_3)) >= ((((int) (-80)) - ((int) (-145))) - (((int) (var_24)) * ((int) (var_26))))))))));
+ unsigned short var_394 = (-(((((int) (-37)) | ((int) (struct_obj_9.member_2_4))) * (((int) (var_10)) || ((int) (118)))) & ((int) (-26136)))) / ((int) (((int) ((unsigned short) ((!((int) (struct_obj_9.member_2_2))) && (((int) (var_47)) || ((int) (var_20)))))) != ((~((((int) (-31043)) + (2147483647)) << (((int) (struct_obj_3.member_5_2)) - (59825)))) - ((((int) (struct_obj_4.member_2_3.member_1_2)) * ((int) (struct_obj_1.member_5_2))) ^ (((int) (var_65)) || ((int) (struct_obj_9.member_2_6)))))));
+ short var_395 = (!((int) ((((int) ((signed char) (var_61))) ^ ((int) ((short) (struct_obj_2.member_5_2)))) <= ((int) (struct_obj_6.member_5_1))))) % ((((-((int) (struct_obj_8.member_4_1.member_3_1.member_1_1))) + (-((int) (21146)))) * (-((int) (var_11)))) ^ (((int) ((unsigned short) (((int) (var_35)) >> (((int) (var_35)) - (14408))))) || ((int) (var_43))));
+ signed char var_396 = ((((-((int) (114))) / (((int) (10051)) * ((int) (3676)))) * ((int) (10897))) * (~((((int) (52640)) / ((int) (57215))) * (((int) (126)) * ((int) (21)))))) * ((int) (-104));
+ short var_397 = struct_obj_4.member_2_3.member_1_2;
+ unsigned short var_398 = +((int) ((short) (var_17)));
+ short var_399 = (((int) (39888)) || ((int) ((signed char) ((((int) (-25317)) | ((int) (5975))) | (((int) (struct_obj_7.member_1_2)) ^ ((int) (19725))))))) + ((int) ((~(~(((int) (var_52)) * ((int) (struct_obj_4.member_2_5))))) <= (((((int) (24622)) & ((int) (struct_obj_8.member_4_6))) >> ((((int) (-6)) ^ ((int) (struct_obj_8.member_4_9.member_1_1))) + (13903))) | ((((int) (struct_obj_4.member_2_1.member_1_1)) & ((int) (var_65))) | (~((int) (var_9)))))));
+ signed char var_400 = (~((int) (struct_obj_9.member_2_2))) & (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))));
+ short var_401 = (((int) (30788)) || (((((int) (struct_obj_4.member_2_1.member_1_1)) || ((int) (var_54))) && (((int) (struct_obj_9.member_2_5)) || ((int) (31866)))) && (!(((int) (-25)) || ((int) (var_25)))))) && ((((!((int) (-8773))) && (((int) (var_4)) || ((int) (struct_obj_6.member_5_2)))) || (((int) ((unsigned short) (struct_obj_10.member_1_0))) || (!((int) (var_390))))) || (((int) (var_63)) && ((((int) (var_14)) && ((int) (var_3))) && (((int) (46668)) && ((int) (var_376))))));
+ short var_402 = -((+((((int) (struct_obj_6.member_5_1)) * ((int) (struct_obj_10.member_1_3))) / (((int) (41269)) * ((int) (4485))))) * ((+(((int) (71)) * ((int) (struct_obj_7.member_1_0)))) / ((((int) (85)) * ((int) (var_14))) * ((int) (struct_obj_3.member_5_2)))));
+ }
+ else
+ {
+ short var_403 = struct_obj_3.member_5_2;
+ var_40 = (signed char) (((int) ((((int) ((+((int) (struct_obj_8.member_4_6))) != ((int) ((unsigned short) (var_24))))) & (~(((int) (struct_obj_4.member_2_1.member_1_0)) >> (((int) (5468)) - (5438))))) >= ((int) ((short) ((unsigned short) (((int) (6863)) > ((int) (struct_obj_9.member_2_1.member_1_0)))))))) >> ((((((int) (89)) & ((int) (-26560))) ^ ((int) ((unsigned short) (61166)))) | ((((int) (struct_obj_3.member_5_1)) & ((int) (25315))) ^ (((int) (7697)) & ((int) (89))))) >> (((int) ((signed char) (-(((int) (struct_obj_3.member_5_3)) + ((int) (40803)))))) + (79))));
+ short var_404 = ((int) (var_23)) >> ((((((int) (94)) | ((int) (63983))) >> ((((int) (var_52)) << ((((int) (-34)) + (64)) - (13))) - (1294204900))) & (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145)))))))))) << (((~((int) ((signed char) (var_46)))) | (((int) (struct_obj_4.member_2_0)) | (~((int) (struct_obj_6.member_5_1))))) + (15)));
+ unsigned short var_405 = (short) (~((~(~((int) (-82)))) & (~(~((int) (var_21))))));
+ unsigned short var_406 = (!((int) ((((((int) (-5843)) + (2147483647)) >> (((int) (9959)) - (9945))) || (((int) (65528)) % ((int) (18356)))) > ((int) (-82))))) & ((int) ((((((int) (16978)) << (((int) (55441)) - (55441))) & (~((int) (20123)))) << ((((((int) (-53)) & ((int) (-20160))) + (2147483647)) << ((((int) (63586)) ^ ((int) (48225))) - (17411))) - (2147463464))) <= (~(!(((int) (32938)) && ((int) (55062)))))));
+ short var_407 = (~(~((int) ((unsigned short) (~((int) (30575))))))) < (~((~((int) ((unsigned short) (var_24)))) % (~((int) (((int) (struct_obj_9.member_2_2)) != ((int) (struct_obj_10.member_1_2)))))));
+ var_37 = (signed char) (((int) ((unsigned short) (!((((int) (struct_obj_5.member_1_0)) * ((int) (4381))) / (((int) (struct_obj_9.member_2_0)) * ((int) (var_8))))))) & (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145))))))))));
+ unsigned short var_408 = ((int) ((!((((int) ((-127 - 1))) * ((int) (var_23))) * ((int) (var_405)))) <= ((int) ((unsigned short) ((!((int) (struct_obj_8.member_4_1.member_3_1.member_1_1))) != (~((int) (14031)))))))) << ((int) (((int) ((unsigned short) ((unsigned short) (+((int) (8559)))))) == ((((int) ((signed char) (-13521))) & ((int) (18645))) >> ((int) (((int) (((int) (115)) >= ((int) (24451)))) > ((int) (((int) (20299)) <= ((int) (-4935)))))))));
+ unsigned short var_409 = ~((~((int) ((unsigned short) (((int) (-5693)) | ((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)))))) | (!((int) (((int) (((int) ((short) (!((int) (45291))))) > ((int) (-24057)))) <= ((((int) (79)) | (((int) (7019)) * ((int) (-30489)))) + ((int) ((((int) (45)) || ((int) (19))) <= (~((int) (8145))))))))));
+ signed char var_410 = (signed char) ((((int) ((signed char) (((int) (struct_obj_8.member_4_3)) - ((int) (2744))))) * (+((int) (struct_obj_8.member_4_9.member_1_2)))) > ((int) (struct_obj_4.member_2_1.member_1_0)));
+ }
+
+ unsigned short var_411 = (signed char) (24176);
+ }
+
+ if ((short) (((!(((int) (struct_obj_1.member_5_2)) && ((int) (50462)))) || ((!((int) (var_26))) && (!((int) (var_239))))) && (!((int) ((signed char) (((int) (-15398)) && ((int) (struct_obj_4.member_2_3.member_1_1))))))))
+ {
+ if (~((int) ((signed char) (((((int) (-3658)) & ((int) (46399))) & (~((int) (var_6)))) & ((((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) & ((int) (struct_obj_8.member_4_2))) | (~((int) (var_55))))))))
+ {
+ signed char var_412 = (((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) | ((!(!((int) (struct_obj_6.member_5_2)))) || ((((int) (-22401)) || ((int) (var_15))) || (((int) (73)) || ((int) (-31)))))) >> (((~(~((int) (77)))) & ((int) ((signed char) (~((int) ((unsigned short) (-3189))))))) - (66));
+ unsigned short var_413 = ~((~(((int) ((unsigned short) (var_63))) ^ (((int) (struct_obj_4.member_2_3.member_1_3)) ^ ((int) (888))))) && ((int) ((signed char) (((int) ((short) (92))) >> (((int) ((signed char) (83))) - (81))))));
+ signed char var_414 = ((int) ((short) (~((int) ((signed char) (!((int) (31724)))))))) != ((int) (((int) ((short) ((!((int) (var_61))) || (((int) (struct_obj_9.member_2_1.member_1_3)) && ((int) (var_15)))))) < ((int) (((((int) (struct_obj_6.member_5_3)) >> (((int) (42310)) - (42285))) && (~((int) ((short) (~(~((int) (-20)))))))) <= (~(((int) (25509)) || ((int) (var_26))))))));
+ signed char var_415 = ~((int) ((short) (~(~((int) (-20))))));
+ struct_obj_5.member_1_3 = (short) ((((int) (((((int) (1141)) >> (((int) (20167)) - (20155))) * (!((int) (7901)))) > (((int) ((unsigned short) (-12160))) || (((int) (6205)) || ((int) (-116)))))) >> ((int) (((!((int) (var_26))) && (((int) (-16178)) || ((int) (-93)))) < ((int) ((-((int) (struct_obj_4.member_2_3.member_1_1))) != ((int) ((signed char) (var_56)))))))) == ((((~((int) (-13334))) & (((int) (38790)) & ((int) (46)))) | (((int) ((short) (var_52))) ^ ((int) ((short) (6800))))) ^ ((int) ((signed char) ((signed char) (((int) (49)) ^ ((int) (-7974))))))));
+ }
+
+ if ((((int) ((signed char) ((((int) (var_16)) ^ ((int) (var_60))) ^ (~((int) (8171)))))) ^ (~((int) (var_63)))) || (((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) * ((((int) ((short) (35294))) * ((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14)))))))) * ((-((int) (-14699))) / (((int) (32201)) * ((int) (13800)))))))
+ {
+ unsigned short var_416 = -(!(+((((int) (var_11)) >> (((int) (62073)) - (62065))) - ((int) (((int) (26396)) > ((int) (var_23)))))));
+ signed char var_417 = (((~(((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))) & ((int) ((unsigned short) (var_239))))) + (2147483647)) >> ((((int) (struct_obj_6.member_5_2)) | (~(((int) (struct_obj_4.member_2_3.member_1_0)) | ((int) (48769))))) + (3079))) >> (((((~((int) (-24))) & (((int) (var_30)) >> (((int) (var_7)) - (32)))) << (((int) ((short) (((int) (struct_obj_2.member_5_0)) & ((int) (struct_obj_6.member_5_3))))) - (12279))) | ((int) ((signed char) (struct_obj_9.member_2_1.member_1_1)))) + (62));
+ signed char var_418 = ((int) ((signed char) (-((int) ((unsigned short) ((short) (struct_obj_1.member_5_3))))))) == ((((((int) (14395)) ^ ((int) (28584))) ^ (((int) (struct_obj_8.member_4_9.member_1_0)) | ((int) (var_239)))) ^ (~(((int) (32)) ^ ((int) (struct_obj_3.member_5_3))))) ^ ((int) ((short) ((((int) (struct_obj_5.member_1_1)) & ((int) (var_13))) ^ (((int) (var_5)) | ((int) (-69)))))));
+ signed char var_419 = (~((~(((int) (28263)) ^ ((int) (115)))) ^ ((((int) (21)) & ((int) (71))) | ((int) (var_39))))) & ((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2))));
+ signed char var_420 = (~(((((int) ((signed char) (-94))) ^ ((int) ((signed char) (struct_obj_7.member_1_1)))) + (2147483647)) >> ((~(~((int) (struct_obj_10.member_1_3)))) + (21785)))) != ((~((int) ((short) ((short) (-27))))) && (~(-((int) (var_37)))));
+ unsigned short var_421 = ~(((int) ((signed char) (+(!((int) (var_4)))))) & ((int) (((~((int) (var_30))) && (((int) (var_23)) && ((int) (struct_obj_8.member_4_9.member_1_0)))) != ((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))))));
+ }
+
+ if ((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2))))
+ {
+ var_36 = (short) (25335);
+ unsigned short var_422 = (((int) ((signed char) ((-((int) (struct_obj_4.member_2_1.member_1_3))) <= ((int) (((int) (-14940)) < ((int) (52041))))))) * (((((int) (struct_obj_2.member_5_2)) ^ ((int) (57552))) >> (((int) (2460)) & ((int) (var_38)))) || ((int) (((int) ((unsigned short) (-2096))) <= (((int) (var_25)) - ((int) (var_66))))))) < ((((+((int) (struct_obj_6.member_5_3))) + (+((int) (46470)))) - ((+((int) (2855))) + (((int) (var_41)) - ((int) (-121))))) + (-((-((int) (var_58))) + ((int) ((short) (-127))))));
+ unsigned short var_423 = 44;
+ short var_424 = -(-((int) ((!(~((int) (61500)))) <= ((~((int) (var_37))) || ((int) (((int) (var_21)) >= ((int) (var_7))))))));
+ unsigned short var_425 = (short) ((~(~(((int) (-11932)) ^ ((int) (var_239))))) ^ (~(~(((int) (-7336)) ^ ((int) (5408))))));
+ unsigned short var_426 = !(((int) (((int) (((int) (283)) <= ((int) (65)))) != ((int) ((signed char) (((int) (22882)) ^ ((int) (29567))))))) || (-(((int) ((signed char) (var_239))) | (((int) (struct_obj_4.member_2_3.member_1_3)) & ((int) (-27))))));
+ unsigned short var_427 = (((((~((int) (struct_obj_3.member_5_3))) ^ (((int) (-24690)) | ((int) (91)))) + (2147483647)) >> ((int) ((((int) (-28477)) + ((int) (var_17))) == (~((int) (var_30)))))) / ((int) ((short) ((short) (((int) (-30015)) - ((int) (65016))))))) >= ((int) (struct_obj_6.member_5_2));
+ short var_428 = (+((int) ((short) ((((int) (-99)) * ((int) (var_58))) + (((int) (-8669)) - ((int) (3621))))))) < ((int) ((signed char) (~(((((int) (var_64)) + (2147483647)) << ((int) (var_427))) << (((((int) ((unsigned short) (11))) - (10)) - (0)) - (1))))));
+ signed char var_429 = ((((int) ((unsigned short) (~((int) (var_50))))) * (~((int) (var_5)))) * ((int) (var_47))) * ((~(((int) ((short) (64554))) * (((int) (68)) * ((int) (39))))) * (((+((int) (-19580))) / (((int) (-26334)) * ((int) (56761)))) * (((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))) * (((int) (struct_obj_9.member_2_1.member_1_0)) * ((int) (var_31))))));
+ }
+
+ if ((~((~(~((int) (var_56)))) | ((((int) (var_43)) >> (((int) (var_13)) + (23914))) >> ((((int) (struct_obj_4.member_2_3.member_1_1)) & ((int) (var_6))) - (35519))))) ^ ((~((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) & (~(~(((int) (struct_obj_8.member_4_0)) << ((((int) (struct_obj_9.member_2_1.member_1_1)) - (31950)) - (6)))))))
+ {
+ short var_430 = (!((~(((int) (var_57)) | ((int) (-5372)))) ^ ((((int) (var_20)) & ((int) (var_18))) | (~((int) (struct_obj_7.member_1_0)))))) && ((int) (struct_obj_4.member_2_6));
+ signed char var_431 = (unsigned short) (~(((((int) (struct_obj_4.member_2_5)) ^ ((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) & (((int) (19)) & ((int) (7794)))) & ((~((int) (var_46))) ^ (~((int) (var_62))))));
+ short var_432 = ((((int) (var_28)) - (((int) (-23906)) - (((int) (var_22)) + ((int) (struct_obj_4.member_2_3.member_1_3))))) - (((((int) (var_2)) + ((int) (struct_obj_10.member_1_0))) + (((int) (struct_obj_10.member_1_2)) - ((int) (55916)))) + (-(((int) (var_23)) - ((int) (29449)))))) || ((int) ((signed char) ((~(~((int) (var_48)))) | ((((int) (struct_obj_6.member_5_0)) ^ ((int) (struct_obj_6.member_5_0))) ^ (((int) (55178)) & ((int) (var_56)))))));
+ signed char var_433 = ((int) (struct_obj_9.member_2_5)) || ((((((int) (27241)) | ((int) (var_51))) & (((int) (84)) | ((int) (-11135)))) | ((int) (struct_obj_3.member_5_0))) | ((int) ((short) (~(((int) (var_17)) | ((int) (3828)))))));
+ short var_434 = !(((int) ((unsigned short) ((((int) (struct_obj_8.member_4_0)) & ((int) (-2293))) <= (((int) (34)) | ((int) (var_39)))))) << ((((((int) (-29164)) & ((int) (struct_obj_8.member_4_5))) ^ ((int) ((unsigned short) (struct_obj_6.member_5_2)))) >> ((((~((int) (struct_obj_8.member_4_5))) + (2147483647)) >> (((int) (var_2)) - (17779))) - (67108820))) - (364)));
+ signed char var_435 = ~(~((int) ((signed char) (-(((int) (struct_obj_9.member_2_2)) && ((int) (struct_obj_9.member_2_1.member_1_0)))))));
+ signed char var_436 = (signed char) ((-((((int) (48727)) << (((((int) (var_51)) + (11808)) - (5)) - (2))) << (((((int) (-23500)) + (2147483647)) >> (((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)) - (25280))) - (1048564)))) < ((int) (struct_obj_7.member_1_0)));
+ unsigned short var_437 = ((-(-((((int) (-8)) ^ ((int) (65))) & (~((int) (struct_obj_1.member_5_1)))))) + (2147483647)) >> ((int) ((short) (!(!(((int) (115)) && ((int) (14265)))))));
+ unsigned short var_438 = ~(((((int) ((short) ((short) (var_13)))) || (!((int) (var_48)))) || ((int) ((unsigned short) (!((int) (31752)))))) || ((int) ((short) ((short) (var_13)))));
+ unsigned short var_439 = ((int) ((unsigned short) ((((((int) (var_42)) + (2147483647)) >> (((int) (struct_obj_9.member_2_4)) - (13535))) & (~((int) (var_56)))) << ((((int) (-17065)) | ((int) ((signed char) (struct_obj_8.member_4_2)))) + (17025))))) & ((~((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14)))))))) ^ ((int) (var_40)));
+ }
+
+ short var_440 = (+((int) (((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))) <= ((int) ((unsigned short) (!((int) (var_56)))))))) <= ((int) (((int) ((signed char) (((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) / (((int) (var_60)) * ((int) (-77)))))) == ((int) ((((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) % ((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2))))) >= ((int) ((((int) (var_66)) && ((int) (var_60))) >= (+((int) (var_2)))))))));
+ short var_441 = struct_obj_3.member_5_0;
+ if ((((~((int) (var_441))) * (+(((int) (struct_obj_6.member_5_2)) + ((int) (var_60))))) && ((int) ((((int) (struct_obj_6.member_5_0)) && (!((int) (25)))) <= ((int) ((signed char) ((signed char) (var_33))))))) || (((~(((int) (struct_obj_5.member_1_1)) & ((int) (11652)))) & ((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14)))))))) | (~((int) ((unsigned short) ((signed char) (var_60)))))))
+ {
+ signed char var_442 = ~((((+((int) (var_7))) / (((int) (18532)) * ((int) (var_28)))) * ((int) (struct_obj_1.member_5_3))) * (((((int) (var_18)) * ((int) (struct_obj_6.member_5_1))) / (~((int) (struct_obj_4.member_2_3.member_1_1)))) / ((((int) (64)) * ((int) (-16))) * (((int) (var_31)) * ((int) (65))))));
+ signed char var_443 = var_18;
+ signed char var_444 = ~(~((~(((int) (var_30)) ^ ((int) (struct_obj_8.member_4_4)))) | ((int) ((unsigned short) (~((int) (struct_obj_9.member_2_1.member_1_0)))))));
+ short var_445 = ((+((((int) (struct_obj_4.member_2_1.member_1_1)) + ((int) (struct_obj_9.member_2_5))) + (((int) (13876)) * ((int) (26471))))) / (-((((int) (12947)) - ((int) (28265))) + (((int) (-30980)) - ((int) (40610)))))) << ((+((int) (((int) ((unsigned short) (var_11))) != ((int) ((signed char) (var_41)))))) >> (((int) ((unsigned short) ((short) (~((int) (struct_obj_4.member_2_0)))))) - (57920)));
+ short var_446 = ((int) ((~(((int) (31)) || (((int) (struct_obj_5.member_1_3)) && ((int) (var_14))))) > (~((int) (18166))))) > (((int) (((int) ((((int) (4507)) >> (((int) (60479)) - (60459))) > (((int) (14247)) * ((int) (var_44))))) < ((int) ((!((int) (var_15))) <= (+((int) (struct_obj_4.member_2_7))))))) | (~((((int) (15746)) | ((int) (struct_obj_9.member_2_2))) ^ ((int) ((unsigned short) (-5912))))));
+ unsigned short var_447 = (+((int) (((int) ((unsigned short) (((int) (-119)) + ((int) (91))))) <= ((((int) (52)) | ((int) (-85))) ^ (((int) (36281)) ^ ((int) (11743))))))) & (~((int) ((short) (((int) ((unsigned short) (5509))) / (((int) (53477)) * ((int) (-1233)))))));
+ signed char var_448 = (~((int) ((short) (((int) ((short) (var_12))) ^ (~((int) (var_15))))))) | ((int) ((signed char) (~(~((int) ((unsigned short) (var_31)))))));
+ unsigned short var_449 = (short) ((((int) ((signed char) ((unsigned short) (-9779)))) || ((((int) (var_6)) - (-((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))))) % ((int) (var_4)))) && ((((int) ((unsigned short) (2615))) && ((int) ((unsigned short) (-127)))) && ((((int) (var_443)) && ((int) (var_56))) || (((int) (struct_obj_5.member_1_3)) || ((int) (struct_obj_1.member_5_1))))));
+ }
+ else
+ {
+ unsigned short var_450 = ((int) ((short) (-(((int) (1)) >> ((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))))))) != ((int) ((signed char) ((((int) (var_6)) - (-((+(((int) ((unsigned short) (((int) (-7293)) * ((int) (5069))))) * ((int) ((signed char) (((int) (struct_obj_2.member_5_3)) * ((int) (var_16))))))) * (((int) (((int) (var_34)) < ((int) ((short) ((unsigned short) (var_24)))))) & ((~((int) ((short) (var_14)))) & (~(~((int) (var_14))))))))) % ((int) (var_4)))));
+ short var_451 = ~((((((int) (var_51)) & ((int) (var_64))) & ((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2))))) & (~(((int) (6939)) ^ ((int) (5312))))) & (~((((int) (62)) << (((int) (var_13)) + (23928))) & (((int) (var_3)) | ((int) (struct_obj_6.member_5_3))))));
+ unsigned short var_452 = ((((((int) (struct_obj_4.member_2_5)) & ((int) (-26752))) || ((int) ((signed char) (-20709)))) - ((int) (((int) ((unsigned short) (45959))) <= (((int) (var_32)) / ((int) (-65)))))) && (+(((int) (struct_obj_3.member_5_3)) || ((int) ((((int) ((short) (struct_obj_2.member_5_0))) & (((int) (var_21)) | ((int) (var_3)))) != (((int) ((short) (6))) ^ (!((int) (var_26))))))))) >> ((int) (((int) (((int) ((((int) (var_28)) >> (((int) (-22)) + (23))) >= (((int) (var_51)) | ((int) (103))))) != (((int) ((signed char) (var_21))) | ((int) ((unsigned short) (var_60)))))) <= ((int) ((~(+((int) (53974)))) <= ((int) (((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) <= ((int) (((int) (19953)) >= ((int) (-25036))))))))));
+ short var_453 = ~((int) ((unsigned short) (~((((int) (20)) << (((int) (var_3)) - (54))) << ((((~((int) (35514))) + (35541)) - (3)) - (21))))));
+ signed char var_454 = ~(!((int) (((int) ((unsigned short) (((int) (17187)) >= ((int) (3599))))) < (((int) ((short) (var_12))) >> ((~((int) (struct_obj_2.member_5_1))) + (25779))))));
+ short var_455 = (((int) ((signed char) ((signed char) (((int) (struct_obj_8.member_4_4)) ^ ((int) (var_452)))))) | (~((int) (struct_obj_4.member_2_3.member_1_3)))) >> ((((((int) ((unsigned short) (124))) & (~((int) (57361)))) << ((~(((int) (93)) ^ ((int) (59)))) + (110))) << ((~(~(~((int) (8))))) + (11))) - (55278));
+ unsigned short var_456 = ((int) ((((((((~((int) (36437))) + (2147483647)) << ((((int) (struct_obj_1.member_5_3)) << (((int) (var_2)) - (17781))) - (5920))) & (~((int) ((signed char) (struct_obj_4.member_2_1.member_1_3))))) ^ (((((int) (var_33)) << (((int) (17994)) - (17983))) >> (((int) ((short) (var_20))) + (16020))) ^ (((~((int) (101))) + (2147483647)) >> ((((int) (-7863)) ^ ((int) (struct_obj_4.member_2_4))) - (21936))))) | (~((int) (struct_obj_4.member_2_3.member_1_2)))) ^ ((int) ((signed char) (((int) (63815)) >> (((int) (-65)) + (94)))))) <= ((int) (99)))) & (!((int) ((signed char) ((unsigned short) (((int) (var_20)) >> (((int) (var_35)) - (14412)))))));
+ signed char var_457 = (!((int) ((signed char) ((((int) (11972)) || ((int) (struct_obj_7.member_1_0))) || (((int) (struct_obj_4.member_2_1.member_1_3)) || ((int) (91))))))) && ((((+(((int) (struct_obj_3.member_5_3)) || ((int) ((((int) ((short) (struct_obj_2.member_5_0))) & (((int) (var_21)) | ((int) (var_3)))) != (((int) ((short) (6))) ^ (!((int) (var_26)))))))) && (((int) (-24193)) || ((int) (struct_obj_4.member_2_1.member_1_0)))) || ((int) (69))) || (!((!((int) (36135))) && (!((int) (-42))))));
+ signed char var_458 = ((int) ((signed char) (((((int) (var_441)) & ((int) (-251))) & (((int) (34879)) & ((int) (struct_obj_4.member_2_7)))) & ((((int) (48265)) * ((int) (var_56))) / (~((int) (-71))))))) & ((int) (((-(((int) (62323)) | ((int) (24633)))) & (~(+(((int) (struct_obj_3.member_5_3)) || ((int) ((((int) ((short) (struct_obj_2.member_5_0))) & (((int) (var_21)) | ((int) (var_3)))) != (((int) ((short) (6))) ^ (!((int) (var_26)))))))))) >= ((int) ((signed char) (~(((int) (-16927)) & ((int) (struct_obj_1.member_5_2))))))));
+ }
+
+ }
+ else
+ {
+ unsigned short var_459 = ((int) ((-((int) ((short) (((int) (-8)) < ((int) (18519)))))) != ((int) ((short) ((((int) (10757)) | ((int) (16517))) ^ (~((int) (8440)))))))) ^ ((int) (var_52));
+ unsigned short var_460 = (-(~((int) (((int) (((int) (((int) (struct_obj_4.member_2_7)) > ((~((int) (struct_obj_4.member_2_0))) | ((int) ((short) (var_35)))))) > (~(~(((int) (39209)) ^ ((int) (struct_obj_4.member_2_1.member_1_3))))))) != ((int) (((int) ((short) (((int) (((int) (var_14)) == ((int) (struct_obj_3.member_5_2)))) * ((int) (((int) (struct_obj_4.member_2_3.member_1_3)) >= ((int) (56773))))))) <= (((((int) (var_13)) + (2147483647)) >> (((int) ((short) (-14702))) + (14731))) << (((int) (struct_obj_2.member_5_1)) - (25749))))))))) == ((int) (((int) ((signed char) ((((int) (var_20)) << (((int) (var_40)) - (63))) == ((((int) (struct_obj_5.member_1_0)) + (2147483647)) << (((int) (31224)) - (31224)))))) <= (!((((int) (struct_obj_10.member_1_2)) * ((int) (63260))) / (((int) (struct_obj_8.member_4_3)) * ((int) (23510)))))));
+ unsigned short var_461 = (((int) ((signed char) ((((int) (var_42)) ^ ((int) (var_55))) >> ((((int) (var_45)) & ((int) (25562))) - (25483))))) & ((int) (((int) (((int) (((int) (struct_obj_4.member_2_7)) > ((~((int) (struct_obj_4.member_2_0))) | ((int) ((short) (var_35)))))) > (~(~(((int) (39209)) ^ ((int) (struct_obj_4.member_2_1.member_1_3))))))) != ((int) (((int) ((short) (((int) (((int) (var_14)) == ((int) (struct_obj_3.member_5_2)))) * ((int) (((int) (struct_obj_4.member_2_3.member_1_3)) >= ((int) (56773))))))) <= (((((int) (var_13)) + (2147483647)) >> (((int) ((short) (-14702))) + (14731))) << (((int) (struct_obj_2.member_5_1)) - (25749)))))))) > (-((int) (struct_obj_1.member_5_3)));
+ unsigned short var_462 = ((int) (var_49)) * ((~(-(((int) (-125)) * ((int) (struct_obj_6.member_5_0))))) / ((int) ((unsigned short) ((short) (((int) (var_21)) * ((int) (var_2)))))));
+ if ((unsigned short) (~(~((int) (((int) (((int) (((int) (struct_obj_4.member_2_7)) > ((~((int) (struct_obj_4.member_2_0))) | ((int) ((short) (var_35)))))) > (~(~(((int) (39209)) ^ ((int) (struct_obj_4.member_2_1.member_1_3))))))) != ((int) (((int) ((short) (((int) (((int) (var_14)) == ((int) (struct_obj_3.member_5_2)))) * ((int) (((int) (struct_obj_4.member_2_3.member_1_3)) >= ((int) (56773))))))) <= (((((int) (var_13)) + (2147483647)) >> (((int) ((short) (-14702))) + (14731))) << (((int) (struct_obj_2.member_5_1)) - (25749))))))))))
+ {
+ signed char var_463 = (short) (((int) ((short) (((int) (var_6)) != (~((int) (var_17)))))) > (((int) ((short) (((int) (125)) * ((int) (struct_obj_4.member_2_0))))) / (~(((int) (struct_obj_8.member_4_7)) * ((int) (struct_obj_9.member_2_1.member_1_0))))));
+ signed char var_464 = (unsigned short) (((int) ((((int) (var_239)) || (((int) (7)) && ((int) (-32493)))) != (((int) ((signed char) (var_10))) && (-((int) (var_14)))))) & (((~((((int) (-16750)) + (2147483647)) << ((int) (var_49)))) + (2147483647)) >> (((((int) (struct_obj_1.member_5_2)) | ((int) (struct_obj_2.member_5_1))) | (((int) (var_38)) & ((int) (5832)))) - (65230))));
+ short var_465 = (unsigned short) ((!((int) (struct_obj_4.member_2_1.member_1_3))) * ((-(((int) (-30177)) * ((int) (var_61)))) * ((~((int) (struct_obj_4.member_2_1.member_1_1))) / (((int) (5831)) * ((int) (var_40))))));
+ var_53 = (short) (((int) (var_23)) < ((int) ((-(((((int) (-65)) + (2147483647)) >> (((int) (-13186)) + (13192))) || ((int) (((int) (((int) (((int) (struct_obj_4.member_2_7)) > ((~((int) (struct_obj_4.member_2_0))) | ((int) ((short) (var_35)))))) > (~(~(((int) (39209)) ^ ((int) (struct_obj_4.member_2_1.member_1_3))))))) != ((int) (((int) ((short) (((int) (((int) (var_14)) == ((int) (struct_obj_3.member_5_2)))) * ((int) (((int) (struct_obj_4.member_2_3.member_1_3)) >= ((int) (56773))))))) <= (((((int) (var_13)) + (2147483647)) >> (((int) ((short) (-14702))) + (14731))) << (((int) (struct_obj_2.member_5_1)) - (25749))))))))) < ((((int) (-21429)) + (2147483647)) >> ((!((int) (16614))) && ((int) (13925)))))));
+ signed char var_466 = (~(~(~(~((int) (8094)))))) ^ ((int) ((short) (~((int) ((signed char) (~((int) (-104))))))));
+ signed char var_467 = ((int) ((signed char) (~((int) ((signed char) (~((int) (struct_obj_2.member_5_1)))))))) | (~((int) ((short) (-42))));
+ var_468 = (signed char) (((!((int) (struct_obj_4.member_2_3.member_1_3))) * ((int) ((unsigned short) ((((int) (struct_obj_8.member_4_7)) * ((int) (65006))) / (-((int) (struct_obj_8.member_4_1.member_3_1.member_1_1))))))) < (~(((((int) (struct_obj_8.member_4_9.member_1_0)) ^ ((int) (struct_obj_5.member_1_0))) ^ (((int) (2436)) | ((int) (var_37)))) ^ (~(~((int) (var_467)))))));
+ }
+
+ }
+
+ }
+
+ short var_469 = (~(((int) ((unsigned short) (var_36))) & (((int) ((unsigned short) (var_18))) & (~((int) (struct_obj_2.member_5_0)))))) ^ ((int) ((short) (~((((int) (var_10)) >> (((int) (struct_obj_2.member_5_1)) - (25743))) << ((~((int) (var_49))) + (31))))));
+ signed char var_470 = (~(~((int) ((signed char) ((unsigned short) (var_9)))))) != ((((((int) (-2067)) ^ ((int) (struct_obj_8.member_4_4))) ^ (~((int) (var_49)))) | (((~((int) (28770))) + (2147483647)) << (((((((int) (var_45)) | ((int) (var_27))) + (29)) - (25)) - (0)) - (1)))) << ((((int) (var_65)) + (12873)) - (27)));
+ unsigned short var_471 = var_26;
+ unsigned short var_472 = -(-(((int) (59835)) + ((int) (15808))));
+ if ((unsigned short) ((~((((int) (-18340)) ^ ((int) (-18253))) ^ (~((int) (-24880))))) | ((int) (-126))))
+ {
+ unsigned short var_473 = ((~((((int) (struct_obj_1.member_5_2)) * ((int) (5330))) / (((int) (struct_obj_1.member_5_2)) * ((int) (101))))) * ((int) (struct_obj_8.member_4_3))) | (+(((int) (7754)) + ((((int) (struct_obj_2.member_5_3)) * ((int) (var_48))) - ((int) (struct_obj_3.member_5_2)))));
+ if ((~((int) ((unsigned short) ((unsigned short) (-((int) (15894))))))) >= (!(((!((int) (12826))) * (((int) (127)) * ((int) (var_36)))) * ((int) ((signed char) (((int) (-15438)) * ((int) (var_32))))))))
+ {
+ unsigned short var_474 = ((int) (struct_obj_3.member_5_2)) ^ (!((int) (((int) ((signed char) (((int) (struct_obj_6.member_5_3)) * ((int) (var_4))))) <= ((int) (((int) ((signed char) (var_12))) < (((int) (46)) * ((int) (37))))))));
+ short var_475 = (short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2))));
+ unsigned short var_476 = ((int) (10092)) > ((int) ((((int) (((int) (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) <= ((int) (struct_obj_6.member_5_0)))) == (~((int) (17336))))) & (((((int) (-11297)) + (2147483647)) >> (((int) (var_52)) - (9862))) & ((int) (var_63)))) > ((~((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))) ^ ((~((int) (struct_obj_9.member_2_7))) | (((int) (-28444)) ^ ((int) (2438)))))));
+ unsigned short var_477 = ((int) (struct_obj_9.member_2_1.member_1_3)) << ((~(~((((int) (var_50)) | ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))) & ((int) ((signed char) (-123)))))) + (132));
+ unsigned short var_478 = ((~((int) ((unsigned short) ((((int) (62522)) * ((int) (struct_obj_3.member_5_1))) - ((int) (124)))))) + (2147483647)) >> (((int) (struct_obj_3.member_5_2)) - (59812));
+ unsigned short var_479 = ~((int) ((((int) (((int) ((signed char) (21844))) <= ((int) (((int) (var_18)) <= ((int) (var_24)))))) & ((~((int) (var_26))) % (((int) (46805)) && ((int) (var_469))))) != (((int) (struct_obj_3.member_5_2)) - (((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2)))))) - ((int) (struct_obj_9.member_2_1.member_1_1))))));
+ short var_480 = ((+((((int) (8636)) - ((int) (-105))) + (((int) (-27878)) - ((int) (61359))))) && (~((~((int) (var_28))) | ((int) ((short) (18641)))))) && ((int) ((signed char) ((~(((int) (-99)) * ((int) (96)))) / (((int) (10930)) * ((int) (-99))))));
+ if ((((int) (struct_obj_8.member_4_2)) && ((int) ((short) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2)))))))) || (!((int) ((short) ((!((int) (889))) && (((int) (var_29)) && ((int) (86))))))))
+ {
+ signed char var_481 = ~(~(((((int) (struct_obj_4.member_2_3.member_1_0)) * ((int) (var_4))) * (~((int) (17223)))) / (~(((int) (545)) * ((int) (var_44))))));
+ short var_482 = ((~(~(((int) (var_479)) >> (((int) (struct_obj_8.member_4_1.member_3_0)) - (649))))) | ((((~((int) (struct_obj_4.member_2_0))) + (2147483647)) >> ((((int) (var_481)) ^ ((int) (var_64))) + (63))) << (((~(((int) (struct_obj_9.member_2_1.member_1_0)) | ((int) (var_471)))) + (14662)) - (23)))) & (~(((((int) (-26622)) & ((int) (13554))) ^ ((int) (47104))) | ((((int) (12106)) ^ ((int) (29))) & (((int) (15902)) | ((int) (40455))))));
+ signed char var_483 = -(((((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2)))))) - (((int) (struct_obj_8.member_4_2)) - ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)))) + (-((int) ((unsigned short) (struct_obj_1.member_5_3))))) - ((-(((int) (var_470)) - ((int) (-23)))) - ((((int) (-24447)) - ((int) (var_33))) - (((int) (struct_obj_7.member_1_2)) + ((int) (99))))));
+ unsigned short var_484 = ~((((int) (var_469)) * ((int) ((signed char) (((int) (var_8)) * ((int) (var_17)))))) * (-((-((int) (-8))) / (((int) (struct_obj_8.member_4_6)) * ((int) (struct_obj_4.member_2_3.member_1_3))))));
+ unsigned short var_485 = ((int) ((signed char) (!(!((int) ((unsigned short) (var_6))))))) % ((int) ((signed char) (struct_obj_3.member_5_2)));
+ short var_486 = (signed char) (!((((int) (struct_obj_3.member_5_2)) * ((int) ((short) (var_1)))) / (-(+((int) (-32650))))));
+ var_41 = (unsigned short) (~((int) (struct_obj_3.member_5_2)));
+ unsigned short var_487 = !(((~((int) ((signed char) (var_48)))) + ((int) ((signed char) (!((((int) (struct_obj_3.member_5_2)) * ((int) ((short) (var_1)))) / (-(+((int) (-32650))))))))) & ((int) (((int) (var_61)) >= ((int) ((unsigned short) (var_28))))));
+ signed char var_488 = ((((((int) (21529)) ^ ((int) (4132))) | ((int) ((signed char) (!((((int) (struct_obj_3.member_5_2)) * ((int) ((short) (var_1)))) / (-(+((int) (-32650))))))))) & (~(~((int) (var_49))))) ^ ((~(((int) (struct_obj_8.member_4_1.member_3_0)) | ((int) (-6)))) ^ (~(((int) (var_10)) | ((int) (var_55)))))) & ((((((int) (28)) ^ ((int) (34913))) | (((int) (27968)) & ((int) (-10524)))) & ((int) (-28484))) & ((int) ((unsigned short) (91))));
+ signed char var_489 = -63;
+ }
+ else
+ {
+ short var_490 = (((((int) ((signed char) (var_41))) * ((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2))))))) * (!((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2)))))))) * (((int) ((((int) (-53)) * ((int) (var_46))) <= ((int) (var_51)))) & ((((int) (var_2)) ^ ((int) (var_60))) % (((int) (var_45)) || ((int) (18)))))) >= ((((int) (-108)) & (((int) ((unsigned short) (var_29))) / (((int) (-6368)) * ((int) (53451))))) & (((int) (((int) ((unsigned short) (var_48))) >= (((int) (64011)) + ((int) (struct_obj_4.member_2_3.member_1_3))))) ^ ((((int) (var_20)) + ((int) (-88))) + (((int) (var_61)) || ((int) (9688))))));
+ unsigned short var_491 = ((int) (var_33)) >> ((int) ((((int) ((short) (+((int) (struct_obj_1.member_5_3))))) * (((-(((int) (var_28)) * ((int) (struct_obj_2.member_5_3)))) * (((int) ((short) (var_14))) / (((int) (16571)) * ((int) (59287))))) * ((int) (43731)))) < (((((int) (struct_obj_4.member_2_6)) / ((int) (var_66))) * ((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2))))))) & (~(~((int) (struct_obj_9.member_2_7)))))));
+ short var_492 = (((int) ((short) (~(((int) (-93)) || ((int) (-125)))))) || ((int) ((~(((int) (struct_obj_4.member_2_6)) >> (((int) (struct_obj_8.member_4_6)) + (13828)))) == ((int) (struct_obj_8.member_4_7))))) >> ((int) (((((int) (31254)) << (((((int) (-32124)) ^ ((int) (21005))) + (12173)) - (11))) >> ((int) (struct_obj_8.member_4_9.member_1_0))) > (-((int) ((((int) (var_59)) | ((int) (var_490))) <= (((int) (var_65)) & ((int) (var_19))))))));
+ unsigned short var_493 = ((int) ((unsigned short) (!(((int) (((int) (var_490)) >= ((int) (-22338)))) && (~((int) (struct_obj_8.member_4_6))))))) > (((int) (((int) ((~((int) (-5961))) < ((int) (var_58)))) < ((((int) (27882)) + ((int) (-8226))) | (~((int) (var_22)))))) & (!((int) (var_7))));
+ short var_494 = (unsigned short) (~((int) (((int) (15)) < ((~((int) (-9))) % ((int) ((short) (61065)))))));
+ }
+
+ if (((((((int) (-6660)) & ((int) (11))) | (((int) (27466)) | ((int) (-98)))) & ((((int) (43475)) & ((int) (20006))) ^ ((int) ((signed char) (28278))))) ^ (~(((int) (-60)) ^ (~((int) (28567)))))) | ((((int) (struct_obj_3.member_5_1)) & (~((int) ((unsigned short) (var_476))))) | ((~(((int) (struct_obj_8.member_4_6)) ^ ((int) (struct_obj_10.member_1_3)))) ^ ((((int) (var_476)) ^ ((int) (struct_obj_8.member_4_9.member_1_0))) & ((int) ((signed char) (struct_obj_1.member_5_2)))))))
+ {
+ signed char var_495 = -(~(~(((int) (39754)) || ((int) ((unsigned short) (10557))))));
+ unsigned short var_496 = (~(~((int) (((int) (((int) (40028)) < ((int) (46)))) >= (((int) (-9194)) || ((int) (-122))))))) != (((int) (19860)) % ((int) ((signed char) (-((int) (var_20))))));
+ unsigned short var_497 = (-(((((int) (struct_obj_4.member_2_6)) / ((int) (var_479))) - (((int) (9407)) + ((int) (var_35)))) * (+((int) ((unsigned short) (25874)))))) && ((int) ((((int) ((short) (struct_obj_8.member_4_5))) & (~(((int) (struct_obj_1.member_5_3)) | ((int) (var_26))))) != (((int) ((short) ((((((int) (var_25)) | ((int) (-14169))) ^ (((int) (var_8)) ^ ((int) (4475)))) | ((((int) (var_28)) ^ ((int) (var_15))) & (~((int) (var_29))))) < ((((int) (var_11)) >> (((int) (var_13)) ^ ((int) (var_13)))) | ((int) (struct_obj_3.member_5_2)))))) * (((int) ((short) (var_17))) * ((int) ((signed char) (var_54)))))));
+ signed char var_498 = ((int) (((int) ((short) ((((int) (var_11)) && ((int) (struct_obj_10.member_1_2))) && (!((int) (12032)))))) < (((-((int) (struct_obj_9.member_2_4))) * ((int) ((signed char) (-((int) (var_20)))))) >> ((((int) (var_495)) & ((int) (var_29))) & (!((int) (struct_obj_4.member_2_1.member_1_3))))))) != (((int) ((unsigned short) (~((int) (var_51))))) ^ ((((int) ((short) (struct_obj_1.member_5_3))) ^ (~((int) (struct_obj_4.member_2_1.member_1_0)))) | (((int) ((short) (var_32))) ^ ((int) ((signed char) (struct_obj_4.member_2_1.member_1_1))))));
+ signed char var_499 = ((int) (-23634)) >= (~((~(~((int) (struct_obj_3.member_5_2)))) & ((int) (var_58))));
+ }
+ else
+ {
+ var_500 = (signed char) (-107);
+ short var_501 = (signed char) (((int) (((((int) (-24644)) * ((int) (-5259))) * (!((int) (-106)))) >= (~((int) ((short) (23525)))))) * (((int) (((int) ((short) (7351))) != ((int) ((short) (12121))))) * ((int) (-13473))));
+ var_52 = (short) (~((int) (var_474)));
+ unsigned short var_502 = ((int) ((signed char) (-((int) (var_20))))) < ((int) ((short) ((+(((int) (var_66)) + ((int) (var_51)))) - (-(((int) (var_476)) + ((int) (var_16)))))));
+ short var_503 = struct_obj_3.member_5_2;
+ short var_504 = var_32;
+ unsigned short var_505 = ((int) ((unsigned short) (((((int) (var_43)) * ((int) (585))) / ((int) ((signed char) (struct_obj_5.member_1_0)))) * (((int) ((unsigned short) (struct_obj_2.member_5_3))) / (((int) (var_10)) * ((int) (22670))))))) * ((+((int) ((signed char) (((int) (61178)) / ((int) (63555)))))) * (!((!((int) (var_469))) * (-((int) (var_25))))));
+ }
+
+ }
+
+ signed char var_506 = var_31;
+ unsigned short var_507 = (((int) (var_26)) | (~((int) (var_47)))) % ((~(-(((int) (var_43)) * ((int) (33232))))) & (((int) (((int) (((int) (27)) >= ((int) (-76)))) != ((int) (((int) (5702)) != ((int) (-95)))))) + ((int) (2753))));
+ if (!((int) (((int) ((~(((int) (28215)) || ((int) (17957)))) <= ((((int) (51658)) ^ ((int) (23571))) & (((int) (53850)) ^ ((int) (-59)))))) >= ((int) ((signed char) ((((int) (struct_obj_10.member_1_2)) / ((int) (struct_obj_1.member_5_1))) % ((int) (var_29))))))))
+ {
+ if (-((int) ((~((~((int) (123))) - (~((int) (var_33))))) == (((int) (((int) (((int) (var_16)) >= ((int) (struct_obj_6.member_5_1)))) != (((int) (var_3)) | ((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))))) & (~((int) (7351)))))))
+ {
+ signed char var_508 = (signed char) (((int) (struct_obj_3.member_5_2)) & ((int) (var_58)));
+ short var_509 = (+((!((int) ((unsigned short) (-21610)))) >> (((int) ((signed char) (((int) (struct_obj_8.member_4_5)) * ((int) (113))))) + (81)))) % ((((int) ((signed char) ((signed char) (((int) (37329)) | ((int) (93)))))) + (2147483647)) << ((((int) ((unsigned short) ((((int) (6310)) << (((int) (32576)) - (32569))) | (((int) (49981)) >> (((int) (-4570)) + (4580)))))) - (21295)) - (1)));
+ signed char var_510 = ((int) (var_26)) <= ((int) (((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))) <= ((int) (((!((int) (var_52))) - (((int) (var_31)) | ((int) (var_23)))) == ((int) ((signed char) (-((int) (-2995)))))))));
+ signed char var_511 = ~(((int) ((short) ((~((int) (-11638))) & (((int) (8453)) & ((int) (-22258)))))) ^ (~(~((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))));
+ unsigned short var_512 = (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) >> (((int) (struct_obj_9.member_2_1.member_1_1)) - (31954))) != ((int) ((((int) (struct_obj_4.member_2_5)) || (!((int) ((signed char) (var_44))))) < ((int) ((unsigned short) (((int) (((int) (-26302)) == ((int) (20343)))) > ((int) ((short) (-28144))))))));
+ short var_513 = ((int) ((unsigned short) (-16))) * ((int) (var_16));
+ var_514 = (short) (~(((~((int) (struct_obj_3.member_5_2))) & (~(~((int) (var_20))))) ^ (((int) (struct_obj_4.member_2_3.member_1_2)) & ((int) (struct_obj_8.member_4_9.member_1_2)))));
+ short var_515 = ~((int) ((short) ((unsigned short) ((signed char) (((int) (var_19)) ^ ((int) (var_12)))))));
+ signed char var_516 = -((int) (var_66));
+ unsigned short var_517 = struct_obj_1.member_5_0;
+ }
+ else
+ {
+ short var_518 = var_19;
+ unsigned short var_519 = (short) (((int) ((short) (+((int) ((unsigned short) (var_12)))))) & (((!((int) (var_35))) | ((int) (((int) (var_7)) < ((int) (struct_obj_4.member_2_1.member_1_3))))) || (~((int) (((int) (17060)) <= ((int) (10237)))))));
+ unsigned short var_520 = (((int) ((((((int) (-30670)) + (2147483647)) << (((((int) (-18058)) + (18075)) - (16)) - (1))) - (((int) (-4556)) & ((int) (-56)))) < ((((int) (struct_obj_6.member_5_3)) && ((int) (struct_obj_7.member_1_0))) || ((int) (var_27))))) + ((int) (struct_obj_8.member_4_5))) - (~((int) ((unsigned short) ((((int) (6497)) - ((int) (var_56))) & (-((int) (var_29)))))));
+ signed char var_521 = (unsigned short) (~((int) (struct_obj_3.member_5_2)));
+ var_522 = (signed char) ((((+(+(+((int) (45430))))) + (((int) (-2768)) * ((int) ((signed char) (((int) (24766)) * ((int) (6852))))))) + (2147483647)) << (((((((int) (-103)) + (108)) - (4)) - (0)) - (0)) - (1)));
+ short var_523 = ((~((int) ((!((int) (((int) (7275)) > ((int) (3644))))) == ((((int) (12413)) << (((int) (19590)) - (19580))) >> ((((int) (115)) & ((int) (55843))) - (26)))))) + (2147483647)) >> (((-(+(+((int) (var_507))))) - ((((int) ((short) (var_61))) + (((int) (42857)) + ((int) (var_1)))) - ((-((int) (var_7))) * ((int) (16))))) + (110426));
+ short var_524 = (~(~((((int) (var_30)) ^ ((int) (struct_obj_8.member_4_4))) & (((int) (var_40)) ^ ((int) (struct_obj_4.member_2_6)))))) > (~((~(((int) (var_1)) * ((int) (var_520)))) / ((((int) (struct_obj_5.member_1_0)) * ((int) (struct_obj_8.member_4_6))) / ((int) ((short) (struct_obj_10.member_1_3))))));
+ signed char var_525 = (((int) ((signed char) (!(((int) (126)) & ((int) (var_36)))))) & (((int) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) > ((int) ((~(+((int) (28029)))) <= ((int) ((unsigned short) (((int) (-1114)) ^ ((int) (struct_obj_4.member_2_6))))))))) - (((int) ((short) (((~((int) (1416))) + (2147483647)) >> (((int) (-93)) + (101))))) && (((((int) (24281)) & ((int) (struct_obj_4.member_2_1.member_1_1))) >> ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))) >> (((int) (var_30)) - (42699)))))) || (((int) (((((int) ((unsigned short) (~((int) (8))))) >> (((int) (25621)) - (25605))) | (((~((int) (var_31))) << (((((int) (struct_obj_4.member_2_4)) + (2147483647)) << ((((int) (-62)) + (71)) - (9))) - (2147464435))) >> (((int) (4111)) >> (((int) (19804)) - (19790))))) >= (((((int) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) > ((int) ((~(+((int) (28029)))) <= ((int) ((unsigned short) (((int) (-1114)) ^ ((int) (struct_obj_4.member_2_6))))))))) - (((int) ((short) (((~((int) (1416))) + (2147483647)) >> (((int) (-93)) + (101))))) && (((((int) (24281)) & ((int) (struct_obj_4.member_2_1.member_1_1))) >> ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))) >> (((int) (var_30)) - (42699))))) & ((int) (var_3))) & (!(!(((int) (struct_obj_4.member_2_4)) && ((int) (var_3)))))))) | ((~(~((int) (9)))) & ((((int) (16613)) ^ ((int) (-20))) ^ (~((int) (-10292))))));
+ var_36 = (short) (((~((!((int) (-104))) * (((int) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) > ((int) ((~(+((int) (28029)))) <= ((int) ((unsigned short) (((int) (-1114)) ^ ((int) (struct_obj_4.member_2_6))))))))) - (((int) ((short) (((~((int) (1416))) + (2147483647)) >> (((int) (-93)) + (101))))) && (((((int) (24281)) & ((int) (struct_obj_4.member_2_1.member_1_1))) >> ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))) >> (((int) (var_30)) - (42699))))))) * (-((int) ((unsigned short) (((int) (struct_obj_1.member_5_1)) * ((int) (10162))))))) || ((int) (struct_obj_5.member_1_0)));
+ }
+
+ signed char var_526 = (((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))) && ((int) (27198))) % ((((int) ((((int) (57392)) & ((int) (50780))) == ((int) ((short) (54035))))) & (+((int) (((int) (13979)) <= ((int) (5855)))))) || ((((int) (6763)) + ((int) (39071))) + ((int) (struct_obj_3.member_5_2))));
+ var_64 = (signed char) ((signed char) (!(~((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))));
+ if ((~(((((int) (struct_obj_4.member_2_3.member_1_0)) || ((int) (30335))) % (((int) (var_43)) || ((int) (25266)))) | (+(+((int) (var_52)))))) <= ((int) ((signed char) (((~((int) (struct_obj_8.member_4_7))) | (((int) (var_61)) | ((int) (var_5)))) | (((int) ((short) (struct_obj_6.member_5_3))) ^ (((int) (struct_obj_1.member_5_2)) & ((int) (struct_obj_6.member_5_1))))))))
+ {
+ signed char var_527 = ((!((int) (struct_obj_3.member_5_2))) && ((int) (var_41))) >= ((((int) (struct_obj_3.member_5_2)) | ((int) ((((int) (struct_obj_4.member_2_1.member_1_3)) - ((int) (19837))) != (!((int) (struct_obj_10.member_1_3)))))) + (((~((int) (var_64))) ^ ((int) (var_37))) & (~(((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)) | ((int) (var_62))))));
+ short var_528 = struct_obj_9.member_2_0;
+ signed char var_529 = (((int) (struct_obj_3.member_5_2)) || ((((int) ((signed char) (var_17))) || (((int) (var_38)) && ((int) (var_36)))) || ((int) ((short) (((int) (var_3)) && ((int) (var_15))))))) != (!((int) ((signed char) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))));
+ short var_530 = !((int) ((signed char) ((short) (~(((int) (-6761)) * ((int) (var_527)))))));
+ unsigned short var_531 = (((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))));
+ }
+
+ if ((-(((int) ((short) (((int) (var_507)) * ((int) (var_59))))) * (+(((int) (var_63)) * ((int) (var_526)))))) + (((+((int) ((unsigned short) (76)))) + ((int) ((unsigned short) (+((int) (11621)))))) * (((int) (95)) + ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))))))
+ {
+ unsigned short var_532 = ((int) (((int) ((short) ((((int) (23716)) << (((int) (var_38)) - (38))) || (~((int) (var_47)))))) < (((int) ((unsigned short) (25887))) | ((-((int) (41298))) - ((int) (((int) (-91)) > ((int) (35354)))))))) + ((int) ((((int) (((int) (((int) (-71)) == ((int) (struct_obj_6.member_5_3)))) < (~((int) (var_18))))) >> ((~(!((int) (struct_obj_3.member_5_1)))) + (27))) > ((-((int) (((int) (struct_obj_3.member_5_0)) <= ((int) (var_6))))) - ((int) ((signed char) (((int) (65033)) + ((int) (struct_obj_3.member_5_0))))))));
+ short var_533 = (short) ((((((int) (struct_obj_9.member_2_1.member_1_3)) >> ((int) (var_470))) << (((int) (-34)) + (50))) || (((int) ((signed char) (30726))) / (((int) (struct_obj_8.member_4_4)) + ((int) (struct_obj_4.member_2_4))))) * ((int) (((int) (struct_obj_9.member_2_7)) != (((int) (var_27)) + (((int) (struct_obj_2.member_5_1)) || ((int) (struct_obj_8.member_4_6)))))));
+ short var_534 = ~((!((!((int) (-8725))) * (((int) (var_18)) * ((int) (var_24))))) * ((int) ((unsigned short) (12434))));
+ unsigned short var_535 = (short) (((int) ((unsigned short) ((signed char) (((int) (var_27)) || ((int) (var_24)))))) && ((!(!((int) (var_17)))) && ((int) ((short) (((int) (-42)) || ((int) (32757)))))));
+ signed char var_536 = ~((int) (struct_obj_4.member_2_3.member_1_2));
+ var_62 = (unsigned short) (var_10);
+ signed char var_537 = ((int) (((int) ((~(~((int) (49907)))) != (((int) (((int) (-19054)) <= ((int) (var_43)))) + ((int) ((signed char) (17511)))))) == ((int) (10634)))) < (((int) (struct_obj_6.member_5_3)) - ((int) (((int) ((((int) (var_64)) * ((int) (var_21))) >= (((int) (var_26)) || ((int) (struct_obj_9.member_2_2))))) < ((int) (var_53)))));
+ unsigned short var_538 = +((int) (var_470));
+ signed char var_539 = var_27;
+ }
+ else
+ {
+ unsigned short var_540 = (signed char) (((int) ((signed char) (~(!((int) (-16)))))) | (~(-((int) (((int) (7587)) <= ((int) (var_45)))))));
+ unsigned short var_541 = !((((((int) ((signed char) (-121))) + (2147483647)) >> ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) || (~(((int) (struct_obj_4.member_2_3.member_1_1)) * ((int) (var_469))))) || (!((int) ((short) (((int) (-12)) * ((int) (18)))))));
+ short var_542 = -(+((int) (var_27)));
+ var_543 = (signed char) ((-(((((int) (64835)) >> (((int) (1187)) - (1187))) >> ((~((int) (var_25))) + (149))) >> (((int) ((short) (((int) (struct_obj_7.member_1_2)) | ((int) (struct_obj_4.member_2_1.member_1_1))))) + (128)))) / ((int) ((((~((int) (struct_obj_4.member_2_3.member_1_3))) | (~((int) (-17256)))) & ((int) (struct_obj_8.member_4_1.member_3_1.member_1_0))) != (~(-((int) ((signed char) (var_2))))))));
+ var_544 = (unsigned short) ((((+(((int) (var_42)) * ((int) (struct_obj_4.member_2_3.member_1_3)))) - ((int) ((short) ((unsigned short) (117))))) + ((int) ((short) ((((int) (106)) * ((int) (12343))) - (((int) (6)) + ((int) (var_53))))))) > ((-((((int) (var_13)) * ((int) (19559))) * (((int) (var_469)) * ((int) (var_46))))) * ((((int) ((unsigned short) (-19))) / (((int) (20823)) * ((int) (var_4)))) * ((((int) (29348)) * ((int) (32247))) / ((int) ((signed char) (var_24)))))));
+ short var_545 = -((int) ((signed char) ((short) ((~((int) (1578))) ^ ((int) ((signed char) (26515)))))));
+ short var_546 = ((~(~((((int) (struct_obj_4.member_2_7)) + (2147483647)) << (((int) (var_14)) - (26))))) | ((int) ((short) (((int) ((short) (struct_obj_4.member_2_0))) ^ (((int) (var_66)) & ((int) (-119))))))) % ((int) ((signed char) ((unsigned short) (~(((int) (11516)) & ((int) (var_545)))))));
+ var_547 = (signed char) ((short) (var_25));
+ var_59 = (unsigned short) (~(((int) (var_41)) << (((((~((int) (struct_obj_4.member_2_6))) | (((int) (var_16)) >> (((int) (struct_obj_7.member_1_0)) + (102)))) + (2147483647)) << (((((((((int) ((short) (struct_obj_8.member_4_1.member_3_1.member_1_2))) ^ ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) + (78)) - (2)) - (0)) - (0)) - (0)) - (1))) - (2147427589))));
+ }
+
+ short var_548 = !(((!(((int) (var_54)) && ((int) (var_11)))) || ((((int) (var_18)) || ((int) (var_7))) && (((int) (var_16)) || ((int) (struct_obj_9.member_2_2))))) >> ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))));
+ var_549 = (signed char) (~(~(~((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))));
+ }
+
+ if (struct_obj_4.member_2_5)
+ {
+ unsigned short var_550 = +((int) (((int) ((short) (((int) ((short) (21542))) & ((int) (((int) (var_17)) > ((int) (41361))))))) != ((int) (((int) ((((int) (struct_obj_5.member_1_1)) >> (((int) (var_11)) - (9751))) >= (~((int) (var_30))))) < ((int) ((signed char) ((signed char) (62686))))))));
+ short var_551 = ~((((int) (struct_obj_3.member_5_2)) + (((int) (struct_obj_5.member_1_0)) + (((int) (2)) - ((int) (var_55))))) << ((((-(((int) (struct_obj_6.member_5_3)) || ((int) (var_48)))) / ((int) ((~((int) (var_7))) <= ((int) (((int) (56959)) == ((int) (struct_obj_8.member_4_8))))))) + (29)) - (24)));
+ unsigned short var_552 = (~(~((int) (var_13)))) * (!(!(((int) ((short) (29468))) && (!((int) (struct_obj_8.member_4_2))))));
+ if ((((int) (var_18)) % (+((int) ((signed char) (((int) (11489)) * ((int) (9265))))))) > (((!((int) ((short) (var_40)))) && (((int) (var_471)) || (((int) (44877)) || ((int) (struct_obj_10.member_1_2))))) - ((((int) ((short) (var_47))) && ((int) (struct_obj_3.member_5_2))) || ((((int) (var_48)) || ((int) (3022))) && (!((int) (var_471)))))))
+ {
+ var_48 = (unsigned short) (((int) ((short) (((int) ((unsigned short) (((int) (var_24)) * ((int) (var_41))))) * (~((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))))) & (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) & ((~((int) (((int) (21911)) >= ((int) (71))))) | (~(!((int) (var_21)))))));
+ signed char var_553 = ((+((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) / (~((((int) (struct_obj_6.member_5_3)) << (((int) (var_33)) - (40297))) | ((int) ((signed char) (struct_obj_2.member_5_0)))))) - ((!((!((int) (var_26))) && ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))) * ((int) ((!((int) (((int) (var_63)) <= ((int) (var_550))))) >= ((+((int) (75))) + (((int) (-34)) + ((int) (var_28)))))));
+ unsigned short var_554 = (short) ((-((int) (((int) (((int) (var_48)) != ((int) (-19268)))) > (((int) (var_36)) << (((int) (var_29)) - (51738)))))) < (!(((int) (struct_obj_2.member_5_2)) << (((int) (struct_obj_9.member_2_7)) - (21083)))));
+ unsigned short var_555 = (((((int) (-7012)) ^ (((int) (var_34)) ^ ((int) (struct_obj_3.member_5_1)))) | (~((int) ((short) (366))))) | ((~(((int) (11695)) | ((int) (-51)))) | ((int) ((signed char) ((unsigned short) (var_17)))))) != ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))));
+ signed char var_556 = ((((((int) (struct_obj_4.member_2_3.member_1_1)) && ((int) (struct_obj_6.member_5_2))) || (((int) (var_60)) || ((int) (struct_obj_4.member_2_3.member_1_2)))) || ((int) (-11))) && (!((((int) (var_65)) && ((int) (struct_obj_9.member_2_4))) && (((int) (var_3)) && ((int) (var_51)))))) && (((int) ((unsigned short) ((short) (((int) (var_50)) && ((int) (struct_obj_7.member_1_0)))))) || (((int) ((unsigned short) (!((int) (8848))))) || ((((int) (var_45)) && ((int) (-14256))) || (((int) (var_19)) && ((int) (var_550))))));
+ }
+
+ var_52 = (short) (~((((((int) (var_24)) + ((int) (struct_obj_9.member_2_1.member_1_0))) + (((int) (struct_obj_2.member_5_0)) - ((int) (var_66)))) - (-(((int) (125)) - ((int) (var_40))))) * ((-(((int) (struct_obj_8.member_4_0)) - ((int) (var_6)))) * (+((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))))));
+ if ((((int) (var_29)) >> (-((!((int) (var_57))) && (!((int) (var_39)))))) % ((~(~((int) (((int) (114)) <= ((int) (34964)))))) - (~((int) ((+((int) (-8064))) > (((int) (var_470)) | ((int) (var_507))))))))
+ {
+ unsigned short var_557 = ((((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) & ((int) ((short) ((signed char) (struct_obj_4.member_2_5))))) >> ((int) ((short) (((int) (var_8)) / (((int) (10468)) * ((int) (-23532))))))) >> ((int) (((int) (struct_obj_5.member_1_0)) <= ((int) ((short) (-(((int) (-100)) * ((int) (var_19))))))));
+ var_558 = (short) (!(~((~(((int) (var_31)) - ((int) (var_557)))) >> (((int) ((signed char) (((int) (-19435)) % ((int) (struct_obj_9.member_2_1.member_1_0))))) + (55)))));
+ signed char var_559 = -35;
+ var_64 = (signed char) (((((int) (var_473)) % (~(((int) (struct_obj_6.member_5_2)) && ((int) (struct_obj_4.member_2_1.member_1_0))))) && (!((((int) (-4)) || ((int) (3208))) && (!((int) (-40)))))) == ((int) (struct_obj_1.member_5_3)));
+ signed char var_560 = (((int) (var_13)) & (~((int) (11657)))) ^ ((~((((int) (var_25)) ^ ((int) (var_559))) ^ (((int) (struct_obj_8.member_4_1.member_3_1.member_1_2)) ^ ((int) (-22908))))) ^ ((~((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) & ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))));
+ short var_561 = struct_obj_8.member_4_7;
+ signed char var_562 = ~((int) ((unsigned short) ((unsigned short) ((~((int) (var_561))) & (((int) (var_26)) ^ ((int) (var_469)))))));
+ short var_563 = struct_obj_3.member_5_2;
+ short var_564 = !((int) (((int) (((((int) (struct_obj_3.member_5_0)) & ((int) (struct_obj_9.member_2_1.member_1_0))) % (((int) (var_60)) && ((int) (var_470)))) > (!(+((int) (32834)))))) > (((~((int) (-117))) & (~((int) (struct_obj_3.member_5_2)))) || (-((int) ((signed char) (var_45)))))));
+ short var_565 = ((int) ((((int) ((((int) (-30333)) & ((int) (var_55))) <= ((int) (struct_obj_8.member_4_6)))) & ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))))) < (!(~(~((int) (var_28))))))) > (-((int) (((~((int) (struct_obj_9.member_2_5))) - (((int) (struct_obj_5.member_1_1)) && ((int) (struct_obj_6.member_5_3)))) <= (-(~((int) (21443)))))));
+ }
+
+ short var_566 = ~(((int) ((unsigned short) ((short) (struct_obj_3.member_5_2)))) >> ((~((int) ((unsigned short) (((int) (struct_obj_8.member_4_1.member_3_1.member_1_0)) ^ ((int) (56133)))))) + (9444)));
+ signed char var_567 = ((int) (-25334)) & ((int) ((signed char) (((int) ((((int) (var_46)) >> ((int) (var_46))) >= (+((int) (var_58))))) < ((int) (struct_obj_7.member_1_0)))));
+ if (~(((~(~((int) (var_1)))) ^ (~(((int) (16674)) & ((int) (-20))))) ^ ((int) (7212))))
+ {
+ unsigned short var_568 = (!(+((((int) (8032)) >> (((int) (-71)) + (87))) * ((int) ((signed char) (66)))))) >> ((((int) (struct_obj_3.member_5_2)) << ((int) ((signed char) ((!((int) (-111))) >= ((int) (((int) (-21044)) == ((int) (11494)))))))) - (119619));
+ short var_569 = (unsigned short) ((((((int) (12689)) & ((int) (struct_obj_9.member_2_0))) & (~((int) (29330)))) | ((int) (struct_obj_3.member_5_2))) & (~((int) ((short) (~((int) (struct_obj_8.member_4_4)))))));
+ unsigned short var_570 = ((+((int) ((short) (((int) (-55)) * ((int) (var_41)))))) * (!(-((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))))) && ((int) ((unsigned short) (((((int) (64)) || ((int) (struct_obj_4.member_2_3.member_1_2))) % ((int) (((int) (struct_obj_4.member_2_6)) != ((int) (struct_obj_2.member_5_1))))) * (((int) ((signed char) (-28985))) ^ ((int) (22407))))));
+ unsigned short var_571 = (~((int) (-20282))) & ((int) ((signed char) (((~(((int) (-25685)) ^ ((int) (-111)))) + (2147483647)) << (((~((int) (var_13))) >> ((((int) (struct_obj_6.member_5_3)) << (((int) (22066)) - (22056))) - (12717046))) - (23)))));
+ short var_572 = ((int) ((~(~(((int) (22554)) | ((int) (var_42))))) < (~((((int) (var_12)) >> (((int) (var_36)) - (27368))) >> ((~((int) (680))) + (687)))))) <= (!(!((int) (((int) ((signed char) (struct_obj_10.member_1_3))) >= (+((int) (84)))))));
+ signed char var_573 = ((~(((int) ((signed char) (((int) (59675)) || ((int) (-27347))))) << ((-((int) (struct_obj_3.member_5_2))) + (59837)))) + (2147483647)) >> ((~((int) (struct_obj_3.member_5_2))) + (59829));
+ signed char var_574 = ((~((int) (struct_obj_8.member_4_1.member_3_1.member_1_2))) & (((~((int) (struct_obj_5.member_1_1))) | (~((int) (struct_obj_8.member_4_9.member_1_1)))) | ((~((int) (49))) | ((int) ((short) (((int) (((int) ((signed char) (((int) (25082)) || ((int) (struct_obj_4.member_2_1.member_1_1))))) <= ((int) (69)))) << ((~((+((int) (var_2))) / ((int) (var_34)))) - (233)))))))) && ((int) ((unsigned short) ((~(((int) (var_472)) >> (((int) (35425)) - (35422)))) & ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))));
+ unsigned short var_575 = ~((int) ((~((int) ((unsigned short) (((int) (var_46)) | ((int) (var_20)))))) >= ((int) ((signed char) (((int) (((int) (-21055)) > ((int) (20469)))) % ((int) (55942)))))));
+ }
+ else
+ {
+ signed char var_576 = ((int) ((~(~((int) (((int) (struct_obj_10.member_1_3)) < ((int) (var_58)))))) <= ((int) (((int) ((((int) (-88)) * ((int) (28366))) != ((int) (struct_obj_3.member_5_2)))) < (~(((int) (var_7)) & ((int) (struct_obj_7.member_1_2)))))))) == ((int) ((short) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))));
+ var_51 = (short) (-(~((int) (54))));
+ signed char var_577 = (unsigned short) ((signed char) ((((int) ((unsigned short) (var_12))) ^ (~((int) (var_38)))) | (~(~((int) (struct_obj_8.member_4_0))))));
+ short var_578 = !(~((int) ((short) (((int) (((int) (var_34)) >= ((int) (var_577)))) & ((int) (((int) (var_63)) != ((int) (5719))))))));
+ signed char var_579 = +((((+((int) (40951))) | (~((int) (var_506)))) / ((((int) (27014)) | ((int) (41639))) ^ (((int) (91)) | ((int) (struct_obj_8.member_4_4))))) << ((int) (((int) (struct_obj_9.member_2_5)) != ((int) (((int) ((short) (29451))) >= (+((int) (var_51))))))));
+ unsigned short var_580 = (unsigned short) ((unsigned short) (var_65));
+ short var_581 = ~((int) (struct_obj_3.member_5_2));
+ short var_582 = ((int) (((int) (struct_obj_3.member_5_2)) < ((int) (((-((int) (var_45))) >> ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) >= ((int) ((short) (((int) (20524)) * ((int) (struct_obj_8.member_4_1.member_3_0))))))))) ^ ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475))))))))));
+ unsigned short var_583 = +((((int) ((short) (18))) | ((int) ((signed char) ((short) (var_58))))) | (((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))) & (~(~((int) (var_66))))));
+ signed char var_584 = !((int) ((short) (((int) ((+((int) (var_25))) <= (~((int) (var_567))))) ^ ((int) ((signed char) ((signed char) (3847)))))));
+ }
+
+ }
+
+ if ((signed char) (((int) (var_62)) & ((int) (((int) (var_8)) <= (!((int) ((unsigned short) (1490))))))))
+ {
+ short var_585 = (short) (((int) (-70)) | ((!((int) ((short) (struct_obj_1.member_5_0)))) && ((int) (struct_obj_3.member_5_2))));
+ if (((int) ((signed char) (((int) ((signed char) (((int) (11726)) * ((int) (var_42))))) * (~(~((int) (struct_obj_1.member_5_1))))))) * (((((int) ((signed char) (var_469))) * ((int) (struct_obj_3.member_5_2))) * ((int) ((unsigned short) (~((int) (-20687)))))) * ((int) ((short) ((!((int) (-36))) * ((int) (48610)))))))
+ {
+ signed char var_586 = ~((!(((int) ((signed char) (42650))) / (((int) (struct_obj_9.member_2_2)) | ((int) (struct_obj_9.member_2_2))))) >> ((((int) ((signed char) (((int) (-63)) ^ ((int) (var_472))))) ^ ((~((int) (53084))) | (((int) (var_37)) & ((int) (var_10))))) - (53044)));
+ signed char var_587 = (short) (((int) (24145)) < (~((~((int) (-20377))) | (((int) (var_32)) & ((int) (var_25))))));
+ short var_588 = (((int) ((short) (~((int) (var_15))))) * ((int) ((unsigned short) (~(((int) (var_27)) * ((int) (var_18))))))) / ((int) ((unsigned short) (var_37)));
+ signed char var_589 = (+(!((((int) (-93)) & ((int) (-2615))) | ((int) ((short) (-123)))))) & ((int) (struct_obj_4.member_2_3.member_1_3));
+ signed char var_590 = ((((int) (17070)) << (((int) (19866)) - (19850))) | (((int) ((short) (((int) (var_26)) != ((int) (var_7))))) >> ((int) ((((int) (var_58)) & ((int) (var_53))) < ((int) (((int) (var_40)) <= ((int) (55455)))))))) / ((((int) ((short) (-((int) (var_46))))) + (2147483647)) >> (((int) (struct_obj_10.member_1_3)) + (21794)));
+ var_591 = (signed char) (((~((((int) (struct_obj_6.member_5_0)) << (((int) (var_506)) - (34))) << (((~((int) (var_60))) + (21611)) - (23)))) & ((int) (var_10))) | ((int) (49472)));
+ short var_592 = (unsigned short) ((short) ((signed char) ((!((int) (26965))) ^ (((int) (18006)) + ((int) (36))))));
+ unsigned short var_593 = (short) ((((int) ((((int) (-29676)) * ((int) (25475))) >= ((int) ((unsigned short) (var_26))))) & ((int) ((((int) (struct_obj_8.member_4_6)) ^ ((int) (9575))) != (((int) (10136)) % ((int) (struct_obj_7.member_1_2)))))) <= ((int) (((int) ((((int) (40469)) & ((int) (7768))) == ((int) ((short) (-29505))))) <= (~(((int) (var_11)) | ((int) (struct_obj_3.member_5_0)))))));
+ unsigned short var_594 = (unsigned short) ((((int) ((((int) (-50)) || ((int) (-78))) > (-((int) (struct_obj_3.member_5_1))))) & (-((int) ((unsigned short) (var_18))))) % ((int) (((-((int) (-24452))) * (!((int) (struct_obj_1.member_5_3)))) != (((~((~((int) (12794))) & ((((int) (-15515)) + (2147483647)) >> (((int) (var_30)) - (42687))))) - ((int) ((short) ((((int) (var_32)) || ((int) (var_12))) >> ((~((int) (-11674))) - (11648)))))) && ((int) (struct_obj_4.member_2_3.member_1_1))))));
+ }
+
+ unsigned short var_595 = (unsigned short) (!((int) ((short) (struct_obj_4.member_2_4))));
+ unsigned short var_596 = ((int) (((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) + (((int) (59094)) + ((int) (struct_obj_9.member_2_1.member_1_3)))))) > (((!((int) (var_27))) - ((int) (((int) (var_10)) <= ((int) (var_60))))) && ((((int) ((-127 - 1))) * ((int) (var_40))) * (-((int) (19780))))))) & ((int) ((-((int) (-43))) < (-((int) ((((int) (var_43)) + ((int) (struct_obj_5.member_1_3))) < (((int) (26468)) % ((int) (60870))))))));
+ signed char var_597 = ~((int) ((short) (~((((int) (21151)) ^ ((int) (struct_obj_8.member_4_9.member_1_2))) & (((int) (var_8)) >> (((int) (var_506)) - (22)))))));
+ unsigned short var_598 = ((((int) (20683)) && ((((int) (76)) && ((int) (var_53))) || ((int) ((unsigned short) (var_61))))) || (((((int) (-10814)) && ((int) (22918))) && (((int) (79)) && ((int) (7990)))) || ((((int) (var_10)) || ((int) (var_44))) || (((int) (28091)) || ((int) (16480)))))) * ((((int) ((((int) (9562)) | ((int) (var_64))) < (-((int) (var_38))))) | ((int) (((int) ((unsigned short) (var_506))) < (((int) (struct_obj_4.member_2_2)) || ((int) (var_34)))))) + ((int) ((~((int) (struct_obj_8.member_4_3))) > (~((int) ((unsigned short) (struct_obj_4.member_2_2)))))));
+ struct_obj_10.member_1_2 = (signed char) (-(-(((~((int) (27631))) & (((int) (25634)) | ((int) (struct_obj_4.member_2_3.member_1_2)))) ^ ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))))));
+ if (((int) ((signed char) (((int) ((short) (((int) (var_43)) && ((int) (40250))))) || ((int) ((signed char) (var_25)))))) != ((int) ((+((int) ((~((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) == ((-((int) (var_7))) || (((int) (struct_obj_4.member_2_3.member_1_2)) || ((int) (var_12))))))) <= ((int) ((~(~(((int) (var_27)) & ((int) (-98))))) <= ((int) (((((int) (-10897)) || ((int) (struct_obj_4.member_2_3.member_1_3))) || ((int) (var_14))) != ((int) (struct_obj_3.member_5_2)))))))))
+ {
+ signed char var_599 = (((int) ((short) (struct_obj_9.member_2_0))) ^ (((((int) ((signed char) (var_2))) ^ (~((int) (23693)))) + (2147483647)) << ((((((int) (struct_obj_5.member_1_0)) + (127)) - (21)) - (0)) - (1)))) | ((((~((int) (var_48))) ^ (((int) (struct_obj_3.member_5_0)) & ((int) (55751)))) ^ (~(((int) (-60)) ^ ((int) (150))))) & (~(((int) ((unsigned short) (struct_obj_4.member_2_6))) ^ (((int) (5973)) << (((int) (36731)) - (36715))))));
+ unsigned short var_600 = ~(+(((int) ((short) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) | ((((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)) & ((int) (struct_obj_9.member_2_2))) | (((int) (var_2)) | ((int) (var_506))))));
+ short var_601 = (((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))));
+ unsigned short var_602 = ((int) ((short) ((((int) ((short) (15058))) - (((int) (13)) + ((int) (var_57)))) + (-(((int) (var_53)) + ((int) (var_53))))))) * ((int) (var_39));
+ signed char var_603 = var_6;
+ unsigned short var_604 = ((int) (((int) (-22742)) > (~((((int) (var_24)) ^ ((int) (struct_obj_5.member_1_3))) ^ (((int) (28)) ^ ((int) (var_28))))))) * ((int) ((short) ((((int) (struct_obj_3.member_5_2)) && (!((int) (89)))) | (~((int) (struct_obj_4.member_2_3.member_1_2))))));
+ short var_605 = (signed char) ((((~((int) (-124))) & (~((int) (4435)))) | ((((int) (46344)) & ((int) (48688))) | (((int) (-81)) ^ ((int) (22626))))) | (~(~(((int) (28400)) ^ ((int) (80))))));
+ signed char var_606 = !(((int) ((~(((int) (var_595)) + ((int) (struct_obj_9.member_2_1.member_1_0)))) > (((int) (((int) (37904)) <= ((int) (struct_obj_8.member_4_3)))) & (!((int) (var_8)))))) & (+(((int) ((short) (var_14))) % ((int) ((signed char) (-120))))));
+ unsigned short var_607 = ~((int) ((signed char) (struct_obj_3.member_5_2)));
+ short var_608 = (short) (((int) (((((int) (-67)) ^ ((int) (23314))) & (~((int) (2233)))) == ((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467))))))))))) + ((int) (-24744)));
+ }
+ else
+ {
+ signed char var_609 = ((int) ((~((((int) (var_596)) | ((int) (struct_obj_8.member_4_8))) || ((int) (var_22)))) != ((int) ((short) (((int) (((int) (-29)) != ((int) (36)))) & ((int) (((int) (30)) <= ((int) (struct_obj_4.member_2_1.member_1_0))))))))) && (+((int) (((int) ((unsigned short) (((int) (struct_obj_8.member_4_1.member_3_0)) / ((int) (struct_obj_10.member_1_3))))) < ((int) (((int) (((int) (struct_obj_4.member_2_3.member_1_0)) > ((int) (var_43)))) <= (~((int) (25446))))))));
+ unsigned short var_610 = (short) ((+((((int) (var_49)) - ((int) (struct_obj_8.member_4_9.member_1_0))) + (-((int) (54566))))) * ((int) (var_34)));
+ short var_611 = ((int) ((signed char) (~((int) (struct_obj_2.member_5_1))))) ^ ((((int) ((short) ((signed char) (62)))) << ((((((int) (25)) ^ ((int) (-16))) + (2147483647)) << ((((int) (5683)) & ((int) (-10))) - (5682))) - (2147483607))) | (((int) ((signed char) (((int) (13434)) >> (((int) (-71)) + (97))))) << ((((int) (20025)) >> (((int) (-101)) + (122))) << ((int) ((signed char) (-4597))))));
+ var_42 = (signed char) (((int) (((int) ((unsigned short) ((!((int) (var_21))) * (((int) (var_55)) * ((int) (var_473)))))) <= ((int) (((int) ((((int) (struct_obj_8.member_4_1.member_3_0)) || ((int) (var_38))) <= (((int) (var_56)) * ((int) (struct_obj_8.member_4_9.member_1_0))))) > ((((int) (var_57)) & ((int) (var_37))) || (~((int) (var_5)))))))) <= ((int) (var_62)));
+ short var_612 = (~((int) (((int) ((((int) (-86)) & ((int) (var_1))) >= ((int) (63479)))) != ((int) (var_50))))) % (((int) (((((int) (struct_obj_1.member_5_2)) ^ ((int) (struct_obj_8.member_4_5))) | (((int) (-7103)) ^ ((int) (96)))) < ((int) (var_39)))) | ((int) ((~((int) ((unsigned short) (var_53)))) != (((int) (((int) (struct_obj_3.member_5_0)) != ((int) (struct_obj_6.member_5_1)))) && ((int) ((signed char) (40)))))));
+ }
+
+ if ((~((int) ((signed char) (~((int) (-2706)))))) <= (+(((((int) (struct_obj_9.member_2_1.member_1_3)) + ((int) (-38))) * ((int) ((unsigned short) (var_48)))) * (-(((int) (53)) + ((int) (42)))))))
+ {
+ short var_613 = ((int) ((unsigned short) (~((~((int) (35514))) | (((int) (-11248)) | ((int) (-11218))))))) & (~(~((int) ((short) ((unsigned short) (var_17))))));
+ short var_614 = (((((int) ((signed char) (var_60))) & ((int) (struct_obj_8.member_4_9.member_1_1))) >> ((int) ((signed char) (((int) (var_60)) || ((int) (struct_obj_9.member_2_7)))))) || (((((int) (var_58)) * ((int) (41314))) / (((int) (struct_obj_9.member_2_0)) * ((int) (var_30)))) * ((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))))) * ((int) (((((int) (-2486)) ^ ((int) ((unsigned short) (112)))) % (-((int) ((short) (struct_obj_8.member_4_1.member_3_1.member_1_0))))) < (((int) ((((int) (struct_obj_9.member_2_1.member_1_3)) + ((int) (var_62))) >= (!((int) (struct_obj_2.member_5_0))))) || ((int) ((unsigned short) (+((int) (struct_obj_8.member_4_9.member_1_2))))))));
+ unsigned short var_615 = (unsigned short) (((int) (-15187)) * (!((((int) (82)) * ((int) (7986))) * ((int) ((signed char) (-8101))))));
+ unsigned short var_616 = ((int) (struct_obj_5.member_1_1)) > ((((int) ((+((int) ((~((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) == ((-((int) (var_7))) || (((int) (struct_obj_4.member_2_3.member_1_2)) || ((int) (var_12))))))) <= ((int) ((~(~(((int) (var_27)) & ((int) (-98))))) <= ((int) (((((int) (-10897)) || ((int) (struct_obj_4.member_2_3.member_1_3))) || ((int) (var_14))) != ((int) (struct_obj_3.member_5_2)))))))) & (((int) (struct_obj_3.member_5_2)) >> (((int) ((signed char) (struct_obj_6.member_5_1))) - (108)))) >> (((~(~((int) (struct_obj_10.member_1_0)))) ^ (((int) (var_507)) - (((int) (var_37)) && ((int) (var_47))))) - (2008)));
+ unsigned short var_617 = var_40;
+ unsigned short var_618 = ~(~((~(((int) (-49)) | ((int) (6)))) ^ (~(((int) (-101)) | ((int) (-118))))));
+ var_52 = (short) (((int) ((~((((int) (58053)) * ((int) (-35))) / (((int) (-22)) * ((int) (4112))))) > (((((int) (-100)) & ((int) (34043))) ^ (((int) (10311)) | ((int) (-10654)))) & (~(((int) (-22199)) | ((int) (22289))))))) && (((int) (struct_obj_3.member_5_2)) >> (+((int) ((short) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))))));
+ }
+ else
+ {
+ short var_619 = ((~(((int) ((short) (13900))) * ((int) ((signed char) (-20248))))) * (((((int) (-975)) * ((int) (struct_obj_9.member_2_1.member_1_0))) / (((int) (var_9)) * ((int) (struct_obj_3.member_5_0)))) * ((((int) (5)) * ((int) (28036))) * (!((int) (struct_obj_8.member_4_1.member_3_1.member_1_1)))))) || (((int) ((signed char) (((int) ((unsigned short) (struct_obj_4.member_2_1.member_1_0))) && ((int) ((unsigned short) (var_8)))))) & ((((int) ((unsigned short) (var_41))) ^ (((int) (var_35)) | ((int) (var_9)))) | (((int) ((unsigned short) (struct_obj_3.member_5_3))) ^ (((int) (17186)) >> (((int) (struct_obj_9.member_2_1.member_1_1)) - (31946))))));
+ unsigned short var_620 = (~(((int) ((signed char) (~((int) (var_41))))) & ((int) ((unsigned short) (struct_obj_3.member_5_2))))) / ((int) (-5296));
+ signed char var_621 = var_20;
+ short var_622 = (((int) (struct_obj_6.member_5_0)) | ((~((int) (2))) | (((int) ((signed char) (struct_obj_4.member_2_2))) ^ ((int) ((+((int) ((~((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) == ((-((int) (var_7))) || (((int) (struct_obj_4.member_2_3.member_1_2)) || ((int) (var_12))))))) <= ((int) ((~(~(((int) (var_27)) & ((int) (-98))))) <= ((int) (((((int) (-10897)) || ((int) (struct_obj_4.member_2_3.member_1_3))) || ((int) (var_14))) != ((int) (struct_obj_3.member_5_2))))))))))) ^ ((((int) ((signed char) (~((int) (var_31))))) | ((int) (struct_obj_3.member_5_2))) | ((int) ((unsigned short) ((unsigned short) (~((int) (var_2)))))));
+ short var_623 = ((((int) ((unsigned short) ((signed char) (var_18)))) || (((int) ((+((int) ((~((int) ((((int) ((-((int) ((short) (-4355)))) < (-((int) (struct_obj_3.member_5_2))))) - (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) || ((~((int) (-19743))) * (((int) (58561)) / ((int) (40662)))))) <= ((int) ((signed char) (((int) (((((int) (struct_obj_3.member_5_2)) ^ ((int) (-77))) & (((int) ((short) (~((int) (-10947))))) | ((((int) (var_30)) >> (((int) (145)) - (138))) | ((((int) (-11225)) + (2147483647)) >> (((int) (31473)) - (31471)))))) >= ((int) (((-(-((int) (struct_obj_2.member_5_0)))) * (-((int) ((unsigned short) (var_1))))) > ((int) (((int) ((unsigned short) (~((int) (-5))))) != (((int) (struct_obj_3.member_5_2)) && (((int) (var_17)) << (((int) (var_9)) - (13475)))))))))) <= ((((int) (49)) ^ ((int) (7553))) & ((int) ((signed char) (23467)))))))))) == ((-((int) (var_7))) || (((int) (struct_obj_4.member_2_3.member_1_2)) || ((int) (var_12))))))) <= ((int) ((~(~(((int) (var_27)) & ((int) (-98))))) <= ((int) (((((int) (-10897)) || ((int) (struct_obj_4.member_2_3.member_1_3))) || ((int) (var_14))) != ((int) (struct_obj_3.member_5_2)))))))) && (((int) (2844)) && ((int) (struct_obj_8.member_4_5))))) || (!((((int) (43906)) || ((int) (var_470))) || (((int) (var_27)) && ((int) (var_52)))))) && (((int) ((signed char) ((((int) (-26084)) || ((int) (struct_obj_8.member_4_4))) || (((int) (struct_obj_4.member_2_1.member_1_0)) || ((int) (var_12)))))) || (((int) (var_45)) && ((((int) (struct_obj_8.member_4_9.member_1_0)) || ((int) (var_23))) && ((int) (struct_obj_4.member_2_1.member_1_1)))));
+ signed char var_624 = +(~(((int) ((((int) (4004)) ^ ((int) (var_26))) <= (((int) (var_16)) << (((int) (struct_obj_4.member_2_0)) - (7592))))) << (!((int) (var_51)))));
+ short var_625 = ((int) ((signed char) ((signed char) ((((int) (58)) || ((int) (5530))) >> ((-((int) (var_472))) + (10129)))))) || (+(((((int) (var_624)) * ((int) (struct_obj_10.member_1_3))) * (~((int) (-13129)))) * ((((int) (-6837)) * ((int) (-86))) / (((int) (78)) * ((int) (-2058))))));
+ unsigned short var_626 = -(~(~(~((int) (var_28)))));
+ }
+
+ }
+
+ short var_627 = (((~(((int) (21000)) & ((int) (61917)))) ^ ((((int) (30872)) ^ ((int) (struct_obj_3.member_5_2))) & (((int) (var_472)) & ((int) (var_46))))) | (((((int) (23969)) | ((int) (var_23))) & (((int) (var_38)) ^ ((int) (31735)))) & (~(~((int) (struct_obj_4.member_2_3.member_1_3)))))) & (((((int) (struct_obj_9.member_2_6)) & (~((int) (var_22)))) ^ (((int) (-36)) & (~((int) (var_15))))) | ((int) (struct_obj_4.member_2_4)));
+ }
+
+}
diff --git a/multiple_labels_crash_test/func.ref.s b/multiple_labels_crash_test/func.ref.s
new file mode 100644
index 00000000..3e08e447
--- /dev/null
+++ b/multiple_labels_crash_test/func.ref.s
@@ -0,0 +1,5170 @@
+// File generated by CompCert 3.7
+// Command line: -dmach -S tmp/func.c -o tmp/func.ref.s
+ .text
+ .balign 2
+ .globl foo
+foo:
+ mov x29, sp
+ sub sp, sp, #32
+ str x29, [sp, #0]
+ str x30, [sp, #8]
+ str x19, [sp, #16]
+ str x20, [sp, #24]
+ adrp x16, var_47
+ ldrsb w0, [x16, #:lo12:var_47]
+ movn w16, #5210, lsl #0
+ and w0, w0, w16
+ ubfiz w0, w0, 0, 16
+ cmp w0, #1125
+ cset x0, le
+ cbz w0, .L100
+ adrp x16, var_24
+ ldrsh w0, [x16, #:lo12:var_24]
+ movz w16, #16885, lsl #0
+ eor w0, w0, w16
+ movn w16, #103, lsl #0
+ orr w15, w0, w16
+ adrp x16, struct_obj_4 + 22
+ ldrh w14, [x16, #:lo12:struct_obj_4 + 22]
+ sbfiz w17, w14, 0, 8
+ cmp w15, w17
+ cset x0, le
+ cmp w0, #1
+ cset x0, ne
+ adrp x16, var_58
+ strb w0, [x16, #:lo12:var_58]
+ orr w9, wzr, #1
+ orr w11, wzr, #1
+ adrp x16, struct_obj_4 + 12
+ ldrsb w4, [x16, #:lo12:struct_obj_4 + 12]
+ sub w12, w9, w4
+ adrp x16, var_15
+ ldrh w3, [x16, #:lo12:var_15]
+ sub w7, wzr, w3
+ sbfiz w13, w7, 0, 8
+ sub w13, w13, #43
+ lsl w11, w11, w13
+ sub w0, w12, w11
+ cbnz w0, .L101
+ adrp x16, struct_obj_10 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_10 + 6]
+ sbfiz w5, w0, 0, 8
+ adrp x16, var_31
+ ldrsh w0, [x16, #:lo12:var_31]
+ sub w0, w5, w0
+ add w0, w0, #24576
+ add w0, w0, #2605
+ sub w0, wzr, w0
+ cmp w0, #0
+ cset x0, ne
+ cbz w0, .L102
+.L101:
+ movz w0, #0, lsl #0
+ movz w16, #51591, lsl #0
+ cmp w0, w16
+ cset x0, eq
+ adrp x16, var_27
+ ldrsh w15, [x16, #:lo12:var_27]
+ adrp x16, struct_obj_6 + 4
+ ldrh w29, [x16, #:lo12:struct_obj_6 + 4]
+ and w6, w15, w29
+ orn w4, wzr, w6
+ movz w16, #29499, lsl #0
+ and w9, w4, w16
+ adrp x16, var_23
+ ldrh w17, [x16, #:lo12:var_23]
+ cmp w9, w17
+ cset x17, le
+ lsl w0, w0, w17
+ sbfiz w29, w0, 0, 16
+ adrp x16, var_30
+ ldrh w11, [x16, #:lo12:var_30]
+ adrp x16, var_3
+ ldrsb w5, [x16, #:lo12:var_3]
+ sub w0, w5, #49
+ lsl w10, w11, w0
+ movn w16, #245, lsl #0
+ eor w9, w10, w16
+ cbnz w9, .L103
+ adrp x16, var_9
+ ldrh w14, [x16, #:lo12:var_9]
+ adrp x16, struct_obj_4 + 2
+ ldrsb w17, [x16, #:lo12:struct_obj_4 + 2]
+ movz w16, #53547, lsl #0
+ orr w15, w17, w16
+ sub w12, w15, #53248
+ sub w12, w12, #359
+ asr w3, w14, w12
+ cmp w3, #0
+ cset x11, ne
+ b .L104
+.L103:
+ orr w11, wzr, #1
+.L104:
+ adrp x16, struct_obj_7 + 2
+ ldrsh w4, [x16, #:lo12:struct_obj_7 + 2]
+ movz w13, #53518, lsl #0
+ movk w13, #32767, lsl #16
+ adrp x16, struct_obj_4 + 26
+ ldrsh w5, [x16, #:lo12:struct_obj_4 + 26]
+ adrp x16, var_34
+ ldrsb w12, [x16, #:lo12:var_34]
+ eor w10, w5, w12
+ sub w5, w10, #8192
+ sub w5, w5, #1378
+ asr w6, w13, w5
+ adrp x16, struct_obj_4 + 2
+ ldrsb w5, [x16, #:lo12:struct_obj_4 + 2]
+ orn w1, wzr, w5
+ adrp x16, var_1
+ ldrh w3, [x16, #:lo12:var_1]
+ sbfiz w0, w3, 0, 8
+ adrp x16, var_19
+ ldrsb w7, [x16, #:lo12:var_19]
+ adrp x16, struct_obj_1 + 4
+ ldrh w10, [x16, #:lo12:struct_obj_1 + 4]
+ and w12, w7, w10
+ movz w16, #113, lsl #0
+ and w12, w12, w16
+ orr w0, w0, w12
+ cmp w1, w0
+ cset x0, ne
+ asr w14, w6, w0
+ eor w10, w4, w14
+ orr w16, wzr, #2147483647
+ add w8, w10, w16
+ adrp x16, var_29
+ ldrh w6, [x16, #:lo12:var_29]
+ adrp x16, var_8
+ ldrh w2, [x16, #:lo12:var_8]
+ and w14, w6, w2
+ adrp x16, var_48
+ ldrh w3, [x16, #:lo12:var_48]
+ orr w10, w14, w3
+ adrp x16, struct_obj_8 + 18
+ ldrsh w12, [x16, #:lo12:struct_obj_8 + 18]
+ orn w4, wzr, w12
+ adrp x16, struct_obj_8 + 20
+ ldrsh w3, [x16, #:lo12:struct_obj_8 + 20]
+ ubfiz w1, w3, 0, 16
+ sub w3, w1, #49152
+ sub w3, w3, #2540
+ lsl w7, w4, w3
+ and w10, w10, w7
+ movz w4, #49144, lsl #0
+ adrp x16, struct_obj_5 + 2
+ ldrsh w1, [x16, #:lo12:struct_obj_5 + 2]
+ sub w13, w1, #28672
+ sub w13, w13, #274
+ lsl w17, w4, w13
+ sub w13, wzr, w11
+ add w15, w13, #5
+ lsl w17, w17, w15
+ adrp x16, struct_obj_2 + 2
+ ldrh w11, [x16, #:lo12:struct_obj_2 + 2]
+ movz w16, #27896, lsl #0
+ eor w14, w11, w16
+ adrp x16, var_56
+ ldrh w13, [x16, #:lo12:var_56]
+ orn w15, wzr, w13
+ add w11, w15, #16384
+ add w11, w11, #3806
+ lsl w1, w14, w11
+ eor w2, w17, w1
+ movz w16, #33395, lsl #0
+ movk w16, #1535, lsl #16
+ sub w2, w2, w16
+ lsl w14, w10, w2
+ asr w14, w8, w14
+ cbz w14, .L105
+ adrp x16, struct_obj_3 + 2
+ ldrh w10, [x16, #:lo12:struct_obj_3 + 2]
+ cbz w10, .L106
+ adrp x16, var_18
+ ldrsb w2, [x16, #:lo12:var_18]
+ cmp w2, #0
+ cset x7, ne
+ b .L107
+.L106:
+ movz w7, #0, lsl #0
+.L107:
+ movz w6, #0, lsl #0
+ cbz w6, .L108
+ orr w8, wzr, #1
+ b .L109
+.L108:
+ orr w8, wzr, #1
+.L109:
+ cmp w7, #0
+ cset x6, lt
+ cmp w6, w0
+ cset x17, ge
+ movn w2, #2717, lsl #0
+ adrp x16, struct_obj_9 + 26
+ ldrsh w4, [x16, #:lo12:struct_obj_9 + 26]
+ madd w12, w4, w2, wzr
+ orr w16, wzr, #2147483647
+ add w11, w12, w16
+ orr w3, wzr, w11, asr #3
+ cmp w3, #0
+ cset x10, eq
+ cmp w17, w10
+ cset x10, ne
+ asr w8, w10, w8
+ ubfiz w3, w8, 0, 16
+ cbnz w9, .L110
+ adrp x16, var_9
+ ldrh w10, [x16, #:lo12:var_9]
+ movz w16, #53547, lsl #0
+ orr w1, w5, w16
+ sub w4, w1, #53248
+ sub w4, w4, #359
+ asr w9, w10, w4
+ cmp w9, #0
+ cset x1, ne
+ b .L111
+.L110:
+ orr w1, wzr, #1
+.L111:
+ movz w2, #34812, lsl #0
+ adrp x16, var_13
+ ldrsh w11, [x16, #:lo12:var_13]
+ madd w14, w11, w2, wzr
+ adrp x16, struct_obj_1 + 2
+ ldrh w6, [x16, #:lo12:struct_obj_1 + 2]
+ adrp x16, var_65
+ ldrsh w4, [x16, #:lo12:var_65]
+ madd w9, w6, w4, wzr
+ sdiv w9, w14, w9
+ orr w8, wzr, #62
+ adrp x16, var_35
+ ldrh w2, [x16, #:lo12:var_35]
+ madd w14, w2, w8, wzr
+ cmp w14, #0
+ cset x10, eq
+ madd w15, w9, w10, wzr
+ sub w2, wzr, w0
+ madd w12, w15, w2, wzr
+ sub w1, wzr, w1
+ eor w11, w12, w1
+ adrp x16, var_70
+ strb w11, [x16, #:lo12:var_70]
+ adrp x16, var_30
+ ldrh w7, [x16, #:lo12:var_30]
+ adrp x16, var_3
+ ldrsb w15, [x16, #:lo12:var_3]
+ sub w0, w15, #49
+ lsl w0, w7, w0
+ movn w16, #245, lsl #0
+ eor w0, w0, w16
+ cbnz w0, .L112
+ adrp x16, var_9
+ ldrh w15, [x16, #:lo12:var_9]
+ movz w16, #53547, lsl #0
+ orr w2, w5, w16
+ sub w1, w2, #53248
+ sub w1, w1, #359
+ asr w14, w15, w1
+ cmp w14, #0
+ cset x7, ne
+ b .L113
+.L112:
+ orr w7, wzr, #1
+.L113:
+ sub w10, wzr, w7
+ movz w12, #20687, lsl #0
+ movk w12, #32767, lsl #16
+ adrp x16, var_4
+ ldrh w6, [x16, #:lo12:var_4]
+ sbfiz w14, w6, 0, 16
+ sub w13, w14, #3630
+ asr w5, w12, w13
+ eor w17, w10, w5
+ orr w16, wzr, #2147483647
+ add w15, w17, w16
+ adrp x16, struct_obj_4 + 12
+ ldrsb w12, [x16, #:lo12:struct_obj_4 + 12]
+ orn w2, wzr, w12
+ adrp x16, struct_obj_2 + 2
+ ldrh w11, [x16, #:lo12:struct_obj_2 + 2]
+ orn w2, w2, w11
+ ubfiz w1, w2, 0, 16
+ sub w0, w1, #61440
+ sub w0, w0, #4095
+ lsl w8, w15, w0
+ adrp x16, var_41
+ ldrh w7, [x16, #:lo12:var_41]
+ adrp x16, struct_obj_9 + 22
+ ldrh w5, [x16, #:lo12:struct_obj_9 + 22]
+ adrp x16, struct_obj_9 + 20
+ ldrsh w4, [x16, #:lo12:struct_obj_9 + 20]
+ sub w0, w4, #12288
+ sub w0, w0, #1248
+ lsl w17, w5, w0
+ eor w13, w7, w17
+ eor w0, w8, w13
+ adrp x16, struct_obj_9 + 22
+ strh w0, [x16, #:lo12:struct_obj_9 + 22]
+ movz w8, #35578, lsl #0
+ adrp x16, struct_obj_5
+ ldrsb w2, [x16, #:lo12:struct_obj_5]
+ madd w14, w2, w8, wzr
+ movz w11, #103, lsl #0
+ madd w13, w3, w11, wzr
+ madd w8, w14, w13, wzr
+ adrp x16, var_26
+ ldrh w12, [x16, #:lo12:var_26]
+ cbnz w12, .L105
+ adrp x16, var_34
+ ldrsb w11, [x16, #:lo12:var_34]
+ cmp w11, #0
+ cset x7, ne
+.L105:
+ adrp x16, var_61
+ ldrsb w0, [x16, #:lo12:var_61]
+ adrp x16, var_15
+ ldrh w14, [x16, #:lo12:var_15]
+ orr w10, w0, w14
+ adrp x16, var_52
+ ldrsh w8, [x16, #:lo12:var_52]
+ movz w16, #5914, lsl #0
+ and w0, w8, w16
+ orr w6, w10, w0
+ adrp x16, struct_obj_2
+ ldrsh w10, [x16, #:lo12:struct_obj_2]
+ bic w8, w6, w10
+ adrp x16, var_24
+ ldrsh w10, [x16, #:lo12:var_24]
+ movz w16, #31461, lsl #0
+ orr w10, w10, w16
+ orr w3, w8, w10
+ movz w4, #0, lsl #0
+ sbfiz w0, w4, 0, 8
+ cmp w3, w0
+ cset x3, ne
+ adrp x16, var_78
+ strh w3, [x16, #:lo12:var_78]
+ adrp x16, struct_obj_8
+ ldrh w13, [x16, #:lo12:struct_obj_8]
+ sub w10, wzr, w13
+ cbz w10, .L114
+ adrp x16, struct_obj_4
+ ldrsh w11, [x16, #:lo12:struct_obj_4]
+ cbnz w11, .L115
+ adrp x16, struct_obj_8 + 4
+ ldrsb w6, [x16, #:lo12:struct_obj_8 + 4]
+ cbnz w6, .L115
+ orr w8, wzr, #1
+ cmp w29, #0
+ cset x2, ne
+ adrp x16, struct_obj_1 + 2
+ ldrh w9, [x16, #:lo12:struct_obj_1 + 2]
+ cmp w9, #0
+ csel x0, x8, x2, ne
+.L115:
+ adrp x16, var_54
+ ldrsh w0, [x16, #:lo12:var_54]
+ orr w16, wzr, #2147483647
+ add w17, w0, w16
+ adrp x16, var_62
+ ldrh w14, [x16, #:lo12:var_62]
+ adrp x16, struct_obj_2 + 4
+ ldrh w7, [x16, #:lo12:struct_obj_2 + 4]
+ eor w12, w14, w7
+ sbfiz w29, w12, 0, 16
+ sub w6, w29, #24576
+ sub w6, w6, #440
+ asr w0, w17, w6
+ adrp x16, var_54
+ strh w0, [x16, #:lo12:var_54]
+ adrp x16, var_47
+ ldrsb w0, [x16, #:lo12:var_47]
+ orn w12, wzr, w0
+ adrp x16, struct_obj_7 + 2
+ ldrsh w0, [x16, #:lo12:struct_obj_7 + 2]
+ orr w16, wzr, #2147483647
+ add w13, w0, w16
+ adrp x16, var_18
+ ldrsb w11, [x16, #:lo12:var_18]
+ sub w14, w11, #75
+ asr w3, w13, w14
+ madd w0, w12, w3, wzr
+ cmp w0, #0
+ cset x0, le
+ orn w12, wzr, w0
+ movn w3, #21, lsl #0
+ adrp x16, struct_obj_4 + 18
+ ldrsh w14, [x16, #:lo12:struct_obj_4 + 18]
+ madd w15, w14, w3, wzr
+ movn w6, #32288, lsl #0
+ adrp x16, var_6
+ ldrh w29, [x16, #:lo12:var_6]
+ madd w7, w29, w6, wzr
+ sdiv w2, w15, w7
+ orn w0, wzr, w2
+ adrp x16, struct_obj_2 + 2
+ ldrh w11, [x16, #:lo12:struct_obj_2 + 2]
+ adrp x16, var_4
+ ldrh w7, [x16, #:lo12:var_4]
+ madd w14, w11, w7, wzr
+ adrp x16, var_7
+ ldrsb w1, [x16, #:lo12:var_7]
+ cmp w1, #0
+ cset x8, eq
+ madd w9, w14, w8, wzr
+ orn w7, wzr, w9
+ madd w0, w0, w7, wzr
+ cmp w12, w0
+ cset x0, gt
+ adrp x16, var_82
+ strh w0, [x16, #:lo12:var_82]
+.L114:
+ adrp x16, struct_obj_4 + 18
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 18]
+ cbz w0, .L102
+ adrp x16, struct_obj_2 + 4
+ ldrh w0, [x16, #:lo12:struct_obj_2 + 4]
+ cmp w0, #0
+ cset x0, ne
+.L102:
+ adrp x16, struct_obj_3
+ ldrsh w0, [x16, #:lo12:struct_obj_3]
+ cbnz w0, .L116
+ adrp x16, var_33
+ ldrh w0, [x16, #:lo12:var_33]
+ cbnz w0, .L117
+ adrp x16, var_28
+ ldrsh w0, [x16, #:lo12:var_28]
+ cmp w0, #0
+ cset x0, ne
+ b .L118
+.L117:
+ orr w0, wzr, #1
+ b .L118
+.L116:
+ orr w0, wzr, #1
+.L118:
+ orn w12, wzr, w0
+ adrp x16, var_2
+ ldrh w1, [x16, #:lo12:var_2]
+ adrp x16, struct_obj_4 + 26
+ ldrsh w29, [x16, #:lo12:struct_obj_4 + 26]
+ sub w0, w1, w29
+ sbfiz w15, w0, 0, 8
+ cmp w12, w15
+ b.ge .L119
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ cbnz w7, .L120
+ adrp x16, struct_obj_8 + 22
+ ldrh w13, [x16, #:lo12:struct_obj_8 + 22]
+ cmp w13, #0
+ cset x4, ne
+ b .L121
+.L120:
+ orr w4, wzr, #1
+.L121:
+ eor w15, w4, #1
+ eor w9, w15, #1
+ adrp x16, var_47
+ ldrsb w3, [x16, #:lo12:var_47]
+ cmp w3, #0
+ cset x8, ne
+ movz w16, #14251, lsl #0
+ cmp w8, w16
+ cset x3, le
+ cmp w3, w7
+ cset x8, ne
+ ubfiz w12, w29, 0, 16
+ cmp w8, w12
+ cset x13, ge
+ adrp x16, struct_obj_1
+ ldrsh w12, [x16, #:lo12:struct_obj_1]
+ ubfiz w17, w12, 0, 16
+ orn w4, wzr, w17
+ movz w16, #40329, lsl #0
+ movk w16, #116, lsl #16
+ eor w11, w4, w16
+ eor w15, w13, w11
+ cbz w15, .L122
+ movz w4, #0, lsl #0
+ adrp x16, struct_obj_5
+ ldrsb w7, [x16, #:lo12:struct_obj_5]
+ movz w16, #12154, lsl #0
+ eor w7, w7, w16
+ adrp x16, var_1
+ ldrh w1, [x16, #:lo12:var_1]
+ adrp x16, struct_obj_10 + 6
+ ldrsh w4, [x16, #:lo12:struct_obj_10 + 6]
+ movn w16, #9, lsl #0
+ orr w10, w4, w16
+ eor w29, w1, w10
+ eor w2, w7, w29
+ adrp x16, struct_obj_8 + 26
+ ldrsb w4, [x16, #:lo12:struct_obj_8 + 26]
+ orr w0, w4, w9
+ and w0, w2, w0
+ sbfiz w0, w0, 0, 8
+ adrp x16, var_90
+ strh w0, [x16, #:lo12:var_90]
+ adrp x16, var_16
+ ldrh w0, [x16, #:lo12:var_16]
+ movz w16, #56567, lsl #0
+ eor w12, w0, w16
+ adrp x16, struct_obj_7
+ ldrsb w8, [x16, #:lo12:struct_obj_7]
+ and w14, w12, w8
+ adrp x16, var_8
+ ldrh w11, [x16, #:lo12:var_8]
+ orr w12, w14, w11
+ adrp x16, var_5
+ ldrh w2, [x16, #:lo12:var_5]
+ adrp x16, var_32
+ ldrh w3, [x16, #:lo12:var_32]
+ eon w1, w2, w3
+ adrp x16, var_34
+ ldrsb w4, [x16, #:lo12:var_34]
+ movz w16, #44163, lsl #0
+ and w5, w4, w16
+ sbfiz w9, w5, 0, 8
+ orr w3, w1, w9
+ bic w0, w12, w3
+ adrp x16, var_94
+ strh w0, [x16, #:lo12:var_94]
+ b .L123
+.L122:
+ adrp x16, struct_obj_6 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_6 + 6]
+ adrp x16, var_100
+ strh w0, [x16, #:lo12:var_100]
+.L123:
+ adrp x16, struct_obj_8 + 24
+ ldrh w0, [x16, #:lo12:struct_obj_8 + 24]
+ sbfiz w0, w0, 0, 8
+ adrp x16, var_106
+ strh w0, [x16, #:lo12:var_106]
+ adrp x16, var_55
+ ldrsb w4, [x16, #:lo12:var_55]
+ adrp x16, var_3
+ ldrsb w6, [x16, #:lo12:var_3]
+ adrp x16, struct_obj_2 + 4
+ ldrh w5, [x16, #:lo12:struct_obj_2 + 4]
+ movz w16, #19146, lsl #0
+ orr w2, w5, w16
+ eon w8, w2, w6
+ ubfiz w6, w8, 0, 16
+ adrp x16, struct_obj_8 + 16
+ ldrsb w17, [x16, #:lo12:struct_obj_8 + 16]
+ adrp x16, var_2
+ ldrh w1, [x16, #:lo12:var_2]
+ eon w10, w17, w1
+ movz w16, #33293, lsl #0
+ orr w15, w4, w16
+ adrp x16, struct_obj_4 + 2
+ ldrsb w29, [x16, #:lo12:struct_obj_4 + 2]
+ eon w17, w15, w29
+ and w14, w10, w17
+ and w0, w6, w14
+ cmp w0, #0
+ cset x0, eq
+ adrp x16, var_46
+ strh w0, [x16, #:lo12:var_46]
+ orr w0, wzr, #1
+ adrp x16, var_40
+ strb w0, [x16, #:lo12:var_40]
+ adrp x16, var_7
+ ldrsb w0, [x16, #:lo12:var_7]
+ ubfiz w0, w0, 0, 16
+ cbz w0, .L124
+ adrp x16, struct_obj_8 + 28
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 28]
+ cbz w0, .L124
+ adrp x16, var_11
+ ldrsh w0, [x16, #:lo12:var_11]
+ cmp w0, #0
+ cset x0, ne
+ cbz w0, .L124
+ adrp x16, struct_obj_7 + 2
+ ldrsh w0, [x16, #:lo12:struct_obj_7 + 2]
+ cbnz w0, .L124
+ adrp x16, var_17
+ ldrsh w0, [x16, #:lo12:var_17]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L124
+ adrp x16, var_10
+ ldrh w0, [x16, #:lo12:var_10]
+ b .L124
+.L119:
+ adrp x16, struct_obj_8 + 28
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 28]
+ cbnz w0, .L125
+ adrp x16, struct_obj_4 + 4
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 4]
+ cmp w0, #0
+ cset x0, ne
+ b .L126
+.L125:
+ orr w0, wzr, #1
+.L126:
+ adrp x16, struct_obj_4 + 8
+ ldrsh w12, [x16, #:lo12:struct_obj_4 + 8]
+ adrp x16, struct_obj_2 + 2
+ ldrh w14, [x16, #:lo12:struct_obj_2 + 2]
+ sdiv w13, w12, w14
+ msub w7, w13, w14, w12
+ sbfiz w11, w7, 0, 8
+ movz w16, #54823, lsl #0
+ cmp w0, w16
+ cset x8, le
+ orr w8, w11, w8
+ adrp x16, var_9
+ ldrh w6, [x16, #:lo12:var_9]
+ adrp x16, var_15
+ ldrh w11, [x16, #:lo12:var_15]
+ adrp x16, struct_obj_2 + 6
+ ldrsh w12, [x16, #:lo12:struct_obj_2 + 6]
+ eor w0, w11, w12
+ adrp x16, struct_obj_4
+ ldrsh w5, [x16, #:lo12:struct_obj_4]
+ movn w16, #116, lsl #0
+ and w12, w5, w16
+ orr w0, w0, w12
+ bic w9, w6, w0
+ adrp x16, struct_obj_4 + 2
+ ldrsb w11, [x16, #:lo12:struct_obj_4 + 2]
+ orr w5, w9, w11
+ ubfiz w10, w5, 0, 16
+ adrp x16, struct_obj_4 + 18
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 18]
+ madd w5, w10, w0, wzr
+ cmp w8, w5
+ cset x15, gt
+ adrp x16, var_21
+ ldrsb w2, [x16, #:lo12:var_21]
+ orn w29, wzr, w2
+ movn w16, #38, lsl #0
+ orr w5, w29, w16
+ adrp x16, var_23
+ ldrh w4, [x16, #:lo12:var_23]
+ eon w8, w4, w2
+ adrp x16, var_38
+ ldrsb w17, [x16, #:lo12:var_38]
+ adrp x16, var_61
+ ldrsb w3, [x16, #:lo12:var_61]
+ bic w29, w17, w3
+ eor w1, w8, w29
+ and w3, w5, w1
+ and w14, w15, w3
+ adrp x16, var_37
+ strb w14, [x16, #:lo12:var_37]
+ sbfiz w0, w0, 0, 8
+.L124:
+ orr w0, wzr, #1
+ cbz w0, .L127
+ adrp x16, struct_obj_7 + 2
+ ldrsh w0, [x16, #:lo12:struct_obj_7 + 2]
+ cbnz w0, .L128
+ adrp x16, var_14
+ ldrsb w0, [x16, #:lo12:var_14]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L128
+ adrp x16, var_20
+ ldrh w0, [x16, #:lo12:var_20]
+ adrp x16, var_129
+ strh w0, [x16, #:lo12:var_129]
+ orr w0, wzr, #1
+ cbnz w0, .L129
+ orr w0, wzr, #1
+ b .L129
+.L128:
+ adrp x16, struct_obj_4 + 24
+ ldrh w29, [x16, #:lo12:struct_obj_4 + 24]
+ adrp x16, var_58
+ ldrsb w5, [x16, #:lo12:var_58]
+ sdiv w13, w29, w5
+ msub w3, w13, w5, w29
+ adrp x16, var_27
+ ldrsh w4, [x16, #:lo12:var_27]
+ orn w7, wzr, w4
+ sdiv w2, w3, w7
+ msub w0, w2, w7, w3
+ ubfiz w0, w0, 0, 16
+ adrp x16, struct_obj_9
+ ldrsh w0, [x16, #:lo12:struct_obj_9]
+ adrp x16, var_123
+ strh w0, [x16, #:lo12:var_123]
+ adrp x16, struct_obj_4 + 2
+ ldrsb w0, [x16, #:lo12:struct_obj_4 + 2]
+ cbz w0, .L129
+ orr w0, wzr, #1
+ cbz w0, .L129
+ orr w0, wzr, #1
+.L129:
+ adrp x16, struct_obj_9 + 20
+ ldrsh w11, [x16, #:lo12:struct_obj_9 + 20]
+ adrp x16, var_48
+ ldrh w13, [x16, #:lo12:var_48]
+ add w0, w11, w13
+ orn w0, wzr, w0
+ adrp x16, struct_obj_4 + 24
+ ldrh w1, [x16, #:lo12:struct_obj_4 + 24]
+ adrp x16, var_9
+ ldrh w13, [x16, #:lo12:var_9]
+ adrp x16, var_56
+ ldrh w10, [x16, #:lo12:var_56]
+ and w29, w10, #-97
+ eon w7, w13, w29
+ cbz w7, .L130
+ adrp x16, struct_obj_3 + 2
+ ldrh w11, [x16, #:lo12:struct_obj_3 + 2]
+ cbz w11, .L131
+ adrp x16, var_18
+ ldrsb w13, [x16, #:lo12:var_18]
+.L131:
+ orr w5, wzr, #1
+ movz w15, #0, lsl #0
+ adrp x16, var_64
+ ldrsb w0, [x16, #:lo12:var_64]
+ cmp w0, #0
+ csel x17, x5, x15, ne
+ cbnz w17, .L132
+ adrp x16, var_28
+ ldrsh w8, [x16, #:lo12:var_28]
+.L132:
+ adrp x16, struct_obj_6
+ ldrsh w7, [x16, #:lo12:struct_obj_6]
+ bic w0, w1, w7
+ adrp x16, var_143
+ strb w0, [x16, #:lo12:var_143]
+.L130:
+ adrp x16, struct_obj_10 + 6
+ ldrsh w10, [x16, #:lo12:struct_obj_10 + 6]
+ adrp x16, struct_obj_8 + 28
+ ldrsh w15, [x16, #:lo12:struct_obj_8 + 28]
+ sub w4, w10, w15
+ adrp x16, struct_obj_5 + 6
+ ldrsh w5, [x16, #:lo12:struct_obj_5 + 6]
+ orr w16, wzr, #2147483647
+ add w2, w5, w16
+ cmp w4, w2, asr #11
+ cset x0, lt
+ sub w15, wzr, w0
+ movz w3, #21384, lsl #0
+ adrp x16, struct_obj_4 + 12
+ ldrsb w14, [x16, #:lo12:struct_obj_4 + 12]
+ adrp x16, struct_obj_4 + 8
+ ldrsh w8, [x16, #:lo12:struct_obj_4 + 8]
+ madd w7, w14, w8, wzr
+ madd w5, w7, w3, wzr
+ bic w15, w15, w5
+ adrp x16, var_11
+ ldrsh w17, [x16, #:lo12:var_11]
+ movz w16, #28869, lsl #0
+ orr w12, w17, w16
+ adrp x16, struct_obj_10 + 4
+ ldrsb w7, [x16, #:lo12:struct_obj_10 + 4]
+ adrp x16, struct_obj_7 + 4
+ ldrsb w9, [x16, #:lo12:struct_obj_7 + 4]
+ adrp x16, var_31
+ ldrsh w1, [x16, #:lo12:var_31]
+ and w11, w9, w1
+ orn w17, w7, w11
+ orr w13, w12, w17
+ cmp w15, w13
+ cset x0, eq
+ adrp x16, var_55
+ strb w0, [x16, #:lo12:var_55]
+ adrp x16, var_50
+ ldrh w29, [x16, #:lo12:var_50]
+ adrp x16, struct_obj_6 + 4
+ ldrh w12, [x16, #:lo12:struct_obj_6 + 4]
+ adrp x16, var_51
+ ldrsh w11, [x16, #:lo12:var_51]
+ movz w16, #58076, lsl #0
+ eor w9, w29, w16
+ adrp x16, struct_obj_2 + 2
+ ldrh w10, [x16, #:lo12:struct_obj_2 + 2]
+ adrp x16, struct_obj_8
+ ldrh w11, [x16, #:lo12:struct_obj_8]
+ sub w11, w11, #16384
+ sub w11, w11, #954
+ lsl w4, w10, w11
+ eor w0, w9, w4
+ adrp x16, var_8
+ ldrh w1, [x16, #:lo12:var_8]
+ sub w15, w1, #12288
+ sub w15, w15, #2352
+ asr w29, w0, w15
+ adrp x16, var_45
+ ldrsb w5, [x16, #:lo12:var_45]
+ movz w16, #27168, lsl #0
+ cmp w5, w16
+ cset x12, gt
+ movz w16, #32858, lsl #0
+ cmp w12, w16
+ cset x9, lt
+ orr w0, wzr, w9, asr #3
+ lsl w0, w29, w0
+ sbfiz w0, w0, 0, 8
+ cbz w0, .L127
+ adrp x16, var_28
+ ldrsh w0, [x16, #:lo12:var_28]
+ adrp x16, var_29
+ ldrh w0, [x16, #:lo12:var_29]
+ cmp w0, #0
+ cset x17, ne
+ movz w10, #0, lsl #0
+ movz w1, #0, lsl #0
+ cmp w17, #0
+ csel x0, x10, x1, ne
+ eor w1, w0, #1
+ adrp x16, var_47
+ ldrsb w4, [x16, #:lo12:var_47]
+ orr w0, w1, w4
+ adrp x16, var_152
+ strh w0, [x16, #:lo12:var_152]
+.L127:
+ adrp x16, struct_obj_4
+ ldrsh w0, [x16, #:lo12:struct_obj_4]
+ cmp w0, #0
+ cset x0, ne
+ adrp x16, struct_obj_1 + 2
+ ldrh w7, [x16, #:lo12:struct_obj_1 + 2]
+ adrp x16, var_18
+ ldrsb w29, [x16, #:lo12:var_18]
+ cmp w7, w29
+ cset x29, le
+ adrp x16, var_7
+ ldrsb w3, [x16, #:lo12:var_7]
+ movz w16, #7701, lsl #0
+ cmp w3, w16
+ cset x2, ne
+ and w0, w29, w2
+ adrp x16, var_1
+ ldrh w0, [x16, #:lo12:var_1]
+ cbnz w0, .L133
+ adrp x16, struct_obj_8 + 8
+ ldrsb w0, [x16, #:lo12:struct_obj_8 + 8]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L133
+ adrp x16, struct_obj_8 + 20
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 20]
+ cbnz w0, .L133
+ adrp x16, var_49
+ ldrsb w0, [x16, #:lo12:var_49]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L133
+ orr w0, wzr, #1
+ orr w2, wzr, #1
+ adrp x16, var_29
+ ldrh w11, [x16, #:lo12:var_29]
+ cmp w11, #0
+ csel x0, x0, x2, ne
+ cbnz w0, .L133
+ adrp x16, struct_obj_6 + 2
+ ldrh w0, [x16, #:lo12:struct_obj_6 + 2]
+ sbfiz w0, w0, 0, 16
+ cmp w0, #0
+ cset x0, eq
+ cbnz w0, .L134
+.L133:
+ adrp x16, var_48
+ ldrh w0, [x16, #:lo12:var_48]
+ cbnz w0, .L135
+ adrp x16, var_31
+ ldrsh w0, [x16, #:lo12:var_31]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L135
+ adrp x16, struct_obj_8 + 18
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 18]
+ ubfiz w0, w0, 0, 16
+ cbz w0, .L136
+ adrp x16, var_25
+ ldrsb w0, [x16, #:lo12:var_25]
+ cmp w0, #0
+ cset x0, eq
+ b .L137
+.L136:
+ movz w0, #0, lsl #0
+ b .L137
+.L135:
+ movz w0, #0, lsl #0
+.L137:
+ eor w0, w0, #1
+ cbz w0, .L138
+.L134:
+ adrp x16, struct_obj_4 + 10
+ ldrh w15, [x16, #:lo12:struct_obj_4 + 10]
+ adrp x16, struct_obj_8 + 20
+ ldrsh w6, [x16, #:lo12:struct_obj_8 + 20]
+ orn w2, wzr, w6
+ ubfiz w3, w2, 0, 16
+ orn w9, wzr, w3
+ sdiv w0, w15, w9
+ adrp x16, var_156
+ strb w0, [x16, #:lo12:var_156]
+ adrp x16, var_15
+ ldrh w2, [x16, #:lo12:var_15]
+ adrp x16, struct_obj_8 + 26
+ ldrsb w11, [x16, #:lo12:struct_obj_8 + 26]
+ movz w16, #17017, lsl #0
+ and w17, w11, w16
+ sbfiz w29, w17, 0, 8
+ adrp x16, struct_obj_1 + 2
+ ldrh w14, [x16, #:lo12:struct_obj_1 + 2]
+ adrp x16, var_39
+ ldrh w10, [x16, #:lo12:var_39]
+ sub w7, w10, #24576
+ sub w7, w7, #3586
+ lsl w1, w14, w7
+ adrp x16, struct_obj_1 + 4
+ ldrh w12, [x16, #:lo12:struct_obj_1 + 4]
+ and w17, w1, w12
+ sub w3, w17, #53248
+ sub w3, w3, #2127
+ asr w14, w29, w3
+ lsl w13, w2, w14
+ sbfiz w12, w13, 0, 8
+ adrp x16, var_14
+ ldrsb w8, [x16, #:lo12:var_14]
+ adrp x16, struct_obj_4 + 12
+ ldrsb w6, [x16, #:lo12:struct_obj_4 + 12]
+ lsl w3, w8, w6
+ ubfiz w6, w3, 0, 16
+ movz w2, #19254, lsl #0
+ movk w2, #42921, lsl #16
+ adrp x16, struct_obj_8 + 30
+ ldrsb w29, [x16, #:lo12:struct_obj_8 + 30]
+ cmp w29, #5
+ cset x14, gt
+ madd w7, w14, w2, wzr
+ adrp x16, struct_obj_4 + 16
+ ldrsb w7, [x16, #:lo12:struct_obj_4 + 16]
+ adrp x16, struct_obj_8 + 20
+ ldrsh w6, [x16, #:lo12:struct_obj_8 + 20]
+ adrp x16, var_54
+ ldrsh w5, [x16, #:lo12:var_54]
+ adrp x16, var_23
+ ldrh w3, [x16, #:lo12:var_23]
+ orr w16, wzr, #2147483647
+ add w4, w5, w16
+ and w3, w3, w4
+ cbz w3, .L139
+ adrp x16, var_11
+ ldrsh w5, [x16, #:lo12:var_11]
+ cbnz w5, .L140
+ adrp x16, struct_obj_9 + 24
+ ldrh w13, [x16, #:lo12:struct_obj_9 + 24]
+ cmp w13, #0
+ cset x13, ne
+ cbz w13, .L139
+.L140:
+ adrp x16, struct_obj_9
+ ldrsh w9, [x16, #:lo12:struct_obj_9]
+ cbz w9, .L139
+ cbnz w7, .L139
+ adrp x16, struct_obj_2 + 4
+ ldrh w17, [x16, #:lo12:struct_obj_2 + 4]
+ cmp w17, #0
+ cset x17, ne
+.L139:
+ adrp x16, struct_obj_6 + 6
+ ldrsh w4, [x16, #:lo12:struct_obj_6 + 6]
+ adrp x16, var_65
+ ldrsh w17, [x16, #:lo12:var_65]
+ sub w7, w4, w17
+ adrp x16, struct_obj_4 + 10
+ ldrh w3, [x16, #:lo12:struct_obj_4 + 10]
+ sub w14, w3, #28672
+ sub w14, w14, #2102
+ lsl w29, w11, w14
+ sub w0, w7, w29
+ sbfiz w2, w0, 0, 8
+ cbz w2, .L141
+.L141:
+ adrp x16, struct_obj_2 + 4
+ ldrh w29, [x16, #:lo12:struct_obj_2 + 4]
+ cbnz w10, .L142
+ adrp x16, struct_obj_4 + 26
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 26]
+ cmp w0, #0
+ cset x0, ne
+ b .L143
+.L142:
+ orr w0, wzr, #1
+.L143:
+ adrp x16, var_45
+ ldrsb w1, [x16, #:lo12:var_45]
+ movz w16, #15962, lsl #0
+ orr w14, w1, w16
+ adrp x16, struct_obj_9 + 24
+ ldrh w10, [x16, #:lo12:struct_obj_9 + 24]
+ movz w16, #64811, lsl #0
+ eor w7, w10, w16
+ orr w6, w14, w7
+ cmp w29, w6
+ cset x5, ge
+ orn w9, wzr, w0
+ ubfiz w29, w9, 0, 16
+ cmp w5, w29
+ b.gt .L144
+ adrp x16, var_3
+ ldrsb w0, [x16, #:lo12:var_3]
+ adrp x16, struct_obj_9
+ ldrsh w0, [x16, #:lo12:struct_obj_9]
+ cmp w0, #40
+ b.lt .L145
+ adrp x16, struct_obj_6
+ ldrsh w14, [x16, #:lo12:struct_obj_6]
+ adrp x16, struct_obj_5 + 2
+ ldrsh w13, [x16, #:lo12:struct_obj_5 + 2]
+ sdiv w8, w14, w13
+ msub w0, w8, w13, w14
+ cmp w0, #0
+ cset x29, ne
+ b .L146
+.L145:
+ orr w29, wzr, #1
+.L146:
+ movz w6, #92, lsl #0
+ movz w7, #0, lsl #0
+ adrp x16, struct_obj_7 + 2
+ ldrsh w17, [x16, #:lo12:struct_obj_7 + 2]
+ and w10, w17, w29
+ sub w9, w7, w10
+ add w4, w9, #32
+ asr w0, w6, w4
+ adrp x16, var_178
+ strh w0, [x16, #:lo12:var_178]
+ adrp x16, struct_obj_4 + 4
+ ldrsh w4, [x16, #:lo12:struct_obj_4 + 4]
+ adrp x16, var_4
+ ldrh w0, [x16, #:lo12:var_4]
+ eor w4, w4, w0
+ adrp x16, struct_obj_9 + 8
+ ldrsh w29, [x16, #:lo12:struct_obj_9 + 8]
+ eor w0, w4, w29
+ adrp x16, var_3
+ ldrsb w0, [x16, #:lo12:var_3]
+ adrp x16, var_36
+ ldrsh w0, [x16, #:lo12:var_36]
+ movz w16, #55161, lsl #0
+ cmp w0, w16
+ cset x8, gt
+ adrp x16, var_55
+ ldrsb w13, [x16, #:lo12:var_55]
+ add w0, w8, w13
+ sbfiz w0, w0, 0, 8
+ cmp w0, #0
+ cset x0, eq
+ orn w0, wzr, w0
+ adrp x16, var_46
+ strh w0, [x16, #:lo12:var_46]
+ b .L147
+.L144:
+ adrp x16, var_20
+ ldrh w0, [x16, #:lo12:var_20]
+ cmp w0, #0
+ cset x7, ne
+ adrp x16, struct_obj_6 + 2
+ ldrh w17, [x16, #:lo12:struct_obj_6 + 2]
+ sbfx w5, w17, 30, 2
+ orr w0, w7, w5
+.L147:
+ adrp x16, struct_obj_9 + 2
+ ldrsb w0, [x16, #:lo12:struct_obj_9 + 2]
+ cmp w0, #0
+ cset x17, eq
+ adrp x16, var_19
+ ldrsb w10, [x16, #:lo12:var_19]
+ orn w4, wzr, w10
+ madd w0, w17, w4, wzr
+ orn w0, wzr, w0
+ cbz w0, .L138
+ adrp x16, var_40
+ ldrsb w0, [x16, #:lo12:var_40]
+ cmp w0, #0
+ cset x0, ne
+ cbz w0, .L138
+ adrp x16, var_48
+ ldrh w0, [x16, #:lo12:var_48]
+.L138:
+ adrp x16, struct_obj_7 + 2
+ ldrsh w0, [x16, #:lo12:struct_obj_7 + 2]
+ cbnz w0, .L148
+ adrp x16, var_57
+ ldrsb w0, [x16, #:lo12:var_57]
+ cmp w0, #0
+ cset x5, ne
+ b .L149
+.L148:
+ movz w5, #0, lsl #0
+.L149:
+ adrp x16, struct_obj_8 + 2
+ ldrsh w10, [x16, #:lo12:struct_obj_8 + 2]
+ tbz w10, #5, .L150
+ adrp x16, var_1
+ ldrh w9, [x16, #:lo12:var_1]
+ adrp x16, struct_obj_2 + 6
+ ldrsh w3, [x16, #:lo12:struct_obj_2 + 6]
+ sub w8, w9, w3
+ sbfiz w9, w8, 0, 16
+ cmp w9, #0
+ cset x10, eq
+ b .L151
+.L150:
+ movz w10, #0, lsl #0
+.L151:
+ adrp x16, struct_obj_8 + 12
+ ldrsb w9, [x16, #:lo12:struct_obj_8 + 12]
+ adrp x16, struct_obj_9 + 10
+ ldrh w0, [x16, #:lo12:struct_obj_9 + 10]
+ orr w7, w9, w0
+ adrp x16, var_11
+ ldrsh w3, [x16, #:lo12:var_11]
+ ubfiz w0, w3, 0, 16
+ and w11, w7, w0
+ orn w14, wzr, w11
+ orr w16, wzr, #2147483647
+ add w4, w14, w16
+ adrp x16, var_53
+ ldrsh w6, [x16, #:lo12:var_53]
+ adrp x16, struct_obj_8
+ ldrh w7, [x16, #:lo12:struct_obj_8]
+ cmp w6, w7
+ cset x12, gt
+ sub w8, wzr, w3
+ madd w0, w12, w8, wzr
+ madd w6, w5, w0, wzr
+ asr w0, w4, w6
+ and w0, w0, w10
+ cbz w0, .L100
+ adrp x16, var_1
+ ldrh w4, [x16, #:lo12:var_1]
+ adrp x16, struct_obj_4 + 26
+ ldrsh w1, [x16, #:lo12:struct_obj_4 + 26]
+ movz w0, #21555, lsl #0
+ adrp x16, var_39
+ strh w0, [x16, #:lo12:var_39]
+ sub w0, wzr, w4
+ adrp x16, var_46
+ strh w0, [x16, #:lo12:var_46]
+ adrp x16, var_65
+ ldrsh w0, [x16, #:lo12:var_65]
+ cbz w0, .L152
+ adrp x16, var_7
+ ldrsb w0, [x16, #:lo12:var_7]
+ cmp w0, #0
+ cset x13, ne
+ b .L153
+.L152:
+ movz w13, #0, lsl #0
+.L153:
+ orr w3, wzr, #1
+ movz w17, #0, lsl #0
+ cmp w13, #0
+ csel x0, x3, x17, ne
+ adrp x16, var_5
+ ldrh w0, [x16, #:lo12:var_5]
+ cbnz w0, .L154
+ adrp x16, struct_obj_2 + 2
+ ldrh w0, [x16, #:lo12:struct_obj_2 + 2]
+ cbz w0, .L155
+ adrp x16, var_43
+ ldrh w0, [x16, #:lo12:var_43]
+ cmp w0, #0
+ cset x0, ne
+ b .L156
+.L155:
+ movz w0, #0, lsl #0
+ b .L156
+.L154:
+ orr w0, wzr, #1
+.L156:
+ cbnz w0, .L157
+ movz w0, #0, lsl #0
+ cbz w0, .L157
+ adrp x16, struct_obj_4
+ ldrsh w0, [x16, #:lo12:struct_obj_4]
+ sbfiz w0, w0, 0, 8
+.L157:
+ orr w3, wzr, #2147418112
+ adrp x16, var_4
+ ldrh w2, [x16, #:lo12:var_4]
+ movn w16, #6281, lsl #0
+ orr w0, w2, w16
+ add w15, w0, #4096
+ add w15, w15, #130
+ lsl w0, w3, w15
+ orn w0, wzr, w0
+ adrp x16, var_49
+ strb w0, [x16, #:lo12:var_49]
+ adrp x16, var_54
+ ldrsh w3, [x16, #:lo12:var_54]
+ adrp x16, struct_obj_8
+ ldrh w8, [x16, #:lo12:struct_obj_8]
+ eor w5, w3, w8
+ eor w0, w5, w3
+ sbfiz w12, w0, 0, 8
+ adrp x16, struct_obj_8 + 4
+ ldrsb w13, [x16, #:lo12:struct_obj_8 + 4]
+ orn w13, wzr, w13
+ movn w16, #20559, lsl #0
+ orr w11, w13, w16
+ movn w16, #26, lsl #0
+ and w2, w11, w16
+ sbfiz w13, w2, 0, 16
+ and w0, w12, w13
+ adrp x16, struct_obj_9 + 24
+ ldrh w0, [x16, #:lo12:struct_obj_9 + 24]
+ adrp x16, var_43
+ ldrh w2, [x16, #:lo12:var_43]
+ cmp w2, #0
+ cset x1, eq
+ adrp x16, var_7
+ ldrsb w17, [x16, #:lo12:var_7]
+ cmp w1, w17
+ cset x17, le
+ adrp x16, var_28
+ ldrsh w14, [x16, #:lo12:var_28]
+ movz w16, #24924, lsl #0
+ and w13, w14, w16
+ adrp x16, struct_obj_7
+ ldrsb w5, [x16, #:lo12:struct_obj_7]
+ orn w3, w13, w5
+ movz w16, #72, lsl #0
+ eor w15, w3, w16
+ cmp w17, w15
+ cset x12, gt
+ lsl w0, w0, w12
+ cbz w0, .L158
+ adrp x16, struct_obj_10 + 6
+ ldrsh w13, [x16, #:lo12:struct_obj_10 + 6]
+ adrp x16, struct_obj_4 + 4
+ ldrsh w29, [x16, #:lo12:struct_obj_4 + 4]
+ adrp x16, var_41
+ ldrh w12, [x16, #:lo12:var_41]
+ cbnz w12, .L159
+ adrp x16, var_4
+ ldrh w1, [x16, #:lo12:var_4]
+ cmp w1, #0
+ cset x14, ne
+ cbnz w14, .L159
+ adrp x16, var_1
+ ldrh w1, [x16, #:lo12:var_1]
+ cmp w1, #0
+ cset x7, eq
+ cbnz w7, .L159
+ orr w15, wzr, #1
+ orr w17, wzr, #1
+ cmp w13, #0
+ csel x3, x15, x17, ne
+ eor w8, w3, #1
+ cbz w8, .L159
+ adrp x16, var_42
+ ldrsb w4, [x16, #:lo12:var_42]
+ ubfiz w7, w4, 0, 16
+ cbnz w7, .L159
+ cmp w29, #0
+ cset x0, ne
+.L159:
+ adrp x16, struct_obj_10 + 4
+ ldrsb w0, [x16, #:lo12:struct_obj_10 + 4]
+ movn w16, #30699, lsl #0
+ cmp w0, w16
+ cset x14, ne
+ adrp x16, var_58
+ ldrsb w5, [x16, #:lo12:var_58]
+ sub w0, w14, w5
+ orn w0, wzr, w0
+.L158:
+ adrp x16, struct_obj_3 + 2
+ ldrh w0, [x16, #:lo12:struct_obj_3 + 2]
+ movn w16, #11885, lsl #0
+ and w0, w0, w16
+ sub w0, wzr, w0
+ adrp x16, var_217
+ strb w0, [x16, #:lo12:var_217]
+ adrp x16, struct_obj_8
+ ldrh w6, [x16, #:lo12:struct_obj_8]
+ adrp x16, var_54
+ ldrsh w8, [x16, #:lo12:var_54]
+ cbz w8, .L160
+ adrp x16, struct_obj_10 + 6
+ ldrsh w2, [x16, #:lo12:struct_obj_10 + 6]
+ cbnz w2, .L161
+ adrp x16, struct_obj_8 + 24
+ ldrh w5, [x16, #:lo12:struct_obj_8 + 24]
+ cmp w5, #0
+ cset x7, ne
+ cbnz w7, .L161
+.L160:
+ adrp x16, struct_obj_8 + 20
+ ldrsh w8, [x16, #:lo12:struct_obj_8 + 20]
+ cbz w8, .L162
+ adrp x16, struct_obj_3 + 4
+ ldrh w13, [x16, #:lo12:struct_obj_3 + 4]
+ cmp w13, #0
+ cset x11, ne
+ b .L163
+.L162:
+ movz w11, #0, lsl #0
+.L163:
+ eor w7, w11, #1
+ cbz w7, .L164
+.L161:
+ adrp x16, struct_obj_4 + 2
+ ldrsb w1, [x16, #:lo12:struct_obj_4 + 2]
+ cmp w1, #0
+ cset x14, eq
+ cbnz w14, .L165
+ orr w7, wzr, #1
+ b .L166
+.L165:
+ orr w7, wzr, #1
+ b .L166
+.L164:
+ movz w7, #0, lsl #0
+.L166:
+ adrp x16, struct_obj_1
+ ldrsh w5, [x16, #:lo12:struct_obj_1]
+ movz w16, #43755, lsl #0
+ eor w11, w5, w16
+ adrp x16, var_29
+ ldrh w4, [x16, #:lo12:var_29]
+ eor w3, w4, #124
+ and w17, w11, w3
+ eor w0, w17, #-128
+ movz w16, #32295, lsl #0
+ and w13, w0, w16
+ movz w16, #110, lsl #0
+ eor w0, w13, w16
+ orn w2, wzr, w0
+ orr w16, wzr, #2147483647
+ add w4, w2, w16
+ adrp x16, struct_obj_8 + 16
+ ldrsb w2, [x16, #:lo12:struct_obj_8 + 16]
+ cmn w2, #601
+ cset x11, le
+ cmp w6, #0
+ cset x10, eq
+ cmp w11, w10
+ cset x8, ne
+ cmp w13, #0
+ cset x3, lt
+ cmp w8, w3
+ cset x8, gt
+ asr w9, w4, w8
+ cmp w7, w9
+ b.gt .L167
+ adrp x16, var_65
+ strh w13, [x16, #:lo12:var_65]
+ adrp x16, struct_obj_4 + 16
+ ldrsb w0, [x16, #:lo12:struct_obj_4 + 16]
+ orr w16, wzr, #2147483647
+ add w15, w0, w16
+ adrp x16, var_18
+ ldrsb w13, [x16, #:lo12:var_18]
+ adrp x16, struct_obj_4 + 8
+ ldrsh w1, [x16, #:lo12:struct_obj_4 + 8]
+ movz w16, #68, lsl #0
+ orr w14, w1, w16
+ adrp x16, struct_obj_1 + 4
+ ldrh w1, [x16, #:lo12:struct_obj_1 + 4]
+ movn w16, #16241, lsl #0
+ eor w5, w1, w16
+ and w11, w14, w5
+ add w9, w11, #57344
+ add w9, w9, #1482
+ lsl w13, w13, w9
+ sub w10, w13, #5042176
+ sub w10, w10, #4072
+ asr w0, w15, w10
+ adrp x16, var_32
+ ldrh w0, [x16, #:lo12:var_32]
+ movn w16, #22, lsl #0
+ and w0, w0, w16
+ sub w0, wzr, w0
+ b .L100
+.L167:
+ adrp x16, var_50
+ ldrh w1, [x16, #:lo12:var_50]
+ orn w17, wzr, w1
+ sbfiz w14, w17, 0, 8
+ adrp x16, var_40
+ ldrsb w17, [x16, #:lo12:var_40]
+ orr w4, w17, #6
+ sbfiz w8, w4, 0, 16
+ bic w10, w14, w8
+ adrp x16, struct_obj_9 + 20
+ ldrsh w1, [x16, #:lo12:struct_obj_9 + 20]
+ and w0, w2, w1
+ movz w16, #61009, lsl #0
+ orr w12, w0, w16
+ sub w12, wzr, w12
+ orr w16, wzr, #2147483647
+ add w14, w12, w16
+ movn w5, #52, lsl #0
+ adrp x16, struct_obj_1 + 6
+ ldrsh w11, [x16, #:lo12:struct_obj_1 + 6]
+ madd w3, w11, w5, wzr
+ madd w8, w13, w3, wzr
+ cmp w8, #0
+ cset x29, eq
+ asr w1, w14, w29
+ cmp w10, w1
+ cset x0, le
+ adrp x16, var_234
+ strh w0, [x16, #:lo12:var_234]
+ adrp x16, var_23
+ ldrh w0, [x16, #:lo12:var_23]
+ cbnz w0, .L100
+ adrp x16, var_2
+ ldrh w0, [x16, #:lo12:var_2]
+.L100:
+ adrp x16, struct_obj_9
+ ldrsh w0, [x16, #:lo12:struct_obj_9]
+ movn w16, #48877, lsl #0
+ and w0, w0, w16
+ movn w16, #30503, lsl #0
+ eor w0, w0, w16
+ movz w16, #47, lsl #0
+ tst w0, w16
+ b.eq .L168
+ adrp x16, var_16
+ ldrh w0, [x16, #:lo12:var_16]
+ cbz w0, .L169
+ adrp x16, var_37
+ ldrsb w0, [x16, #:lo12:var_37]
+ cmp w0, #0
+ cset x29, ne
+ b .L170
+.L169:
+ movz w29, #0, lsl #0
+.L170:
+ adrp x16, var_15
+ ldrh w17, [x16, #:lo12:var_15]
+ adrp x16, var_65
+ ldrsh w1, [x16, #:lo12:var_65]
+ ubfiz w0, w1, 0, 16
+ add w10, w0, w29
+ cmp w17, w10
+ cset x6, le
+ orn w10, wzr, w6
+ movz w16, #32708, lsl #0
+ cmp w10, w16
+ cset x6, lt
+ adrp x16, var_37
+ ldrsb w0, [x16, #:lo12:var_37]
+ add w13, w0, w6
+ cmn w13, #1594
+ cset x4, ge
+ movz w16, #56889, lsl #0
+ eor w8, w1, w16
+ orr w16, wzr, #2147483647
+ add w6, w8, w16
+ adrp x16, struct_obj_9 + 20
+ ldrsh w14, [x16, #:lo12:struct_obj_9 + 20]
+ sub w29, w14, #12288
+ sub w29, w29, #1239
+ lsl w15, w0, w29
+ sub w8, w15, #15200256
+ sub w8, w8, #4072
+ asr w11, w6, w8
+ orn w5, wzr, w11
+ orr w16, wzr, #2147483647
+ add w11, w5, w16
+ adrp x16, struct_obj_1 + 6
+ ldrsh w29, [x16, #:lo12:struct_obj_1 + 6]
+ movn w16, #29412, lsl #0
+ orr w10, w29, w16
+ adrp x16, var_61
+ ldrsb w12, [x16, #:lo12:var_61]
+ orn w7, w10, w12
+ ubfiz w2, w7, 0, 16
+ sub w10, w2, #32768
+ sub w10, w10, #4095
+ lsl w9, w11, w10
+ adrp x16, var_22
+ ldrsb w5, [x16, #:lo12:var_22]
+ movn w16, #10106, lsl #0
+ and w11, w5, w16
+ adrp x16, struct_obj_10
+ ldrsb w12, [x16, #:lo12:struct_obj_10]
+ movn w16, #7265, lsl #0
+ orr w6, w12, w16
+ add w10, w6, #4096
+ add w10, w10, #3136
+ lsl w12, w11, w10
+ adrp x16, var_28
+ ldrsh w3, [x16, #:lo12:var_28]
+ sbfiz w13, w3, 0, 8
+ adrp x16, struct_obj_9 + 22
+ ldrh w8, [x16, #:lo12:struct_obj_9 + 22]
+ sub w10, w8, #24576
+ sub w10, w10, #2375
+ asr w11, w4, w10
+ and w5, w13, w11
+ lsl w17, w12, w5
+ adrp x16, struct_obj_8 + 24
+ ldrh w8, [x16, #:lo12:struct_obj_8 + 24]
+ movz w16, #31750, lsl #0
+ eor w15, w8, w16
+ sbfiz w2, w15, 0, 16
+ orr w16, wzr, #2147483647
+ add w7, w2, w16
+ adrp x16, struct_obj_4 + 22
+ ldrh w11, [x16, #:lo12:struct_obj_4 + 22]
+ sbfiz w8, w11, 0, 8
+ orn w6, wzr, w8
+ add w14, w6, #113
+ lsl w29, w7, w14
+ movz w16, #45511, lsl #0
+ movk w16, #32767, lsl #16
+ sub w4, w29, w16
+ lsl w2, w17, w4
+ orr w0, w9, w2
+ sbfiz w7, w0, 0, 8
+ adrp x16, struct_obj_1
+ ldrsh w5, [x16, #:lo12:struct_obj_1]
+ adrp x16, var_18
+ ldrsb w6, [x16, #:lo12:var_18]
+ orn w8, wzr, w6
+ adrp x16, var_38
+ ldrsb w12, [x16, #:lo12:var_38]
+ eon w12, w8, w12
+ bic w1, w5, w12
+ adrp x16, struct_obj_8 + 6
+ ldrsh w4, [x16, #:lo12:struct_obj_8 + 6]
+ movn w16, #74, lsl #0
+ orr w15, w4, w16
+ orn w29, wzr, w15
+ madd w1, w1, w29, wzr
+ adrp x16, var_49
+ strb w1, [x16, #:lo12:var_49]
+ adrp x16, var_30
+ ldrh w9, [x16, #:lo12:var_30]
+ cbnz w9, .L171
+ adrp x16, var_17
+ ldrsh w8, [x16, #:lo12:var_17]
+ movz w16, #58592, lsl #0
+ and w12, w8, w16
+ adrp x16, struct_obj_8 + 18
+ ldrsh w3, [x16, #:lo12:struct_obj_8 + 18]
+ movz w16, #32236, lsl #0
+ eor w9, w3, w16
+ eor w9, w12, w9
+ cmp w9, #0
+ cset x1, eq
+ sub w17, wzr, w1
+ cmp w17, #0
+ cset x13, eq
+ adrp x16, struct_obj_8
+ strh w13, [x16, #:lo12:struct_obj_8]
+ adrp x16, var_64
+ ldrsb w15, [x16, #:lo12:var_64]
+ adrp x16, var_32
+ ldrh w29, [x16, #:lo12:var_32]
+ adrp x16, struct_obj_9 + 24
+ ldrh w11, [x16, #:lo12:struct_obj_9 + 24]
+ adrp x16, var_17
+ ldrsh w6, [x16, #:lo12:var_17]
+ sbfiz w8, w6, 0, 8
+ adrp x16, struct_obj_8 + 26
+ ldrsb w14, [x16, #:lo12:struct_obj_8 + 26]
+ and w6, w14, w11
+ and w4, w8, w6
+ orn w4, wzr, w4
+ cbz w4, .L172
+ adrp x16, var_16
+ ldrh w13, [x16, #:lo12:var_16]
+ adrp x16, var_58
+ ldrsb w2, [x16, #:lo12:var_58]
+ and w29, w13, w2
+ sbfiz w17, w29, 0, 8
+ movn w16, #29487, lsl #0
+ orr w12, w17, w16
+ ubfiz w10, w15, 0, 16
+ cbnz w10, .L173
+ adrp x16, struct_obj_4 + 18
+ ldrsh w6, [x16, #:lo12:struct_obj_4 + 18]
+ cbnz w6, .L173
+ adrp x16, var_10
+ ldrh w14, [x16, #:lo12:var_10]
+ cmp w14, #0
+ cset x8, ne
+ cbnz w8, .L173
+ adrp x16, struct_obj_4 + 2
+ ldrsb w0, [x16, #:lo12:struct_obj_4 + 2]
+.L173:
+ movz w15, #26, lsl #0
+ adrp x16, var_297
+ strh w15, [x16, #:lo12:var_297]
+ adrp x16, var_53
+ ldrsh w17, [x16, #:lo12:var_53]
+ adrp x16, var_42
+ ldrsb w6, [x16, #:lo12:var_42]
+ adrp x16, var_65
+ strh w6, [x16, #:lo12:var_65]
+ adrp x16, var_6
+ ldrh w0, [x16, #:lo12:var_6]
+ adrp x16, var_15
+ ldrh w1, [x16, #:lo12:var_15]
+ orn w12, w0, w1
+ adrp x16, var_8
+ ldrh w2, [x16, #:lo12:var_8]
+ movn w16, #90, lsl #0
+ eor w1, w2, w16
+ b .L174
+.L172:
+ orr w14, wzr, #1
+ movz w13, #0, lsl #0
+ adrp x16, struct_obj_8 + 18
+ ldrsh w8, [x16, #:lo12:struct_obj_8 + 18]
+ cmp w8, #0
+ csel x9, x14, x13, ne
+ cbz w9, .L174
+ adrp x16, struct_obj_2 + 6
+ ldrsh w5, [x16, #:lo12:struct_obj_2 + 6]
+ cbz w5, .L175
+ adrp x16, var_20
+ ldrh w8, [x16, #:lo12:var_20]
+ cmp w8, #0
+ cset x3, ne
+.L175:
+ adrp x16, var_24
+ ldrsh w11, [x16, #:lo12:var_24]
+ sbfiz w8, w11, 0, 8
+ cbnz w8, .L176
+.L176:
+.L174:
+ adrp x16, struct_obj_6
+ ldrsh w6, [x16, #:lo12:struct_obj_6]
+ and w3, w6, w7
+ adrp x16, var_12
+ ldrh w8, [x16, #:lo12:var_12]
+ bic w14, w3, w8
+ orn w5, wzr, w14, lsl #15
+ cbz w5, .L177
+ movz w4, #1346, lsl #0
+ adrp x16, var_48
+ ldrh w12, [x16, #:lo12:var_48]
+ madd w5, w12, w4, wzr
+ sbfiz w15, w5, 0, 8
+ cmp w15, w7
+ cset x13, ne
+ movz w16, #19262, lsl #0
+ cmp w13, w16
+ cset x29, lt
+ cbz w29, .L177
+ adrp x16, var_7
+ ldrsb w15, [x16, #:lo12:var_7]
+ movn w13, #42, lsl #0
+ adrp x16, struct_obj_4 + 12
+ ldrsb w2, [x16, #:lo12:struct_obj_4 + 12]
+ adrp x16, struct_obj_8 + 16
+ ldrsb w17, [x16, #:lo12:struct_obj_8 + 16]
+ madd w15, w2, w17, wzr
+ madd w29, w15, w13, wzr
+ movz w12, #86, lsl #0
+ madd w5, w6, w12, wzr
+ orr w0, wzr, w5, lsr #31
+ sxtw x13, w5
+ movz x12, #51543, lsl #0
+ movk x12, #15108, lsl #16
+ madd x4, x13, x12, xzr
+ orr x1, xzr, x4, asr #32
+ add w4, w0, w1, asr #24
+ madd w10, w29, w4, wzr
+ orr w3, wzr, w10, lsl #24
+ cmp w3, #0
+ cset x8, eq
+ adrp x16, var_314
+ strb w8, [x16, #:lo12:var_314]
+ adrp x16, struct_obj_7 + 2
+ ldrsh w10, [x16, #:lo12:struct_obj_7 + 2]
+ sbfiz w14, w10, 0, 8
+ cmp w14, #1
+ cset x15, lt
+ orn w3, wzr, w15
+ orr w14, wzr, #1
+ cbz w14, .L178
+ orr w29, wzr, #1
+ b .L179
+.L178:
+ movz w29, #0, lsl #0
+.L179:
+ b .L180
+.L177:
+ adrp x16, var_28
+ ldrsh w0, [x16, #:lo12:var_28]
+.L180:
+ adrp x16, var_12
+ ldrh w10, [x16, #:lo12:var_12]
+ adrp x16, var_62
+ ldrh w1, [x16, #:lo12:var_62]
+ eor w5, w10, w1
+ adrp x16, struct_obj_10 + 6
+ ldrsh w12, [x16, #:lo12:struct_obj_10 + 6]
+ adrp x16, struct_obj_2
+ ldrsh w8, [x16, #:lo12:struct_obj_2]
+ orr w14, w12, w8
+ orr w1, w5, w14
+ movz w16, #6229, lsl #0
+ orr w17, w1, w16
+ ubfiz w8, w17, 0, 16
+ adrp x16, struct_obj_3 + 6
+ ldrsh w11, [x16, #:lo12:struct_obj_3 + 6]
+ orr w2, w11, #8
+ orn w2, wzr, w2
+ movn w16, #3193, lsl #0
+ eor w29, w2, w16
+ adrp x16, var_8
+ ldrh w0, [x16, #:lo12:var_8]
+ adrp x16, var_25
+ ldrsb w9, [x16, #:lo12:var_25]
+ and w11, w0, w9
+ movn w16, #12881, lsl #0
+ and w13, w11, w16
+ orn w15, w29, w13
+ and w14, w8, w15
+ cbnz w14, .L181
+ adrp x16, var_46
+ ldrh w5, [x16, #:lo12:var_46]
+ adrp x16, struct_obj_8 + 2
+ ldrsh w10, [x16, #:lo12:struct_obj_8 + 2]
+ adrp x16, var_40
+ ldrsb w5, [x16, #:lo12:var_40]
+ adrp x16, var_22
+ ldrsb w6, [x16, #:lo12:var_22]
+ sdiv w29, w5, w6
+ msub w3, w29, w6, w5
+ eor w1, w10, w3
+.L181:
+ adrp x16, var_41
+ ldrh w10, [x16, #:lo12:var_41]
+ adrp x16, struct_obj_4 + 24
+ ldrh w3, [x16, #:lo12:struct_obj_4 + 24]
+ adrp x16, struct_obj_4 + 12
+ ldrsb w4, [x16, #:lo12:struct_obj_4 + 12]
+ cbz w4, .L182
+ cmp w3, #0
+ cset x17, ne
+ b .L183
+.L182:
+ movz w17, #0, lsl #0
+.L183:
+ adrp x16, var_2
+ ldrh w10, [x16, #:lo12:var_2]
+ adrp x16, var_16
+ ldrh w1, [x16, #:lo12:var_16]
+ eor w2, w10, w1
+ movz w16, #40083, lsl #0
+ and w29, w1, w16
+ sbfiz w5, w29, 0, 8
+ cmp w2, w5
+ cset x29, lt
+ movz w16, #14594, lsl #0
+ cmp w29, w16
+ cset x14, le
+ adrp x16, var_35
+ ldrh w11, [x16, #:lo12:var_35]
+ sbfiz w29, w11, 0, 8
+ movn w16, #31724, lsl #0
+ cmp w29, w16
+ cset x13, ne
+ movz w6, #55455, lsl #0
+ sdiv w1, w6, w17
+ cmp w13, w1
+ cset x8, le
+ sbfiz w17, w0, 0, 8
+ sub w6, wzr, w17
+ orr w29, wzr, #-9
+ sdiv w17, w6, w29
+ msub w9, w17, w29, w6
+ add w17, w9, #10
+ asr w6, w8, w17
+ sbfiz w11, w6, 0, 8
+ cmp w14, w11
+ cset x13, ne
+ adrp x16, var_358
+ strh w13, [x16, #:lo12:var_358]
+ b .L184
+.L171:
+ adrp x16, var_33
+ ldrh w8, [x16, #:lo12:var_33]
+ movz w16, #7439, lsl #0
+ and w6, w8, w16
+ orn w4, wzr, w6
+ cbz w4, .L185
+ adrp x16, var_27
+ ldrsh w4, [x16, #:lo12:var_27]
+ adrp x16, struct_obj_9 + 24
+ ldrh w15, [x16, #:lo12:struct_obj_9 + 24]
+ cmp w4, w15, lsl #8
+ cset x4, ne
+ b .L186
+.L185:
+ movz w4, #0, lsl #0
+.L186:
+ orr w29, wzr, #31
+ movz w15, #4200, lsl #0
+ adrp x16, struct_obj_10
+ ldrsb w13, [x16, #:lo12:struct_obj_10]
+ madd w15, w13, w15, wzr
+ madd w9, w15, w29, wzr
+ adrp x16, var_40
+ ldrsb w15, [x16, #:lo12:var_40]
+ sub w10, wzr, w15
+ orn w0, wzr, w10
+ madd w15, w9, w0, wzr
+ sub w1, wzr, w15
+ adrp x16, struct_obj_8 + 18
+ ldrsh w2, [x16, #:lo12:struct_obj_8 + 18]
+ sbfiz w15, w2, 0, 8
+ cmp w15, #0
+ cset x14, eq
+ adrp x16, var_36
+ ldrsh w5, [x16, #:lo12:var_36]
+ movz w16, #18436, lsl #0
+ and w11, w5, w16
+ cmp w14, w11
+ cset x6, ge
+ cmp w4, w6
+ cset x10, lt
+ cmp w1, w10
+ b.lt .L187
+ adrp x16, var_8
+ ldrh w2, [x16, #:lo12:var_8]
+ adrp x16, struct_obj_9 + 10
+ ldrh w12, [x16, #:lo12:struct_obj_9 + 10]
+ cbz w12, .L188
+ adrp x16, var_20
+ ldrh w9, [x16, #:lo12:var_20]
+ cmp w9, #0
+ cset x1, ne
+ b .L189
+.L188:
+ movz w1, #0, lsl #0
+.L189:
+ orr w2, wzr, #1
+ orr w0, wzr, #1
+ cmp w1, #0
+ csel x2, x2, x0, ne
+ cbnz w2, .L190
+ adrp x16, struct_obj_9 + 22
+ ldrh w3, [x16, #:lo12:struct_obj_9 + 22]
+ cmp w3, #0
+ cset x11, ne
+ b .L191
+.L190:
+ orr w11, wzr, #1
+.L191:
+ movz w6, #29648, lsl #0
+ movk w6, #1081, lsl #16
+ asr w29, w6, w11
+ adrp x16, var_240
+ strb w29, [x16, #:lo12:var_240]
+ movz w5, #61679, lsl #0
+ adrp x16, var_10
+ ldrh w4, [x16, #:lo12:var_10]
+ madd w4, w4, w5, wzr
+ adrp x16, var_3
+ ldrsb w3, [x16, #:lo12:var_3]
+ movn w12, #38, lsl #0
+ sdiv w5, w3, w12
+ msub w3, w5, w12, w3
+ cmp w4, w3
+ cset x15, gt
+ movz w2, #90, lsl #0
+ adrp x16, var_14
+ ldrsb w4, [x16, #:lo12:var_14]
+ sdiv w12, w2, w4
+ orr w17, w15, w12, asr #28
+ adrp x16, struct_obj_8 + 8
+ ldrsb w8, [x16, #:lo12:struct_obj_8 + 8]
+ adrp x16, struct_obj_9 + 10
+ ldrh w10, [x16, #:lo12:struct_obj_9 + 10]
+ cmp w8, w10
+ cset x10, gt
+ cmn w10, #57
+ cset x5, ge
+ adrp x16, var_62
+ ldrh w6, [x16, #:lo12:var_62]
+ movz w16, #5083, lsl #0
+ orr w15, w6, w16
+ orn w3, wzr, w15
+ sdiv w6, w5, w3
+ cmp w17, w6
+ cset x6, lt
+ sub w5, wzr, w6
+ adrp x16, var_241
+ strh w5, [x16, #:lo12:var_241]
+ adrp x16, struct_obj_4 + 26
+ ldrsh w12, [x16, #:lo12:struct_obj_4 + 26]
+ adrp x16, var_33
+ ldrh w9, [x16, #:lo12:var_33]
+ cmn w9, #2638
+ cset x10, ge
+ movz w16, #65439, lsl #0
+ movk w16, #127, lsl #16
+ cmp w10, w16
+ cset x17, lt
+ adrp x16, var_59
+ ldrh w11, [x16, #:lo12:var_59]
+ orr w0, w11, #48
+ sbfiz w8, w0, 0, 8
+ orr w16, wzr, #2147483647
+ add w29, w8, w16
+ and w15, w12, w7
+ orn w15, wzr, w15
+ add w13, w15, #76
+ lsl w4, w29, w13
+ ubfiz w15, w4, 0, 16
+ cmp w17, w15
+ cset x29, ne
+ adrp x16, struct_obj_9 + 10
+ strh w29, [x16, #:lo12:struct_obj_9 + 10]
+ adrp x16, var_22
+ ldrsb w13, [x16, #:lo12:var_22]
+ sub w2, w9, #36864
+ sub w2, w2, #3417
+ asr w12, w13, w2
+ sbfiz w3, w12, 0, 8
+ orr w15, wzr, w3, lsr #31
+ sxtw x5, w3
+ movz x0, #20745, lsl #0
+ movk x0, #21032, lsl #16
+ madd x17, x5, x0, xzr
+ orr x4, xzr, x17, asr #32
+ add w4, w15, w4, asr #13
+ adrp x16, struct_obj_8 + 4
+ ldrsb w1, [x16, #:lo12:struct_obj_8 + 4]
+ adrp x16, struct_obj_6 + 4
+ ldrh w15, [x16, #:lo12:struct_obj_6 + 4]
+ orr w17, w15, #-127
+ orr w14, w1, w17
+ adrp x16, var_7
+ ldrsb w6, [x16, #:lo12:var_7]
+ adrp x16, var_1
+ ldrh w1, [x16, #:lo12:var_1]
+ and w5, w6, w1
+ movz w16, #18007, lsl #0
+ and w17, w5, w16
+ eon w29, w14, w17
+ adrp x16, var_57
+ strb w29, [x16, #:lo12:var_57]
+ adrp x16, struct_obj_9 + 20
+ ldrsh w9, [x16, #:lo12:struct_obj_9 + 20]
+.L187:
+ adrp x16, var_20
+ ldrh w29, [x16, #:lo12:var_20]
+ sbfiz w10, w29, 0, 8
+ sub w3, wzr, w10
+ adrp x16, struct_obj_8 + 2
+ ldrsh w1, [x16, #:lo12:struct_obj_8 + 2]
+ adrp x16, struct_obj_9 + 2
+ ldrsb w0, [x16, #:lo12:struct_obj_9 + 2]
+ eor w8, w1, w0
+ adrp x16, var_45
+ ldrsb w12, [x16, #:lo12:var_45]
+ movz w16, #58, lsl #0
+ eor w0, w12, w16
+ add w4, w0, #128
+ lsl w29, w8, w4
+ adrp x16, var_31
+ ldrsh w9, [x16, #:lo12:var_31]
+ cmp w29, w9
+ cset x11, eq
+ adrp x16, struct_obj_1 + 2
+ ldrh w2, [x16, #:lo12:struct_obj_1 + 2]
+ movz w16, #37360, lsl #0
+ orr w4, w2, w16
+ adrp x16, var_5
+ ldrh w8, [x16, #:lo12:var_5]
+ orn w8, w4, w8
+ cmp w8, #8
+ cset x17, le
+ eor w12, w11, w17
+ cmp w3, w12
+ b.le .L192
+ adrp x16, var_58
+ ldrsb w9, [x16, #:lo12:var_58]
+ cbz w9, .L193
+ adrp x16, struct_obj_8 + 6
+ ldrsh w8, [x16, #:lo12:struct_obj_8 + 6]
+ cmp w8, #0
+ cset x12, ne
+ b .L194
+.L193:
+ movz w12, #0, lsl #0
+.L194:
+ movz w13, #20736, lsl #0
+ movk w13, #64035, lsl #16
+ orr w14, wzr, #-63
+ adrp x16, struct_obj_8 + 8
+ ldrsb w11, [x16, #:lo12:struct_obj_8 + 8]
+ madd w8, w11, w9, wzr
+ orn w10, wzr, w8
+ madd w14, w10, w14, wzr
+ sdiv w1, w13, w14
+ adrp x16, var_22
+ ldrsb w10, [x16, #:lo12:var_22]
+ add w5, w10, #36
+ adrp x16, struct_obj_4 + 24
+ ldrh w15, [x16, #:lo12:struct_obj_4 + 24]
+ cmp w15, w12
+ cset x15, gt
+ cmp w5, w15
+ cset x14, lt
+ and w17, w1, w14
+ adrp x16, var_52
+ ldrsh w5, [x16, #:lo12:var_52]
+ sbfiz w29, w5, 0, 8
+ adrp x16, struct_obj_4 + 26
+ ldrsh w4, [x16, #:lo12:struct_obj_4 + 26]
+ sub w0, w4, #12288
+ sub w0, w0, #1655
+ movn w12, #37, lsl #0
+ adrp x16, struct_obj_9 + 4
+ ldrsh w15, [x16, #:lo12:struct_obj_9 + 4]
+ sub w8, wzr, w15
+ sub w12, w12, w8
+ add w15, w0, w12
+ sub w15, w15, #16384
+ sub w15, w15, #223
+ movn w16, #27, lsl #0
+ eor w6, w17, w16
+ orn w13, wzr, w6
+ movz w16, #28048, lsl #0
+ orr w8, w13, w16
+ sbfiz w10, w8, 0, 8
+ eor w0, w15, w10
+ adrp x16, struct_obj_9 + 24
+ strh w0, [x16, #:lo12:struct_obj_9 + 24]
+ adrp x16, var_16
+ ldrh w8, [x16, #:lo12:var_16]
+ adrp x16, var_58
+ ldrsb w1, [x16, #:lo12:var_58]
+ adrp x16, struct_obj_4 + 10
+ ldrh w6, [x16, #:lo12:struct_obj_4 + 10]
+ sub w11, w6, #28672
+ sub w11, w11, #2095
+ asr w9, w1, w11
+ lsl w8, w8, w17
+ sub w17, w8, #4096
+ sub w17, w17, #3785
+ asr w9, w9, w17
+ cmn w9, #17
+ cset x12, gt
+ adrp x16, struct_obj_8 + 16
+ ldrsb w11, [x16, #:lo12:struct_obj_8 + 16]
+ movn w16, #7837, lsl #0
+ and w10, w11, w16
+ movz w16, #22400, lsl #0
+ cmp w10, w16
+ cset x13, ne
+ orn w1, wzr, w29
+ eor w29, w13, w1
+ sdiv w13, w12, w29
+ adrp x16, var_260
+ strb w13, [x16, #:lo12:var_260]
+ b .L195
+.L192:
+ adrp x16, var_8
+ ldrh w10, [x16, #:lo12:var_8]
+ cbnz w10, .L196
+ adrp x16, struct_obj_9 + 8
+ ldrsh w2, [x16, #:lo12:struct_obj_9 + 8]
+ cmp w2, #0
+ cset x5, ne
+ cbz w5, .L197
+.L196:
+ adrp x16, var_59
+ ldrh w12, [x16, #:lo12:var_59]
+ sbfiz w0, w12, 0, 16
+ cmp w0, #0
+ cset x29, ne
+ cbnz w29, .L195
+.L197:
+ adrp x16, var_51
+ ldrsh w17, [x16, #:lo12:var_51]
+.L195:
+ adrp x16, var_39
+ ldrh w13, [x16, #:lo12:var_39]
+ movz w16, #10137, lsl #0
+ eor w14, w13, w16
+ adrp x16, var_14
+ ldrsb w29, [x16, #:lo12:var_14]
+ movz w16, #33, lsl #0
+ eor w3, w29, w16
+ and w11, w14, w3
+ sbfiz w10, w11, 0, 8
+ cbnz w10, .L198
+ adrp x16, var_62
+ ldrh w8, [x16, #:lo12:var_62]
+ orn w12, wzr, w8
+ adrp x16, struct_obj_8 + 4
+ strb w12, [x16, #:lo12:struct_obj_8 + 4]
+ adrp x16, var_24
+ ldrsh w8, [x16, #:lo12:var_24]
+ adrp x16, var_16
+ ldrh w17, [x16, #:lo12:var_16]
+ adrp x16, var_34
+ ldrsb w15, [x16, #:lo12:var_34]
+ adrp x16, struct_obj_3 + 6
+ ldrsh w5, [x16, #:lo12:struct_obj_3 + 6]
+ adrp x16, var_4
+ ldrh w11, [x16, #:lo12:var_4]
+ adrp x16, struct_obj_9 + 8
+ ldrsh w0, [x16, #:lo12:struct_obj_9 + 8]
+ adrp x16, struct_obj_9 + 10
+ ldrh w6, [x16, #:lo12:struct_obj_9 + 10]
+ madd w29, w0, w6, wzr
+ sub w6, wzr, w29
+ ubfiz w4, w6, 0, 16
+ sub w17, wzr, w17
+ madd w10, w17, w15, wzr
+ cmp w8, w10
+ cset x0, le
+ cmp w0, w5
+ cset x0, lt
+ add w8, w11, #24576
+ add w8, w8, #1397
+ orn w9, wzr, w8
+ sbfiz w8, w9, 0, 8
+ cmn w8, #123
+ cset x13, le
+ orr w15, w0, w13
+ orn w17, wzr, w15
+ b .L199
+.L198:
+ adrp x16, var_51
+ ldrsh w8, [x16, #:lo12:var_51]
+ ubfiz w4, w8, 0, 16
+ cbnz w4, .L200
+ adrp x16, struct_obj_8 + 16
+ ldrsb w0, [x16, #:lo12:struct_obj_8 + 16]
+ cbz w0, .L201
+ adrp x16, var_62
+ ldrh w11, [x16, #:lo12:var_62]
+ cmp w11, #0
+ cset x12, ne
+ b .L202
+.L201:
+ movz w12, #0, lsl #0
+ b .L202
+.L200:
+ orr w12, wzr, #1
+.L202:
+ cbz w12, .L203
+ adrp x16, var_8
+ ldrh w0, [x16, #:lo12:var_8]
+ cbnz w0, .L203
+ adrp x16, struct_obj_4 + 12
+ ldrsb w0, [x16, #:lo12:struct_obj_4 + 12]
+ cmp w0, #0
+ cset x0, ne
+.L203:
+ adrp x16, var_21
+ ldrsb w17, [x16, #:lo12:var_21]
+ adrp x16, struct_obj_8 + 28
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 28]
+ sub w14, w0, w29
+ adrp x16, var_17
+ ldrsh w0, [x16, #:lo12:var_17]
+ sub w2, wzr, w0
+ add w29, w14, w2
+ sub w4, wzr, w29
+ adrp x16, struct_obj_9 + 22
+ ldrh w3, [x16, #:lo12:struct_obj_9 + 22]
+ add w11, w4, w3
+ sub w8, w17, w11
+ adrp x16, var_268
+ strb w8, [x16, #:lo12:var_268]
+.L199:
+ adrp x16, struct_obj_9 + 22
+ ldrh w3, [x16, #:lo12:struct_obj_9 + 22]
+ orr w29, wzr, #1
+ adrp x16, struct_obj_4 + 2
+ ldrsb w10, [x16, #:lo12:struct_obj_4 + 2]
+ movn w16, #3614, lsl #0
+ eor w14, w10, w16
+ sbfiz w13, w14, 0, 8
+ movn w16, #53, lsl #0
+ eor w17, w13, w16
+ sub w1, w17, #115
+ asr w12, w29, w1
+ adrp x16, var_29
+ ldrh w11, [x16, #:lo12:var_29]
+ adrp x16, var_26
+ ldrh w15, [x16, #:lo12:var_26]
+ cmp w11, w15
+ cset x1, ne
+ movz w16, #53609, lsl #0
+ eor w17, w1, w16
+ adrp x16, var_48
+ ldrh w4, [x16, #:lo12:var_48]
+ orr w2, wzr, w4, lsr #31
+ sxtw x0, w4
+ movz x11, #31139, lsl #0
+ movk x11, #11586, lsl #16
+ madd x1, x0, x11, xzr
+ orr x8, xzr, x1, asr #32
+ add w29, w2, w8, asr #11
+ movn w16, #23752, lsl #0
+ orr w9, w29, w16
+ cmp w17, w9
+ cset x9, ge
+ eor w2, w9, #1
+ adrp x16, var_284
+ strh w2, [x16, #:lo12:var_284]
+ adrp x16, var_30
+ ldrh w13, [x16, #:lo12:var_30]
+ adrp x16, var_5
+ ldrh w0, [x16, #:lo12:var_5]
+ and w13, w13, w0
+ orr w0, w13, #30
+ eon w0, w0, w12
+ movz w16, #65513, lsl #0
+ and w4, w0, w16
+ orn w8, wzr, w4
+ orr w16, wzr, #2147483647
+ add w0, w8, w16
+ adrp x16, struct_obj_9 + 8
+ ldrsh w29, [x16, #:lo12:struct_obj_9 + 8]
+ movz w16, #64443, lsl #0
+ orr w5, w29, w16
+ adrp x16, struct_obj_8 + 20
+ ldrsh w6, [x16, #:lo12:struct_obj_8 + 20]
+ eor w8, w6, #-17
+ adrp x16, struct_obj_2 + 4
+ ldrh w14, [x16, #:lo12:struct_obj_2 + 4]
+ movz w16, #46991, lsl #0
+ and w1, w14, w16
+ orr w6, w8, w1
+ sub w1, w6, #45056
+ sub w1, w1, #1939
+ asr w12, w5, w1
+ sub w10, w12, #4091
+ lsl w1, w0, w10
+ adrp x16, struct_obj_8 + 18
+ strh w1, [x16, #:lo12:struct_obj_8 + 18]
+.L184:
+ movz w6, #0, lsl #0
+ adrp x16, var_359
+ strh w6, [x16, #:lo12:var_359]
+ adrp x16, var_43
+ ldrh w0, [x16, #:lo12:var_43]
+ sbfiz w2, w0, 0, 16
+ adrp x16, struct_obj_4 + 10
+ ldrh w9, [x16, #:lo12:struct_obj_4 + 10]
+ orn w12, wzr, w9
+ orr w16, wzr, #2147483647
+ add w14, w12, w16
+ adrp x16, struct_obj_2
+ ldrsh w8, [x16, #:lo12:struct_obj_2]
+ movn w16, #15348, lsl #0
+ and w8, w8, w16
+ orr w16, wzr, #2147483647
+ add w6, w8, w16
+ movz w16, #33773, lsl #0
+ movk w16, #32767, lsl #16
+ sub w13, w6, w16
+ asr w3, w14, w13
+ orr w6, w2, w3
+ adrp x16, var_7
+ ldrsb w3, [x16, #:lo12:var_7]
+ adrp x16, struct_obj_4 + 22
+ ldrh w4, [x16, #:lo12:struct_obj_4 + 22]
+ eor w13, w3, w4, lsl #5
+ adrp x16, var_60
+ ldrsh w14, [x16, #:lo12:var_60]
+ movz w16, #38, lsl #0
+ and w15, w14, w16
+ adrp x16, struct_obj_9 + 10
+ ldrh w0, [x16, #:lo12:struct_obj_9 + 10]
+ adrp x16, var_50
+ ldrh w12, [x16, #:lo12:var_50]
+ sub w4, w12, #45056
+ sub w4, w4, #1901
+ asr w0, w0, w4
+ lsl w9, w15, w0
+ lsl w10, w13, w9
+ movz w14, #0, lsl #0
+ orr w5, wzr, w14, lsl #11
+ movn w16, #76, lsl #0
+ orr w15, w5, w16
+ bic w8, w10, w15
+ and w6, w6, w8
+ cbz w6, .L204
+ adrp x16, struct_obj_9 + 2
+ ldrsb w6, [x16, #:lo12:struct_obj_9 + 2]
+ movz w6, #18490, lsl #0
+ movn w16, #34, lsl #0
+ orr w17, w12, w16
+ adrp x16, var_56
+ ldrh w4, [x16, #:lo12:var_56]
+ eon w2, w17, w4
+ sub w29, w2, #16384
+ sub w29, w29, #3818
+ lsl w11, w6, w29
+ adrp x16, var_367
+ strb w11, [x16, #:lo12:var_367]
+ adrp x16, var_46
+ ldrh w0, [x16, #:lo12:var_46]
+ adrp x16, struct_obj_9 + 10
+ ldrh w3, [x16, #:lo12:struct_obj_9 + 10]
+ adrp x16, var_35
+ ldrh w8, [x16, #:lo12:var_35]
+ cbnz w8, .L205
+ adrp x16, struct_obj_4 + 18
+ ldrsh w6, [x16, #:lo12:struct_obj_4 + 18]
+ cmp w6, #0
+ cset x8, ne
+ cbnz w8, .L205
+ cbnz w3, .L206
+ adrp x16, struct_obj_5
+ ldrsb w6, [x16, #:lo12:struct_obj_5]
+ cmp w6, #0
+ cset x17, ne
+ b .L207
+.L206:
+ orr w17, wzr, #1
+ b .L207
+.L205:
+ orr w17, wzr, #1
+.L207:
+ adrp x16, struct_obj_8 + 26
+ ldrsb w14, [x16, #:lo12:struct_obj_8 + 26]
+ adrp x16, struct_obj_1 + 6
+ ldrsh w8, [x16, #:lo12:struct_obj_1 + 6]
+ eor w9, w14, w8
+ movn w16, #14805, lsl #0
+ eor w0, w0, w16
+ eor w9, w9, w0
+ cbz w9, .L208
+ adrp x16, struct_obj_8 + 4
+ ldrsb w15, [x16, #:lo12:struct_obj_8 + 4]
+ and w29, w8, w15
+ adrp x16, struct_obj_5 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_5 + 6]
+ bic w8, w29, w0
+ cmp w8, #0
+ cset x8, ne
+ b .L209
+.L208:
+ movz w8, #0, lsl #0
+.L209:
+ movz w14, #17, lsl #0
+ adrp x16, var_56
+ ldrh w1, [x16, #:lo12:var_56]
+ sub w3, w1, #16384
+ sub w3, w3, #3797
+ lsl w6, w14, w3
+ orn w1, wzr, w6
+ cmp w1, w17
+ cset x17, gt
+ cmp w17, w8
+ b.le .L210
+ movz w17, #0, lsl #0
+ orn w14, wzr, w7
+ ubfiz w4, w14, 0, 16
+ sdiv w15, w17, w4
+ msub w13, w15, w4, w17
+ movz w16, #14314, lsl #0
+ cmp w13, w16
+ cset x2, le
+ b .L211
+.L210:
+ orr w2, wzr, #1
+.L211:
+ adrp x16, var_46
+ strh w2, [x16, #:lo12:var_46]
+ adrp x16, var_20
+ ldrh w8, [x16, #:lo12:var_20]
+ adrp x16, var_24
+ ldrsh w9, [x16, #:lo12:var_24]
+ adrp x16, struct_obj_8 + 20
+ ldrsh w12, [x16, #:lo12:struct_obj_8 + 20]
+ add w3, w9, w12
+ add w6, w3, #16384
+ add w6, w6, #3130
+ ubfiz w11, w6, 0, 16
+ adrp x16, struct_obj_3 + 2
+ ldrh w6, [x16, #:lo12:struct_obj_3 + 2]
+ movz w16, #24836, lsl #0
+ and w1, w6, w16
+ movz w16, #14314, lsl #0
+ eor w5, w1, w16
+ orn w15, wzr, w5
+ sdiv w2, w11, w15
+ msub w13, w2, w15, w11
+.L204:
+ adrp x16, struct_obj_8 + 12
+ ldrsb w2, [x16, #:lo12:struct_obj_8 + 12]
+ sub w13, wzr, w2
+ cbz w13, .L212
+ orn w13, wzr, w7
+ sub w2, wzr, w13
+ adrp x16, var_392
+ strh w2, [x16, #:lo12:var_392]
+ adrp x16, var_14
+ ldrsb w6, [x16, #:lo12:var_14]
+ adrp x16, struct_obj_9 + 10
+ ldrh w14, [x16, #:lo12:struct_obj_9 + 10]
+ cbnz w14, .L213
+ adrp x16, var_47
+ ldrsb w1, [x16, #:lo12:var_47]
+.L213:
+ adrp x16, var_65
+ ldrsh w29, [x16, #:lo12:var_65]
+ adrp x16, var_35
+ ldrh w17, [x16, #:lo12:var_35]
+ sub w11, w17, #12288
+ sub w11, w11, #2120
+ asr w10, w17, w11
+ ubfiz w17, w10, 0, 16
+ adrp x16, struct_obj_10
+ ldrsb w1, [x16, #:lo12:struct_obj_10]
+ ubfiz w29, w1, 0, 16
+ cbnz w29, .L212
+ adrp x16, var_63
+ ldrsh w4, [x16, #:lo12:var_63]
+ cbz w4, .L212
+ cbz w6, .L212
+ adrp x16, var_3
+ ldrsb w6, [x16, #:lo12:var_3]
+ cmp w6, #0
+ cset x12, ne
+.L212:
+ orr w10, wzr, #1
+ movz w6, #0, lsl #0
+ adrp x16, struct_obj_1 + 4
+ ldrh w5, [x16, #:lo12:struct_obj_1 + 4]
+ cmp w5, #0
+ csel x0, x10, x6, ne
+ cbz w0, .L214
+ adrp x16, var_26
+ ldrh w5, [x16, #:lo12:var_26]
+ cbnz w5, .L215
+ cmp w7, #0
+ cset x17, eq
+ cbnz w17, .L214
+.L215:
+ movz w1, #0, lsl #0
+ b .L216
+.L214:
+ adrp x16, struct_obj_4 + 14
+ ldrsh w3, [x16, #:lo12:struct_obj_4 + 14]
+ cmp w3, #0
+ cset x8, ne
+ eor w1, w8, #1
+.L216:
+ cbz w1, .L217
+ adrp x16, var_6
+ ldrh w0, [x16, #:lo12:var_6]
+ orn w0, wzr, w0
+ movz w16, #45366, lsl #0
+ and w4, w0, w16
+ adrp x16, struct_obj_8 + 4
+ ldrsb w14, [x16, #:lo12:struct_obj_8 + 4]
+ adrp x16, struct_obj_8 + 12
+ ldrsb w3, [x16, #:lo12:struct_obj_8 + 12]
+ and w3, w14, w3
+ adrp x16, var_55
+ ldrsb w13, [x16, #:lo12:var_55]
+ orn w0, w3, w13
+ and w0, w4, w0
+ sbfiz w0, w0, 0, 8
+ orn w0, wzr, w0
+ cbz w0, .L218
+ adrp x16, struct_obj_6 + 4
+ ldrh w0, [x16, #:lo12:struct_obj_6 + 4]
+ adrp x16, var_63
+ ldrsh w0, [x16, #:lo12:var_63]
+ ubfiz w6, w0, 0, 16
+ adrp x16, struct_obj_4 + 18
+ ldrsh w11, [x16, #:lo12:struct_obj_4 + 18]
+ movz w16, #888, lsl #0
+ eor w7, w11, w16
+ eon w0, w6, w7
+ adrp x16, var_61
+ ldrsb w0, [x16, #:lo12:var_61]
+ cbz w0, .L219
+ adrp x16, struct_obj_9 + 8
+ ldrsh w0, [x16, #:lo12:struct_obj_9 + 8]
+.L219:
+ orr w13, wzr, #1
+ adrp x16, var_26
+ ldrh w8, [x16, #:lo12:var_26]
+ cbnz w8, .L220
+ orr w12, wzr, #1
+ b .L221
+.L220:
+ movz w12, #0, lsl #0
+.L221:
+ cmp w13, #0
+ cset x7, lt
+ adrp x16, struct_obj_4 + 14
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 14]
+ sub w8, wzr, w0
+ adrp x16, var_56
+ ldrh w4, [x16, #:lo12:var_56]
+ sbfiz w5, w4, 0, 8
+ cmp w8, w5
+ cset x10, ne
+ cmp w12, w10
+ cset x4, lt
+ asr w2, w7, w4
+ adrp x16, var_52
+ ldrsh w3, [x16, #:lo12:var_52]
+ movz w16, #6800, lsl #0
+ eor w12, w3, w16
+ orr w4, w12, #4
+ movn w16, #20, lsl #0
+ eor w10, w4, w16
+ cmp w2, w10
+ cset x0, eq
+ adrp x16, struct_obj_5 + 6
+ strh w0, [x16, #:lo12:struct_obj_5 + 6]
+.L218:
+ adrp x16, var_16
+ ldrh w9, [x16, #:lo12:var_16]
+ adrp x16, var_60
+ ldrsh w1, [x16, #:lo12:var_60]
+ eor w0, w9, w1
+ movn w16, #8171, lsl #0
+ eor w0, w0, w16
+ sbfiz w11, w0, 0, 8
+ adrp x16, var_63
+ ldrsh w2, [x16, #:lo12:var_63]
+ eon w0, w11, w2
+ cbz w0, .L222
+ adrp x16, var_23
+ ldrh w14, [x16, #:lo12:var_23]
+ adrp x16, var_30
+ ldrh w2, [x16, #:lo12:var_30]
+ orn w29, wzr, w2
+ cbz w29, .L222
+.L222:
+ movz w5, #29097, lsl #0
+ movk w5, #32767, lsl #16
+ adrp x16, struct_obj_1 + 6
+ ldrsh w10, [x16, #:lo12:struct_obj_1 + 6]
+ adrp x16, var_2
+ ldrh w11, [x16, #:lo12:var_2]
+ sub w1, w11, #16384
+ sub w1, w1, #1397
+ lsl w6, w10, w1
+ sub w0, w6, #4096
+ sub w0, w0, #1824
+ lsl w15, w5, w0
+ adrp x16, struct_obj_4 + 8
+ ldrsh w3, [x16, #:lo12:struct_obj_4 + 8]
+ sbfiz w17, w3, 0, 8
+ bic w5, w15, w17
+ adrp x16, var_33
+ ldrh w15, [x16, #:lo12:var_33]
+ orr w2, wzr, w15, lsl #11
+ adrp x16, var_20
+ ldrh w6, [x16, #:lo12:var_20]
+ sbfiz w6, w6, 0, 16
+ add w17, w6, #12288
+ add w17, w17, #3732
+ asr w29, w2, w17
+ movz w17, #65433, lsl #0
+ movk w17, #32767, lsl #16
+ adrp x16, struct_obj_4 + 20
+ ldrsh w14, [x16, #:lo12:struct_obj_4 + 20]
+ movn w16, #7862, lsl #0
+ eor w0, w14, w16
+ sub w7, w0, #20480
+ sub w7, w7, #1456
+ asr w0, w17, w7
+ eor w11, w29, w0
+ eor w29, w5, w11
+ adrp x16, struct_obj_4 + 16
+ ldrsb w4, [x16, #:lo12:struct_obj_4 + 16]
+ orn w0, w29, w4
+ cbz w0, .L223
+ movz w0, #25335, lsl #0
+ adrp x16, var_36
+ strh w0, [x16, #:lo12:var_36]
+ adrp x16, struct_obj_2 + 4
+ ldrh w0, [x16, #:lo12:struct_obj_2 + 4]
+ movz w16, #57552, lsl #0
+ eor w2, w0, w16
+ adrp x16, var_38
+ ldrsb w7, [x16, #:lo12:var_38]
+ movz w16, #2460, lsl #0
+ and w13, w7, w16
+ asr w0, w2, w13
+ adrp x16, var_37
+ ldrsb w0, [x16, #:lo12:var_37]
+ orn w0, wzr, w0
+.L223:
+ adrp x16, struct_obj_8
+ ldrh w13, [x16, #:lo12:struct_obj_8]
+ adrp x16, struct_obj_9 + 4
+ ldrsh w7, [x16, #:lo12:struct_obj_9 + 4]
+ sub w2, w7, #28672
+ sub w2, w2, #3284
+ lsl w8, w13, w2
+ adrp x16, struct_obj_8 + 8
+ ldrsb w6, [x16, #:lo12:struct_obj_8 + 8]
+ bic w3, w8, w6
+ adrp x16, var_56
+ ldrh w17, [x16, #:lo12:var_56]
+ adrp x16, var_43
+ ldrh w29, [x16, #:lo12:var_43]
+ adrp x16, var_13
+ ldrsh w15, [x16, #:lo12:var_13]
+ add w8, w15, #20480
+ add w8, w8, #3434
+ asr w6, w29, w8
+ adrp x16, struct_obj_4 + 14
+ ldrsh w12, [x16, #:lo12:struct_obj_4 + 14]
+ adrp x16, var_6
+ ldrh w2, [x16, #:lo12:var_6]
+ and w11, w12, w2
+ sub w4, w11, #32768
+ sub w4, w4, #2751
+ asr w4, w6, w4
+ orr w8, w17, w4
+ eon w14, w3, w8
+ cbz w14, .L224
+ adrp x16, var_20
+ ldrh w6, [x16, #:lo12:var_20]
+ adrp x16, var_18
+ ldrsb w3, [x16, #:lo12:var_18]
+ and w0, w6, w3
+ adrp x16, struct_obj_7
+ ldrsb w12, [x16, #:lo12:struct_obj_7]
+ orn w13, w0, w12
+ adrp x16, var_57
+ ldrsb w29, [x16, #:lo12:var_57]
+ movn w16, #5371, lsl #0
+ orr w10, w29, w16
+ eon w29, w13, w10
+ adrp x16, var_28
+ ldrsh w2, [x16, #:lo12:var_28]
+ movn w11, #23905, lsl #0
+ adrp x16, var_22
+ ldrsb w9, [x16, #:lo12:var_22]
+ adrp x16, struct_obj_4 + 18
+ ldrsh w13, [x16, #:lo12:struct_obj_4 + 18]
+ add w1, w9, w13
+ sub w5, w11, w1
+ sub w7, w2, w5
+ adrp x16, var_2
+ ldrh w8, [x16, #:lo12:var_2]
+ adrp x16, struct_obj_10
+ ldrsb w12, [x16, #:lo12:struct_obj_10]
+ add w9, w8, w12
+ adrp x16, struct_obj_10 + 4
+ ldrsb w5, [x16, #:lo12:struct_obj_10 + 4]
+ add w14, w9, w5
+ adrp x16, var_23
+ ldrh w1, [x16, #:lo12:var_23]
+ sub w12, w1, #28672
+ sub w12, w12, #777
+ sub w6, wzr, w12
+ add w8, w14, w6
+ sub w8, w7, w8
+ add w3, w8, #53248
+ add w3, w3, #2668
+ adrp x16, struct_obj_9 + 22
+ ldrh w13, [x16, #:lo12:struct_obj_9 + 22]
+ adrp x16, struct_obj_9 + 10
+ ldrh w9, [x16, #:lo12:struct_obj_9 + 10]
+ cbnz w15, .L225
+ adrp x16, var_48
+ ldrh w10, [x16, #:lo12:var_48]
+ cmp w10, #0
+ cset x6, eq
+ b .L226
+.L225:
+ orr w6, wzr, #1
+.L226:
+ orr w8, wzr, #1
+ movz w29, #0, lsl #0
+ cmp w6, #0
+ csel x13, x8, x29, ne
+.L224:
+ adrp x16, var_60
+ ldrsh w4, [x16, #:lo12:var_60]
+ movz w29, #59623, lsl #0
+ adrp x16, struct_obj_2 + 6
+ ldrsh w13, [x16, #:lo12:struct_obj_2 + 6]
+ adrp x16, var_16
+ ldrh w15, [x16, #:lo12:var_16]
+ madd w10, w13, w15, wzr
+ sbfiz w9, w10, 0, 8
+ adrp x16, var_34
+ ldrsb w15, [x16, #:lo12:var_34]
+ adrp x16, var_24
+ ldrsh w14, [x16, #:lo12:var_24]
+ sbfiz w10, w14, 0, 16
+ cmp w15, w10
+ cset x15, lt
+ adrp x16, var_14
+ ldrsb w11, [x16, #:lo12:var_14]
+ adrp x16, var_33
+ ldrh w7, [x16, #:lo12:var_33]
+ adrp x16, struct_obj_3
+ ldrsh w2, [x16, #:lo12:struct_obj_3]
+ orn w0, wzr, w2
+ adrp x16, struct_obj_6 + 4
+ ldrh w3, [x16, #:lo12:struct_obj_6 + 4]
+ add w8, w3, w4
+ madd w2, w0, w8, wzr
+ cbz w2, .L227
+ movz w2, #0, lsl #0
+ movz w3, #0, lsl #0
+ adrp x16, struct_obj_6
+ ldrsh w8, [x16, #:lo12:struct_obj_6]
+ cmp w8, #0
+ csel x0, x2, x3, ne
+ sbfiz w13, w7, 0, 8
+ cmp w0, w13
+ cset x1, le
+ cbnz w1, .L228
+.L227:
+ madd w5, w9, w29, wzr
+ bic w12, w11, w11
+ and w12, w15, w12
+ madd w3, w5, w12, wzr
+ adrp x16, struct_obj_5 + 2
+ ldrsh w5, [x16, #:lo12:struct_obj_5 + 2]
+ movz w16, #11652, lsl #0
+ and w10, w5, w16
+ bic w15, w3, w10
+ sbfiz w7, w4, 0, 8
+ ubfiz w11, w7, 0, 16
+ orn w7, w15, w11
+ cmp w7, #0
+ cset x15, ne
+ cbnz w15, .L228
+ orr w13, wzr, #1
+ orr w15, wzr, #1
+ adrp x16, struct_obj_4 + 22
+ ldrh w29, [x16, #:lo12:struct_obj_4 + 22]
+ movn w16, #26751, lsl #0
+ tst w29, w16
+ csel x0, x13, x15, ne
+ adrp x16, var_32
+ ldrh w15, [x16, #:lo12:var_32]
+ orr w6, wzr, #-65
+ sdiv w1, w15, w6
+ movz w16, #45959, lsl #0
+ cmp w1, w16
+ cset x3, ge
+ sub w0, w0, w3
+ cbz w0, .L229
+ adrp x16, struct_obj_3 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_3 + 6]
+.L229:
+ adrp x16, struct_obj_3 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_3 + 6]
+ b .L168
+.L228:
+ adrp x16, var_18
+ ldrsb w0, [x16, #:lo12:var_18]
+ cbz w0, .L230
+ cmp w17, #0
+ cset x0, ne
+ cbnz w0, .L168
+.L230:
+ adrp x16, struct_obj_5 + 6
+ ldrsh w0, [x16, #:lo12:struct_obj_5 + 6]
+ b .L168
+.L217:
+ adrp x16, struct_obj_4 + 26
+ ldrsh w0, [x16, #:lo12:struct_obj_4 + 26]
+ adrp x16, var_35
+ ldrh w1, [x16, #:lo12:var_35]
+ sbfiz w14, w1, 0, 16
+ adrp x16, struct_obj_4
+ ldrsh w2, [x16, #:lo12:struct_obj_4]
+ orn w17, w14, w2
+ cmp w0, w17
+ cset x8, gt
+ adrp x16, struct_obj_4 + 8
+ ldrsh w1, [x16, #:lo12:struct_obj_4 + 8]
+ movz w16, #39209, lsl #0
+ eor w0, w1, w16
+ cmp w8, w0
+ cset x0, gt
+ adrp x16, var_14
+ ldrsb w14, [x16, #:lo12:var_14]
+ adrp x16, struct_obj_3 + 4
+ ldrh w29, [x16, #:lo12:struct_obj_3 + 4]
+ cmp w14, w29
+ cset x14, eq
+ adrp x16, struct_obj_4 + 18
+ ldrsh w9, [x16, #:lo12:struct_obj_4 + 18]
+ movz w16, #56773, lsl #0
+ cmp w9, w16
+ cset x17, ge
+ madd w14, w14, w17, wzr
+ sbfiz w4, w14, 0, 16
+ adrp x16, var_13
+ ldrsh w14, [x16, #:lo12:var_13]
+ orr w16, wzr, #2147483647
+ add w11, w14, w16
+ orr w14, wzr, w11, asr #29
+ adrp x16, struct_obj_2 + 2
+ ldrh w29, [x16, #:lo12:struct_obj_2 + 2]
+ sub w5, w29, #24576
+ sub w5, w5, #1173
+ lsl w9, w14, w5
+ cmp w4, w9
+ cset x8, le
+ cmp w0, w8
+ cset x14, ne
+ cbz w14, .L168
+ adrp x16, var_10
+ ldrh w0, [x16, #:lo12:var_10]
+ sbfiz w0, w0, 0, 8
+ orr w5, wzr, #1
+ movz w12, #0, lsl #0
+ adrp x16, var_23
+ ldrh w17, [x16, #:lo12:var_23]
+ sub w2, wzr, w5
+ movz w1, #44106, lsl #0
+ movk w1, #32767, lsl #16
+ asr w1, w1, w12
+ cmp w2, w1
+ cset x8, lt
+ cmp w17, w8
+ cset x0, lt
+ adrp x16, var_53
+ strh w0, [x16, #:lo12:var_53]
+ adrp x16, struct_obj_2 + 2
+ ldrh w0, [x16, #:lo12:struct_obj_2 + 2]
+ orn w0, wzr, w0
+ orn w0, wzr, w0
+ movz w16, #41, lsl #0
+ orr w0, w0, w16
+ sbfiz w3, w0, 0, 8
+ adrp x16, struct_obj_4 + 18
+ ldrsh w11, [x16, #:lo12:struct_obj_4 + 18]
+ cmp w11, #0
+ cset x0, eq
+ movz w1, #65006, lsl #0
+ adrp x16, struct_obj_8 + 22
+ ldrh w2, [x16, #:lo12:struct_obj_8 + 22]
+ madd w11, w2, w1, wzr
+ adrp x16, struct_obj_8 + 6
+ ldrsh w15, [x16, #:lo12:struct_obj_8 + 6]
+ sub w1, wzr, w15
+ sdiv w6, w11, w1
+ ubfiz w4, w6, 0, 16
+ madd w15, w0, w4, wzr
+ adrp x16, struct_obj_8 + 26
+ ldrsb w11, [x16, #:lo12:struct_obj_8 + 26]
+ adrp x16, struct_obj_5
+ ldrsb w6, [x16, #:lo12:struct_obj_5]
+ eor w9, w11, w6
+ adrp x16, var_37
+ ldrsb w29, [x16, #:lo12:var_37]
+ movz w16, #2436, lsl #0
+ orr w14, w29, w16
+ eor w6, w9, w14
+ eon w14, w6, w3
+ cmp w15, w14
+ cset x0, lt
+ adrp x16, var_468
+ strb w0, [x16, #:lo12:var_468]
+.L168:
+ adrp x16, var_10
+ ldrh w4, [x16, #:lo12:var_10]
+ adrp x16, struct_obj_2 + 2
+ ldrh w9, [x16, #:lo12:struct_obj_2 + 2]
+ sub w10, w9, #24576
+ sub w10, w10, #1167
+ asr w4, w4, w10
+ adrp x16, var_49
+ ldrsb w6, [x16, #:lo12:var_49]
+ orn w10, wzr, w6
+ add w7, w10, #31
+ lsl w1, w4, w7
+ orn w13, wzr, w1
+ adrp x16, var_36
+ ldrsh w14, [x16, #:lo12:var_36]
+ adrp x16, var_18
+ ldrsb w9, [x16, #:lo12:var_18]
+ adrp x16, struct_obj_2
+ ldrsh w3, [x16, #:lo12:struct_obj_2]
+ bic w1, w9, w3
+ and w9, w14, w1
+ eon w4, w13, w9
+ sbfiz w14, w4, 0, 16
+ adrp x16, var_9
+ ldrh w4, [x16, #:lo12:var_9]
+ sbfiz w5, w4, 0, 8
+ adrp x16, struct_obj_8 + 16
+ ldrsb w2, [x16, #:lo12:struct_obj_8 + 16]
+ movn w16, #2066, lsl #0
+ eor w13, w2, w16
+ eon w6, w13, w6
+ movz w7, #36764, lsl #0
+ movk w7, #32767, lsl #16
+ adrp x16, var_45
+ ldrsb w8, [x16, #:lo12:var_45]
+ adrp x16, var_27
+ ldrsh w9, [x16, #:lo12:var_27]
+ orr w8, w8, w9
+ add w1, w8, #3
+ lsl w15, w7, w1
+ orr w0, w6, w15
+ adrp x16, var_65
+ ldrsh w15, [x16, #:lo12:var_65]
+ add w29, w15, #12288
+ add w29, w29, #558
+ lsl w6, w0, w29
+ cmp w5, w6
+ cset x15, ne
+ adrp x16, var_26
+ ldrh w10, [x16, #:lo12:var_26]
+ movz w11, #5330, lsl #0
+ adrp x16, struct_obj_1 + 4
+ ldrh w29, [x16, #:lo12:struct_obj_1 + 4]
+ madd w0, w29, w11, wzr
+ movz w1, #101, lsl #0
+ madd w17, w29, w1, wzr
+ sdiv w13, w0, w17
+ orn w9, wzr, w13
+ adrp x16, struct_obj_8 + 14
+ ldrh w7, [x16, #:lo12:struct_obj_8 + 14]
+ madd w7, w9, w7, wzr
+ adrp x16, struct_obj_2 + 6
+ ldrsh w29, [x16, #:lo12:struct_obj_2 + 6]
+ adrp x16, var_48
+ ldrh w2, [x16, #:lo12:var_48]
+ madd w5, w29, w2, wzr
+ adrp x16, struct_obj_3 + 4
+ ldrh w17, [x16, #:lo12:struct_obj_3 + 4]
+ sub w6, w5, w17
+ add w9, w6, #4096
+ add w9, w9, #3658
+ orr w2, w7, w9
+ ubfiz w1, w2, 0, 16
+ adrp x16, var_47
+ ldrsb w11, [x16, #:lo12:var_47]
+ orn w5, w10, w11
+ movz w29, #33232, lsl #0
+ adrp x16, var_43
+ ldrh w12, [x16, #:lo12:var_43]
+ madd w13, w12, w29, wzr
+ sub w29, wzr, w13
+ orn w13, wzr, w29
+ movz w16, #2753, lsl #0
+ and w6, w13, w16
+ sdiv w7, w5, w6
+ msub w11, w7, w6, w5
+ ubfiz w0, w11, 0, 16
+ adrp x16, struct_obj_10 + 4
+ ldrsb w9, [x16, #:lo12:struct_obj_10 + 4]
+ adrp x16, struct_obj_1 + 2
+ ldrh w7, [x16, #:lo12:struct_obj_1 + 2]
+ sdiv w29, w9, w7
+ adrp x16, var_29
+ ldrh w7, [x16, #:lo12:var_29]
+ sdiv w11, w29, w7
+ msub w13, w11, w7, w29
+ sbfiz w11, w13, 0, 8
+ cmp w11, #1
+ b.le .L231
+ movn w29, #123, lsl #0
+ adrp x16, var_33
+ ldrh w11, [x16, #:lo12:var_33]
+ orn w8, wzr, w11
+ sub w11, w29, w8
+ orn w13, wzr, w11
+ adrp x16, var_16
+ ldrh w5, [x16, #:lo12:var_16]
+ adrp x16, struct_obj_6 + 2
+ ldrh w12, [x16, #:lo12:struct_obj_6 + 2]
+ cmp w5, w12
+ cset x5, ge
+ adrp x16, var_3
+ ldrsb w2, [x16, #:lo12:var_3]
+ adrp x16, struct_obj_8 + 8
+ ldrsb w8, [x16, #:lo12:struct_obj_8 + 8]
+ orr w29, w2, w8
+ cmp w5, w29
+ cset x2, ne
+ movn w16, #7351, lsl #0
+ and w11, w2, w16
+ cmp w13, w11
+ cset x6, eq
+ sub w2, wzr, w6
+ cbnz w2, .L232
+ adrp x16, struct_obj_6 + 6
+ ldrsh w7, [x16, #:lo12:struct_obj_6 + 6]
+ cbz w7, .L233
+ adrp x16, struct_obj_7
+ ldrsb w7, [x16, #:lo12:struct_obj_7]
+ cmp w7, #0
+ cset x11, ne
+.L233:
+ movn w8, #10, lsl #0
+ adrp x16, var_522
+ strb w8, [x16, #:lo12:var_522]
+ adrp x16, var_1
+ ldrh w3, [x16, #:lo12:var_1]
+ adrp x16, var_30
+ ldrh w13, [x16, #:lo12:var_30]
+ adrp x16, struct_obj_4 + 24
+ ldrh w19, [x16, #:lo12:struct_obj_4 + 24]
+ adrp x16, struct_obj_5
+ ldrsb w7, [x16, #:lo12:struct_obj_5]
+ cbz w17, .L234
+ adrp x16, var_17
+ ldrsh w2, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w11, [x16, #:lo12:var_9]
+ sub w11, w11, #12288
+ sub w11, w11, #1187
+ lsl w4, w2, w11
+ cmp w4, #0
+ cset x20, ne
+ b .L235
+.L234:
+ movz w20, #0, lsl #0
+.L235:
+ adrp x16, struct_obj_3 + 4
+ ldrh w9, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w9, .L236
+ adrp x16, var_17
+ ldrsh w29, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w17, [x16, #:lo12:var_9]
+ sub w17, w17, #12288
+ sub w17, w17, #1187
+ lsl w12, w29, w17
+ cmp w12, #0
+ cset x29, ne
+ b .L237
+.L236:
+ movz w29, #0, lsl #0
+.L237:
+ adrp x16, struct_obj_4 + 4
+ ldrsh w2, [x16, #:lo12:struct_obj_4 + 4]
+ movz w16, #24281, lsl #0
+ and w17, w2, w16
+ movn w16, #76, lsl #0
+ eor w11, w9, w16
+ orr w8, wzr, w13, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w6, w8, w16
+ and w11, w11, w6
+ adrp x16, struct_obj_2
+ ldrsh w2, [x16, #:lo12:struct_obj_2]
+ sub w2, wzr, w2
+ sub w12, wzr, w2
+ sub w4, wzr, w3
+ madd w2, w12, w4, wzr
+ cmp w29, #4
+ cset x6, ne
+ cmp w2, w6
+ cset x3, gt
+ cmp w11, w3
+ cset x8, ge
+ asr w3, w17, w8
+ sub w8, w13, #40960
+ sub w8, w8, #1739
+ asr w5, w3, w8
+ cmp w5, #0
+ cset x5, ne
+ adrp x16, var_36
+ ldrsh w12, [x16, #:lo12:var_36]
+ tst w12, #126
+ cset x13, eq
+ cmp w20, #4
+ cset x6, ne
+ cmp w2, w6
+ cset x2, gt
+ cmp w11, w2
+ cset x29, ge
+ movn w16, #1113, lsl #0
+ eor w2, w19, w16
+ ubfiz w6, w2, 0, 16
+ movn w16, #28029, lsl #0
+ cmp w6, w16
+ cset x17, ge
+ cmp w29, w17
+ cset x29, gt
+ sub w29, w29, w5
+ and w11, w13, w29
+ cbnz w11, .L238
+ adrp x16, struct_obj_4 + 20
+ ldrsh w17, [x16, #:lo12:struct_obj_4 + 20]
+.L238:
+ movn w9, #0, lsl #0
+ movz w2, #10162, lsl #0
+ adrp x16, struct_obj_1 + 2
+ ldrh w17, [x16, #:lo12:struct_obj_1 + 2]
+ madd w29, w17, w2, wzr
+ ubfiz w6, w29, 0, 16
+ sub w12, wzr, w6
+ madd w2, w12, w9, wzr
+ cbnz w2, .L239
+ cmp w7, #0
+ cset x12, ne
+ b .L240
+.L239:
+ orr w12, wzr, #1
+.L240:
+ adrp x16, var_36
+ strh w12, [x16, #:lo12:var_36]
+ b .L241
+.L232:
+ cbz w17, .L242
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ sub w29, w4, #12288
+ sub w29, w29, #1187
+ lsl w4, w7, w29
+ cmp w4, #0
+ cset x13, ne
+ b .L243
+.L242:
+ movz w13, #0, lsl #0
+.L243:
+ movn w16, #76, lsl #0
+ eor w7, w17, w16
+ adrp x16, var_30
+ ldrh w5, [x16, #:lo12:var_30]
+ orr w29, wzr, w5, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w2, w29, w16
+ and w12, w7, w2
+ sub w11, wzr, w3
+ sub w5, wzr, w11
+ adrp x16, var_1
+ ldrh w11, [x16, #:lo12:var_1]
+ sub w3, wzr, w11
+ madd w6, w5, w3, wzr
+ cmp w13, #4
+ cset x5, ne
+ cmp w6, w5
+ cset x3, gt
+ adrp x16, struct_obj_4 + 22
+ ldrh w9, [x16, #:lo12:struct_obj_4 + 22]
+ adrp x16, var_20
+ ldrh w11, [x16, #:lo12:var_20]
+ bic w4, w11, w17
+ adrp x16, struct_obj_4 + 16
+ ldrsb w2, [x16, #:lo12:struct_obj_4 + 16]
+ adrp x16, struct_obj_8 + 30
+ ldrsb w17, [x16, #:lo12:struct_obj_8 + 30]
+ and w13, w2, w17
+ eon w17, w4, w13
+ adrp x16, var_514
+ strh w17, [x16, #:lo12:var_514]
+.L241:
+ adrp x16, struct_obj_3 + 4
+ ldrh w4, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w4, .L244
+ adrp x16, var_17
+ ldrsh w17, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w12, w12, #12288
+ sub w12, w12, #1187
+ lsl w13, w17, w12
+ cmp w13, #0
+ cset x7, ne
+ b .L245
+.L244:
+ movz w7, #0, lsl #0
+.L245:
+ movn w16, #76, lsl #0
+ eor w8, w4, w16
+ adrp x16, var_30
+ ldrh w17, [x16, #:lo12:var_30]
+ orr w9, wzr, w17, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w11, w9, w16
+ and w11, w8, w11
+ adrp x16, struct_obj_2
+ ldrsh w17, [x16, #:lo12:struct_obj_2]
+ sub w6, wzr, w17
+ sub w2, wzr, w6
+ adrp x16, var_1
+ ldrh w6, [x16, #:lo12:var_1]
+ sub w6, wzr, w6
+ madd w19, w2, w6, wzr
+ cmp w7, #4
+ cset x12, ne
+ cmp w19, w12
+ cset x2, gt
+ cbz w4, .L246
+ adrp x16, var_17
+ ldrsh w5, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w17, w12, #12288
+ sub w17, w17, #1187
+ lsl w5, w5, w17
+ cmp w5, #0
+ cset x2, ne
+ b .L247
+.L246:
+ movz w2, #0, lsl #0
+.L247:
+ orr w3, wzr, #1
+ movz w29, #0, lsl #0
+ sub w6, wzr, w4
+ movz w16, #4355, lsl #0
+ cmp w6, w16
+ cset x12, gt
+ sub w6, w12, #1
+ cmp w2, #4
+ cset x17, ne
+ cmp w19, w17
+ cset x5, gt
+ cmp w11, w5
+ cset x12, ge
+ movz w16, #7584, lsl #0
+ cmp w12, w16
+ cset x2, le
+ cmp w6, w2
+ csel x17, x3, x29, le
+ add w12, w4, #45056
+ add w12, w12, #778
+ cmp w12, #0
+ cset x6, ne
+ sdiv w2, w17, w6
+ msub w3, w2, w6, w17
+ sbfiz w13, w3, 0, 8
+ cbz w4, .L248
+ adrp x16, var_17
+ ldrsh w2, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w8, [x16, #:lo12:var_9]
+ sub w9, w8, #12288
+ sub w9, w9, #1187
+ lsl w5, w2, w9
+ cmp w5, #0
+ cset x7, ne
+ b .L249
+.L248:
+ movz w7, #0, lsl #0
+.L249:
+ cmp w7, #4
+ cset x9, ne
+ cmp w19, w9
+ cset x8, gt
+ cmp w11, w8
+ cset x2, ge
+ orn w3, wzr, w2
+ cmp w3, #0
+ cset x5, eq
+ adrp x16, var_64
+ strb w5, [x16, #:lo12:var_64]
+ orr w12, wzr, #1
+ orr w29, wzr, #1
+ adrp x16, struct_obj_4 + 12
+ ldrsb w11, [x16, #:lo12:struct_obj_4 + 12]
+ cmp w11, #0
+ csel x17, x12, x29, ne
+ orr w7, wzr, #1
+ orr w6, wzr, #1
+ adrp x16, var_43
+ ldrh w3, [x16, #:lo12:var_43]
+ cmp w3, #0
+ csel x7, x7, x6, ne
+ sdiv w8, w17, w7
+ msub w17, w8, w7, w17
+ adrp x16, var_52
+ ldrsh w2, [x16, #:lo12:var_52]
+ orr w12, w17, w2
+ orn w5, wzr, w12
+ adrp x16, var_61
+ ldrsb w8, [x16, #:lo12:var_61]
+ adrp x16, var_5
+ ldrh w11, [x16, #:lo12:var_5]
+ orr w2, w8, w11
+ adrp x16, struct_obj_8 + 22
+ ldrh w3, [x16, #:lo12:struct_obj_8 + 22]
+ orn w17, w2, w3
+ adrp x16, struct_obj_6 + 6
+ ldrsh w12, [x16, #:lo12:struct_obj_6 + 6]
+ adrp x16, struct_obj_1 + 4
+ ldrh w2, [x16, #:lo12:struct_obj_1 + 4]
+ adrp x16, struct_obj_6 + 2
+ ldrh w29, [x16, #:lo12:struct_obj_6 + 2]
+ and w11, w2, w29
+ eor w2, w12, w11
+ orr w2, w17, w2
+ sbfiz w3, w2, 0, 8
+ cmp w5, w3
+ b.gt .L250
+ adrp x16, struct_obj_3 + 4
+ ldrh w8, [x16, #:lo12:struct_obj_3 + 4]
+ cbnz w8, .L251
+ adrp x16, var_17
+ ldrsh w17, [x16, #:lo12:var_17]
+ sbfiz w12, w17, 0, 8
+ cbnz w12, .L251
+ adrp x16, var_38
+ ldrsb w4, [x16, #:lo12:var_38]
+ cbz w4, .L252
+ adrp x16, var_36
+ ldrsh w2, [x16, #:lo12:var_36]
+ cmp w2, #0
+ cset x17, ne
+ cbnz w17, .L251
+.L252:
+ adrp x16, var_3
+ ldrsb w2, [x16, #:lo12:var_3]
+.L251:
+ movn w16, #76, lsl #0
+ eor w17, w8, w16
+ adrp x16, var_30
+ ldrh w2, [x16, #:lo12:var_30]
+ orr w4, wzr, w2, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w12, w4, w16
+ and w12, w17, w12
+ adrp x16, struct_obj_2
+ ldrsh w17, [x16, #:lo12:struct_obj_2]
+ sub w11, wzr, w17
+ sub w3, wzr, w11
+ adrp x16, var_1
+ ldrh w5, [x16, #:lo12:var_1]
+ cbz w8, .L253
+ adrp x16, var_17
+ ldrsh w29, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w17, [x16, #:lo12:var_9]
+ sub w2, w17, #12288
+ sub w2, w2, #1187
+ lsl w17, w29, w2
+ cmp w17, #0
+ cset x11, ne
+ b .L254
+.L253:
+ movz w11, #0, lsl #0
+.L254:
+ sub w6, wzr, w5
+ madd w17, w3, w6, wzr
+ cmp w11, #4
+ cset x29, ne
+ cmp w17, w29
+ cset x7, gt
+.L250:
+ adrp x16, struct_obj_3 + 4
+ ldrh w29, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w29, .L255
+ adrp x16, var_17
+ ldrsh w5, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w9, [x16, #:lo12:var_9]
+ sub w17, w9, #12288
+ sub w17, w17, #1187
+ lsl w3, w5, w17
+ cmp w3, #0
+ cset x3, ne
+ b .L256
+.L255:
+ movz w3, #0, lsl #0
+.L256:
+ movn w16, #76, lsl #0
+ eor w6, w29, w16
+ adrp x16, var_30
+ ldrh w17, [x16, #:lo12:var_30]
+ orr w2, wzr, w17, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w12, w2, w16
+ and w4, w6, w12
+ adrp x16, struct_obj_2
+ ldrsh w17, [x16, #:lo12:struct_obj_2]
+ sub w2, wzr, w17
+ sub w7, wzr, w2
+ adrp x16, var_1
+ ldrh w17, [x16, #:lo12:var_1]
+ sub w17, wzr, w17
+ madd w5, w7, w17, wzr
+ cmp w3, #4
+ cset x3, ne
+ cmp w5, w3
+ cset x7, gt
+ cbz w29, .L257
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w17, [x16, #:lo12:var_9]
+ sub w8, w17, #12288
+ sub w8, w8, #1187
+ lsl w17, w7, w8
+ cmp w17, #0
+ cset x11, ne
+ b .L258
+.L257:
+ movz w11, #0, lsl #0
+.L258:
+ adrp x16, var_59
+ ldrh w17, [x16, #:lo12:var_59]
+ madd w2, w0, w17, wzr
+ sbfiz w17, w2, 0, 16
+ adrp x16, var_63
+ ldrsh w2, [x16, #:lo12:var_63]
+ madd w13, w2, w13, wzr
+ madd w9, w17, w13, wzr
+ sub w8, wzr, w9
+ movz w3, #11697, lsl #0
+ sub w17, wzr, w29
+ movz w16, #4355, lsl #0
+ cmp w17, w16
+ cset x7, gt
+ sub w9, w7, #1
+ cmp w11, #4
+ cset x2, ne
+ cmp w5, w2
+ cset x17, gt
+ cmp w4, w17
+ cset x7, ge
+ movz w16, #7584, lsl #0
+ cmp w7, w16
+ cset x7, le
+ cmp w9, w7
+ cset x13, le
+ madd w17, w13, w3, wzr
+ add w8, w8, w17
+ add w8, w8, #1110016
+ add w8, w8, #1199
+ cbnz w8, .L259
+ cbz w29, .L260
+ adrp x16, var_17
+ ldrsh w17, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w2, [x16, #:lo12:var_9]
+ sub w7, w2, #12288
+ sub w7, w7, #1187
+ lsl w11, w17, w7
+ cmp w11, #0
+ cset x2, ne
+ b .L261
+.L260:
+ movz w2, #0, lsl #0
+.L261:
+ cmp w2, #4
+ cset x8, ne
+ cmp w5, w8
+ cset x13, gt
+ cbz w29, .L262
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w2, [x16, #:lo12:var_9]
+ sub w8, w2, #12288
+ sub w8, w8, #1187
+ lsl w17, w7, w8
+ cmp w17, #0
+ cset x8, ne
+ b .L263
+.L262:
+ movz w8, #0, lsl #0
+.L263:
+ movz w13, #65414, lsl #0
+ movk w13, #32767, lsl #16
+ and w11, w6, w12
+ cmp w8, #4
+ cset x12, ne
+ cmp w5, w12
+ cset x7, gt
+ cmp w11, w7
+ cset x2, ge
+ movz w16, #7584, lsl #0
+ cmp w2, w16
+ cset x17, le
+ cmp w9, w17
+ cset x2, le
+ asr w6, w13, w2
+ movz w11, #64835, lsl #0
+ adrp x16, var_25
+ ldrsb w12, [x16, #:lo12:var_25]
+ orn w5, wzr, w12
+ add w6, w5, #149
+ asr w29, w11, w6
+ adrp x16, struct_obj_7 + 4
+ ldrsb w11, [x16, #:lo12:struct_obj_7 + 4]
+ adrp x16, struct_obj_4 + 4
+ ldrsh w2, [x16, #:lo12:struct_obj_4 + 4]
+ orr w9, w11, w2
+ add w2, w9, #128
+ asr w9, w29, w2
+ sub w4, wzr, w9
+ adrp x16, struct_obj_4 + 18
+ ldrsh w3, [x16, #:lo12:struct_obj_4 + 18]
+ orn w9, wzr, w3
+ movz w16, #17255, lsl #0
+ orr w11, w9, w16
+ adrp x16, struct_obj_8 + 4
+ ldrsb w7, [x16, #:lo12:struct_obj_8 + 4]
+ and w17, w11, w7
+ adrp x16, var_2
+ ldrh w29, [x16, #:lo12:var_2]
+ sbfiz w11, w29, 0, 8
+ sub w13, wzr, w11
+ orn w11, wzr, w13
+ cmp w17, w11
+ cset x29, ne
+ sdiv w17, w4, w29
+ adrp x16, var_543
+ strb w17, [x16, #:lo12:var_543]
+ adrp x16, var_42
+ ldrsb w17, [x16, #:lo12:var_42]
+ madd w13, w17, w3, wzr
+ movz w8, #63174, lsl #0
+ movk w8, #19, lsl #16
+ adrp x16, var_53
+ ldrsh w3, [x16, #:lo12:var_53]
+ sub w9, w8, w3
+ sub w11, w9, #6
+ sbfiz w2, w11, 0, 16
+ add w8, w13, w2
+ sub w9, w8, #117
+ movz w5, #19559, lsl #0
+ adrp x16, var_13
+ ldrsh w13, [x16, #:lo12:var_13]
+ madd w2, w13, w5, wzr
+ adrp x16, var_46
+ ldrh w5, [x16, #:lo12:var_46]
+ madd w17, w14, w5, wzr
+ madd w2, w2, w17, wzr
+ sub w5, wzr, w2
+ movz w14, #65517, lsl #0
+ movz w6, #20823, lsl #0
+ adrp x16, var_4
+ ldrh w3, [x16, #:lo12:var_4]
+ madd w13, w3, w6, wzr
+ sdiv w6, w14, w13
+ movz w29, #45116, lsl #0
+ movk w29, #14440, lsl #16
+ adrp x16, var_24
+ ldrsh w4, [x16, #:lo12:var_24]
+ sbfiz w11, w4, 0, 8
+ sdiv w2, w29, w11
+ madd w6, w6, w2, wzr
+ madd w2, w5, w6, wzr
+ cmp w9, w2
+ cset x7, gt
+ adrp x16, var_544
+ strh w7, [x16, #:lo12:var_544]
+ adrp x16, var_547
+ strb w12, [x16, #:lo12:var_547]
+ adrp x16, struct_obj_3 + 4
+ ldrh w3, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w3, .L264
+ adrp x16, var_17
+ ldrsh w6, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w13, [x16, #:lo12:var_9]
+ sub w4, w13, #12288
+ sub w4, w4, #1187
+ lsl w6, w6, w4
+ cmp w6, #0
+ cset x14, ne
+ b .L265
+.L264:
+ movz w14, #0, lsl #0
+.L265:
+ movn w16, #76, lsl #0
+ eor w17, w3, w16
+ adrp x16, var_30
+ ldrh w6, [x16, #:lo12:var_30]
+ orr w12, wzr, w6, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w4, w12, w16
+ and w13, w17, w4
+ adrp x16, struct_obj_2
+ ldrsh w2, [x16, #:lo12:struct_obj_2]
+ sub w11, wzr, w2
+ sub w17, wzr, w11
+ adrp x16, var_1
+ ldrh w29, [x16, #:lo12:var_1]
+ sub w4, wzr, w29
+ madd w17, w17, w4, wzr
+ cmp w14, #4
+ cset x12, ne
+ cmp w17, w12
+ cset x11, gt
+ cbz w3, .L266
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w2, w12, #12288
+ sub w2, w2, #1187
+ lsl w2, w9, w2
+ cmp w2, #0
+ cset x14, ne
+ b .L267
+.L266:
+ movz w14, #0, lsl #0
+.L267:
+ adrp x16, var_41
+ ldrh w6, [x16, #:lo12:var_41]
+ adrp x16, var_16
+ ldrh w2, [x16, #:lo12:var_16]
+ adrp x16, struct_obj_7
+ ldrsb w29, [x16, #:lo12:struct_obj_7]
+ add w4, w29, #102
+ asr w4, w2, w4
+ adrp x16, struct_obj_4 + 24
+ ldrh w8, [x16, #:lo12:struct_obj_4 + 24]
+ orn w9, w4, w8
+ orr w16, wzr, #2147483647
+ add w12, w9, w16
+ adrp x16, struct_obj_8 + 8
+ ldrsb w9, [x16, #:lo12:struct_obj_8 + 8]
+ sub w11, wzr, w3
+ movz w16, #4355, lsl #0
+ cmp w11, w16
+ cset x29, gt
+ sub w29, w29, #1
+ cmp w14, #4
+ cset x11, ne
+ cmp w17, w11
+ cset x17, gt
+ cmp w13, w17
+ cset x14, ge
+ movz w16, #7584, lsl #0
+ cmp w14, w16
+ cset x2, le
+ cmp w29, w2
+ cset x8, le
+ eor w3, w9, w8
+ add w9, w3, #75
+ lsl w8, w12, w9
+ movz w16, #9477, lsl #0
+ movk w16, #32767, lsl #16
+ sub w5, w8, w16
+ lsl w29, w6, w5
+ orn w11, wzr, w29
+ adrp x16, var_59
+ strh w11, [x16, #:lo12:var_59]
+ b .L268
+.L259:
+ movz w17, #23716, lsl #0
+ adrp x16, var_38
+ ldrsb w3, [x16, #:lo12:var_38]
+ sub w8, w3, #38
+ lsl w12, w17, w8
+ adrp x16, struct_obj_9 + 8
+ ldrsh w4, [x16, #:lo12:struct_obj_9 + 8]
+ asr w2, w4, w15
+ orr w2, wzr, w2, lsl #16
+ adrp x16, struct_obj_2 + 2
+ ldrh w12, [x16, #:lo12:struct_obj_2 + 2]
+ adrp x16, var_27
+ ldrsh w9, [x16, #:lo12:var_27]
+ cbnz w9, .L269
+ adrp x16, var_24
+ ldrsh w7, [x16, #:lo12:var_24]
+ cmp w7, #0
+ cset x4, ne
+ b .L270
+.L269:
+ orr w4, wzr, #1
+.L270:
+ cbz w4, .L271
+ adrp x16, var_17
+ ldrsh w4, [x16, #:lo12:var_17]
+.L271:
+ adrp x16, var_10
+ ldrh w13, [x16, #:lo12:var_10]
+ adrp x16, var_62
+ strh w13, [x16, #:lo12:var_62]
+ adrp x16, var_26
+ ldrh w17, [x16, #:lo12:var_26]
+.L268:
+ adrp x16, var_54
+ ldrsh w14, [x16, #:lo12:var_54]
+ cbz w14, .L272
+ adrp x16, var_11
+ ldrsh w29, [x16, #:lo12:var_11]
+ cmp w29, #0
+ cset x13, ne
+ cbz w13, .L272
+ adrp x16, var_18
+ ldrsb w8, [x16, #:lo12:var_18]
+ cbnz w8, .L273
+ adrp x16, var_7
+ ldrsb w2, [x16, #:lo12:var_7]
+ cmp w2, #0
+ cset x4, ne
+ cbz w4, .L272
+.L273:
+ adrp x16, var_16
+ ldrh w17, [x16, #:lo12:var_16]
+.L272:
+ adrp x16, struct_obj_3 + 4
+ ldrh w11, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w11, .L274
+ adrp x16, var_17
+ ldrsh w17, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w12, w12, #12288
+ sub w12, w12, #1187
+ lsl w29, w17, w12
+ cmp w29, #0
+ cset x8, ne
+ b .L275
+.L274:
+ movz w8, #0, lsl #0
+.L275:
+ movn w16, #76, lsl #0
+ eor w2, w11, w16
+ adrp x16, var_30
+ ldrh w12, [x16, #:lo12:var_30]
+ orr w12, wzr, w12, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w9, w12, w16
+ and w13, w2, w9
+ adrp x16, struct_obj_2
+ ldrsh w6, [x16, #:lo12:struct_obj_2]
+ sub w29, wzr, w6
+ sub w17, wzr, w29
+ adrp x16, var_1
+ ldrh w12, [x16, #:lo12:var_1]
+ sub w29, wzr, w12
+ madd w3, w17, w29, wzr
+ cmp w8, #4
+ cset x2, ne
+ cmp w3, w2
+ cset x9, gt
+ cbz w11, .L276
+ adrp x16, var_17
+ ldrsh w2, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w14, [x16, #:lo12:var_9]
+ sub w17, w14, #12288
+ sub w17, w17, #1187
+ lsl w2, w2, w17
+ cmp w2, #0
+ cset x9, ne
+ b .L277
+.L276:
+ movz w9, #0, lsl #0
+.L277:
+ cmp w9, #4
+ cset x7, ne
+ cmp w3, w7
+ cset x2, gt
+ cmp w13, w2
+ cset x3, ge
+ orn w14, wzr, w3
+ adrp x16, var_549
+ strb w14, [x16, #:lo12:var_549]
+.L231:
+ adrp x16, struct_obj_4 + 22
+ ldrh w2, [x16, #:lo12:struct_obj_4 + 22]
+ cbz w2, .L278
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_30
+ ldrh w8, [x16, #:lo12:var_30]
+ adrp x16, struct_obj_6 + 6
+ ldrsh w13, [x16, #:lo12:struct_obj_6 + 6]
+ adrp x16, struct_obj_3 + 4
+ ldrh w5, [x16, #:lo12:struct_obj_3 + 4]
+ adrp x16, var_40
+ ldrsb w11, [x16, #:lo12:var_40]
+ cbnz w11, .L279
+ cbnz w10, .L280
+ orr w2, wzr, #1
+ b .L281
+.L280:
+ orr w2, wzr, #1
+ b .L281
+.L279:
+ movz w2, #0, lsl #0
+.L281:
+ adrp x16, var_47
+ ldrsb w6, [x16, #:lo12:var_47]
+ cbz w6, .L282
+ cmp w5, #0
+ cset x4, ne
+ cbz w4, .L282
+ orr w12, wzr, #1
+ b .L283
+.L282:
+ orr w7, wzr, #1
+ orr w12, wzr, #1
+ adrp x16, var_48
+ ldrh w11, [x16, #:lo12:var_48]
+ cmp w11, #0
+ csel x17, x7, x12, ne
+ cbz w17, .L284
+ cmp w10, #0
+ cset x12, eq
+ b .L283
+.L284:
+ movz w12, #0, lsl #0
+.L283:
+ adrp x16, var_18
+ ldrsb w11, [x16, #:lo12:var_18]
+ orr w3, wzr, w11, lsr #31
+ sxtw x29, w11
+ movz x17, #30841, lsl #0
+ movk x17, #30840, lsl #16
+ madd x29, x29, x17, xzr
+ orr x10, xzr, x29, asr #32
+ add w14, w3, w10, asr #3
+ add w14, w14, w14, lsl #4
+ sub w6, w11, w14
+ sub w14, w2, w12
+ cmp w6, w14
+ b.le .L285
+ cbz w5, .L286
+ adrp x16, var_9
+ ldrh w29, [x16, #:lo12:var_9]
+ sub w3, w29, #12288
+ sub w3, w3, #1187
+ lsl w2, w9, w3
+ cmp w2, #0
+ cset x2, ne
+ b .L287
+.L286:
+ movz w2, #0, lsl #0
+.L287:
+ cbz w5, .L288
+ adrp x16, var_9
+ ldrh w3, [x16, #:lo12:var_9]
+ sub w3, w3, #12288
+ sub w3, w3, #1187
+ lsl w3, w9, w3
+ cmp w3, #0
+ cset x10, ne
+ b .L289
+.L288:
+ movz w10, #0, lsl #0
+.L289:
+ adrp x16, var_24
+ ldrsh w9, [x16, #:lo12:var_24]
+ adrp x16, var_41
+ ldrh w14, [x16, #:lo12:var_41]
+ madd w4, w9, w14, wzr
+ movn w16, #76, lsl #0
+ eor w7, w5, w16
+ orr w17, wzr, w8, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w13, w17, w16
+ and w29, w7, w13
+ adrp x16, struct_obj_2
+ ldrsh w14, [x16, #:lo12:struct_obj_2]
+ sub w9, wzr, w14
+ sub w17, wzr, w9
+ adrp x16, var_1
+ ldrh w6, [x16, #:lo12:var_1]
+ sub w6, wzr, w6
+ madd w7, w17, w6, wzr
+ cmp w2, #4
+ cset x3, ne
+ cmp w7, w3
+ cset x6, gt
+ cmp w29, w6
+ cset x13, ge
+ orn w12, wzr, w13
+ madd w6, w4, w12, wzr
+ cmp w10, #4
+ cset x13, ne
+ cmp w7, w13
+ cset x2, gt
+ cmp w29, w2
+ cset x7, ge
+ adrp x16, var_21
+ ldrsb w2, [x16, #:lo12:var_21]
+ cmp w2, #0
+ cset x8, eq
+ orn w4, wzr, w8
+ orr w3, w4, #-2
+ and w7, w7, w3
+ and w8, w6, w7
+ adrp x16, var_48
+ strh w8, [x16, #:lo12:var_48]
+ cbz w5, .L290
+ adrp x16, var_17
+ ldrsh w4, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w2, [x16, #:lo12:var_9]
+ sub w17, w2, #12288
+ sub w17, w17, #1187
+ lsl w6, w4, w17
+ cmp w6, #0
+ cset x13, ne
+ b .L291
+.L290:
+ movz w13, #0, lsl #0
+.L291:
+ adrp x16, struct_obj_3 + 4
+ ldrh w17, [x16, #:lo12:struct_obj_3 + 4]
+ movn w16, #76, lsl #0
+ eor w3, w17, w16
+ adrp x16, var_30
+ ldrh w2, [x16, #:lo12:var_30]
+ orr w4, wzr, w2, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w7, w4, w16
+ and w4, w3, w7
+ adrp x16, struct_obj_2
+ ldrsh w29, [x16, #:lo12:struct_obj_2]
+ sub w2, wzr, w29
+ sub w3, wzr, w2
+ adrp x16, var_1
+ ldrh w2, [x16, #:lo12:var_1]
+ sub w10, wzr, w2
+ madd w14, w3, w10, wzr
+ cmp w13, #4
+ cset x13, ne
+ cmp w14, w13
+ cset x29, gt
+ adrp x16, var_26
+ ldrh w7, [x16, #:lo12:var_26]
+ cbnz w7, .L292
+.L292:
+ cbz w17, .L293
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w29, w12, #12288
+ sub w29, w29, #1187
+ lsl w10, w9, w29
+ cmp w10, #0
+ cset x3, ne
+ b .L294
+.L293:
+ movz w3, #0, lsl #0
+.L294:
+ cmp w3, #4
+ cset x9, ne
+ cmp w14, w9
+ cset x7, gt
+ adrp x16, struct_obj_4 + 14
+ ldrsh w17, [x16, #:lo12:struct_obj_4 + 14]
+ cbz w17, .L295
+ adrp x16, struct_obj_6 + 4
+ ldrh w2, [x16, #:lo12:struct_obj_6 + 4]
+ cmp w2, #0
+ cset x17, ne
+ cbz w17, .L295
+ orr w2, wzr, #1
+ b .L296
+.L295:
+ adrp x16, var_60
+ ldrsh w2, [x16, #:lo12:var_60]
+ cbnz w2, .L297
+ adrp x16, struct_obj_4 + 16
+ ldrsb w13, [x16, #:lo12:struct_obj_4 + 16]
+ cmp w13, #0
+ cset x2, ne
+ b .L296
+.L297:
+ orr w2, wzr, #1
+.L296:
+ orr w3, wzr, #1
+ orr w7, wzr, #1
+ cmp w2, #0
+ csel x3, x3, x7, ne
+ cbz w3, .L285
+ adrp x16, var_65
+ ldrsh w14, [x16, #:lo12:var_65]
+ cbz w14, .L298
+ adrp x16, struct_obj_9 + 20
+ ldrsh w5, [x16, #:lo12:struct_obj_9 + 20]
+ cmp w5, #0
+ cset x9, ne
+ cbz w9, .L298
+ adrp x16, var_3
+ ldrsb w17, [x16, #:lo12:var_3]
+ cbz w17, .L299
+ adrp x16, var_51
+ ldrsh w7, [x16, #:lo12:var_51]
+ cmp w7, #0
+ cset x14, ne
+ b .L300
+.L299:
+ movz w14, #0, lsl #0
+ b .L300
+.L298:
+ movz w14, #0, lsl #0
+.L300:
+ eor w2, w14, #1
+ cbz w2, .L285
+ adrp x16, var_50
+ ldrh w9, [x16, #:lo12:var_50]
+ cbz w9, .L301
+ adrp x16, struct_obj_7
+ ldrsb w14, [x16, #:lo12:struct_obj_7]
+ cmp w14, #0
+ cset x5, ne
+ b .L302
+.L301:
+ movz w5, #0, lsl #0
+.L302:
+ cbnz w5, .L285
+ orr w2, wzr, #1
+ movz w11, #0, lsl #0
+ adrp x16, var_45
+ ldrsb w5, [x16, #:lo12:var_45]
+ cmp w5, #0
+ csel x2, x2, x11, ne
+ cbnz w2, .L285
+ adrp x16, var_19
+ ldrsb w4, [x16, #:lo12:var_19]
+.L285:
+ adrp x16, struct_obj_3 + 4
+ ldrh w11, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w11, .L303
+ adrp x16, var_17
+ ldrsh w29, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w5, w12, #12288
+ sub w5, w5, #1187
+ lsl w12, w29, w5
+ cmp w12, #0
+ cset x5, ne
+ b .L304
+.L303:
+ movz w5, #0, lsl #0
+.L304:
+ adrp x16, var_24
+ ldrsh w12, [x16, #:lo12:var_24]
+ adrp x16, struct_obj_9 + 2
+ ldrsb w29, [x16, #:lo12:struct_obj_9 + 2]
+ add w13, w12, w29
+ adrp x16, struct_obj_2
+ ldrsh w4, [x16, #:lo12:struct_obj_2]
+ sub w2, w4, #61440
+ sub w2, w2, #4094
+ add w3, w13, w2
+ movz w14, #125, lsl #0
+ adrp x16, var_40
+ ldrsb w12, [x16, #:lo12:var_40]
+ sub w17, w14, w12
+ sub w10, wzr, w17
+ sub w13, w3, w10
+ adrp x16, struct_obj_8
+ ldrh w12, [x16, #:lo12:struct_obj_8]
+ adrp x16, var_6
+ ldrh w8, [x16, #:lo12:var_6]
+ sub w10, w12, w8
+ sub w9, wzr, w10
+ movn w16, #76, lsl #0
+ eor w17, w11, w16
+ adrp x16, var_30
+ ldrh w14, [x16, #:lo12:var_30]
+ orr w14, wzr, w14, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w2, w14, w16
+ and w17, w17, w2
+ sub w11, wzr, w4
+ sub w3, wzr, w11
+ adrp x16, var_1
+ ldrh w29, [x16, #:lo12:var_1]
+ sub w4, wzr, w29
+ madd w10, w3, w4, wzr
+ cmp w5, #4
+ cset x11, ne
+ cmp w10, w11
+ cset x6, gt
+ cmp w17, w6
+ cset x11, ge
+ madd w2, w9, w11, wzr
+ madd w17, w13, w2, wzr
+ orn w11, wzr, w17
+ adrp x16, var_52
+ strh w11, [x16, #:lo12:var_52]
+ adrp x16, var_57
+ ldrsb w8, [x16, #:lo12:var_57]
+ cbnz w8, .L305
+ adrp x16, var_39
+ ldrh w11, [x16, #:lo12:var_39]
+ cmp w11, #0
+ cset x14, eq
+ b .L306
+.L305:
+ movz w14, #0, lsl #0
+.L306:
+ adrp x16, var_29
+ ldrh w2, [x16, #:lo12:var_29]
+ sub w7, wzr, w14
+ asr w14, w2, w7
+ orr w11, wzr, #1
+ orr w0, w15, w0
+ movn w16, #8063, lsl #0
+ cmp w0, w16
+ cset x5, lt
+ orn w12, wzr, w5
+ sub w17, w11, w12
+ sdiv w6, w14, w17
+ msub w4, w6, w17, w14
+ cbz w4, .L307
+ adrp x16, struct_obj_3 + 4
+ ldrh w9, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w9, .L308
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w3, [x16, #:lo12:var_9]
+ sub w4, w3, #12288
+ sub w4, w4, #1187
+ lsl w11, w7, w4
+ cmp w11, #0
+ cset x10, ne
+ b .L309
+.L308:
+ movz w10, #0, lsl #0
+.L309:
+ movn w16, #76, lsl #0
+ eor w15, w9, w16
+ adrp x16, var_30
+ ldrh w7, [x16, #:lo12:var_30]
+ orr w2, wzr, w7, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w5, w2, w16
+ and w3, w15, w5
+ adrp x16, struct_obj_2
+ ldrsh w8, [x16, #:lo12:struct_obj_2]
+ sub w5, wzr, w8
+ sub w17, wzr, w5
+ adrp x16, var_1
+ ldrh w15, [x16, #:lo12:var_1]
+ sub w5, wzr, w15
+ madd w7, w17, w5, wzr
+ cmp w10, #4
+ cset x10, ne
+ cmp w7, w10
+ cset x7, gt
+ cmp w3, w7
+ cset x12, ge
+ adrp x16, struct_obj_4 + 22
+ ldrh w8, [x16, #:lo12:struct_obj_4 + 22]
+ sbfiz w2, w8, 0, 8
+ and w2, w12, w2
+ adrp x16, var_8
+ ldrh w9, [x16, #:lo12:var_8]
+ movz w0, #16848, lsl #0
+ movk w0, #61777, lsl #16
+ sdiv w12, w9, w0
+ sbfiz w0, w12, 0, 16
+ asr w11, w2, w0
+ adrp x16, struct_obj_5
+ ldrsb w13, [x16, #:lo12:struct_obj_5]
+ movn w7, #99, lsl #0
+ adrp x16, var_19
+ ldrsb w2, [x16, #:lo12:var_19]
+ madd w4, w2, w7, wzr
+ sub w7, wzr, w4
+ sbfiz w17, w7, 0, 16
+ cmp w13, w17
+ cset x3, le
+ asr w9, w11, w3
+ ubfiz w8, w9, 0, 16
+ adrp x16, var_31
+ ldrsh w7, [x16, #:lo12:var_31]
+ sub w2, w7, w8
+ orn w4, wzr, w2
+ movn w14, #19434, lsl #0
+ adrp x16, struct_obj_9 + 2
+ ldrsb w2, [x16, #:lo12:struct_obj_9 + 2]
+ sdiv w3, w14, w2
+ msub w0, w3, w2, w14
+ sbfiz w11, w0, 0, 8
+ add w29, w11, #55
+ asr w3, w4, w29
+ orn w0, wzr, w3
+ cmp w0, #0
+ cset x9, eq
+ adrp x16, var_558
+ strh w9, [x16, #:lo12:var_558]
+ adrp x16, struct_obj_6 + 4
+ ldrh w2, [x16, #:lo12:struct_obj_6 + 4]
+ cbz w2, .L310
+ adrp x16, struct_obj_4 + 2
+ ldrsb w10, [x16, #:lo12:struct_obj_4 + 2]
+ cmp w10, #0
+ cset x11, ne
+ b .L311
+.L310:
+ movz w11, #0, lsl #0
+.L311:
+ orn w6, wzr, w11
+ sdiv w9, w1, w6
+ msub w10, w9, w6, w1
+ cbz w10, .L312
+ orr w29, wzr, #1
+ movz w10, #0, lsl #0
+ movz w5, #0, lsl #0
+ cmp w29, #0
+ csel x11, x10, x5, ne
+ eor w15, w11, #1
+ b .L313
+.L312:
+ movz w15, #0, lsl #0
+.L313:
+ adrp x16, struct_obj_1 + 6
+ ldrsh w9, [x16, #:lo12:struct_obj_1 + 6]
+ cmp w15, w9
+ cset x29, eq
+ adrp x16, var_64
+ strb w29, [x16, #:lo12:var_64]
+ adrp x16, struct_obj_3 + 4
+ ldrh w17, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w17, .L314
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w14, [x16, #:lo12:var_9]
+ sub w0, w14, #12288
+ sub w0, w0, #1187
+ lsl w15, w9, w0
+ cmp w15, #0
+ cset x29, ne
+ b .L315
+.L314:
+ movz w29, #0, lsl #0
+.L315:
+ movn w16, #76, lsl #0
+ eor w3, w17, w16
+ adrp x16, var_30
+ ldrh w8, [x16, #:lo12:var_30]
+ orr w5, wzr, w8, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w8, w5, w16
+ and w12, w3, w8
+ adrp x16, struct_obj_2
+ ldrsh w11, [x16, #:lo12:struct_obj_2]
+ sub w10, wzr, w11
+ sub w13, wzr, w10
+ adrp x16, var_1
+ ldrh w15, [x16, #:lo12:var_1]
+ sub w14, wzr, w15
+ madd w7, w13, w14, wzr
+ cmp w29, #4
+ cset x13, ne
+ cmp w7, w13
+ cset x5, gt
+ cbz w17, .L316
+ adrp x16, var_17
+ ldrsh w5, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w4, [x16, #:lo12:var_9]
+ sub w10, w4, #12288
+ sub w10, w10, #1187
+ lsl w8, w5, w10
+ cmp w8, #0
+ cset x8, ne
+ b .L317
+.L316:
+ movz w8, #0, lsl #0
+.L317:
+ cmp w8, #4
+ cset x2, ne
+ cmp w7, w2
+ cset x8, gt
+ orn w13, wzr, w17
+ adrp x16, struct_obj_5 + 2
+ ldrsh w14, [x16, #:lo12:struct_obj_5 + 2]
+.L307:
+ adrp x16, struct_obj_3 + 4
+ ldrh w15, [x16, #:lo12:struct_obj_3 + 4]
+ adrp x16, var_1
+ ldrh w11, [x16, #:lo12:var_1]
+ movn w16, #23820, lsl #0
+ eor w0, w11, w16
+ orn w8, wzr, w0
+ cbnz w8, .L318
+ cbz w15, .L319
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w6, [x16, #:lo12:var_9]
+ sub w12, w6, #12288
+ sub w12, w12, #1187
+ lsl w10, w7, w12
+ cmp w10, #0
+ cset x17, ne
+ b .L320
+.L319:
+ movz w17, #0, lsl #0
+.L320:
+ movn w16, #76, lsl #0
+ eor w8, w15, w16
+ adrp x16, var_30
+ ldrh w29, [x16, #:lo12:var_30]
+ orr w9, wzr, w29, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w5, w9, w16
+ and w9, w8, w5
+ adrp x16, struct_obj_2
+ ldrsh w7, [x16, #:lo12:struct_obj_2]
+ sub w29, wzr, w7
+ sub w7, wzr, w29
+ sub w8, wzr, w11
+ madd w12, w7, w8, wzr
+ cmp w17, #4
+ cset x17, ne
+ cmp w12, w17
+ cset x8, gt
+ movz w13, #55, lsl #0
+ adrp x16, var_51
+ strh w13, [x16, #:lo12:var_51]
+ cbz w15, .L321
+ adrp x16, var_17
+ ldrsh w4, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w15, [x16, #:lo12:var_9]
+ sub w9, w15, #12288
+ sub w9, w9, #1187
+ lsl w17, w4, w9
+ cmp w17, #0
+ cset x12, ne
+ b .L322
+.L321:
+ movz w12, #0, lsl #0
+.L322:
+ adrp x16, struct_obj_3 + 4
+ ldrh w13, [x16, #:lo12:struct_obj_3 + 4]
+ movn w16, #76, lsl #0
+ eor w2, w13, w16
+ adrp x16, var_30
+ ldrh w5, [x16, #:lo12:var_30]
+ orr w3, wzr, w5, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w0, w3, w16
+ and w17, w2, w0
+ adrp x16, struct_obj_2
+ ldrsh w9, [x16, #:lo12:struct_obj_2]
+ sub w15, wzr, w9
+ sub w11, wzr, w15
+ adrp x16, var_1
+ ldrh w8, [x16, #:lo12:var_1]
+ sub w0, wzr, w8
+ madd w3, w11, w0, wzr
+ cmp w12, #4
+ cset x10, ne
+ cmp w3, w10
+ cset x0, gt
+ cbz w13, .L323
+ adrp x16, var_17
+ ldrsh w14, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w0, [x16, #:lo12:var_9]
+ sub w8, w0, #12288
+ sub w8, w8, #1187
+ lsl w2, w14, w8
+ cmp w2, #0
+ cset x11, ne
+ b .L324
+.L323:
+ movz w11, #0, lsl #0
+.L324:
+ cmp w11, #4
+ cset x29, ne
+ cmp w3, w29
+ cset x5, gt
+ b .L278
+.L318:
+ cbz w15, .L325
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w8, [x16, #:lo12:var_9]
+ sub w10, w8, #12288
+ sub w10, w10, #1187
+ lsl w4, w9, w10
+ cmp w4, #0
+ cset x3, ne
+ b .L326
+.L325:
+ movz w3, #0, lsl #0
+.L326:
+ movn w16, #76, lsl #0
+ eor w14, w15, w16
+ adrp x16, var_30
+ ldrh w2, [x16, #:lo12:var_30]
+ orr w10, wzr, w2, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w17, w10, w16
+ and w7, w14, w17
+ adrp x16, struct_obj_2
+ ldrsh w6, [x16, #:lo12:struct_obj_2]
+ sub w12, wzr, w6
+ sub w12, wzr, w12
+ sub w4, wzr, w11
+ madd w2, w12, w4, wzr
+ cmp w3, #4
+ cset x12, ne
+ cmp w2, w12
+ cset x13, gt
+ cbz w15, .L327
+ adrp x16, var_17
+ ldrsh w10, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w6, [x16, #:lo12:var_9]
+ sub w17, w6, #12288
+ sub w17, w17, #1187
+ lsl w8, w10, w17
+ cmp w8, #0
+ cset x6, ne
+ b .L328
+.L327:
+ movz w6, #0, lsl #0
+.L328:
+ movn w3, #54, lsl #0
+ adrp x16, var_41
+ ldrh w4, [x16, #:lo12:var_41]
+ madd w0, w4, w3, wzr
+ sbfiz w0, w0, 0, 16
+ sub w3, wzr, w15
+ movz w16, #4355, lsl #0
+ cmp w3, w16
+ cset x10, gt
+ sub w4, w10, #1
+ cmp w6, #4
+ cset x5, ne
+ cmp w2, w5
+ cset x2, gt
+ cmp w7, w2
+ cset x10, ge
+ movz w16, #7584, lsl #0
+ cmp w10, w16
+ cset x5, le
+ cmp w4, w5
+ cset x14, le
+ sub w4, wzr, w14
+ cmp w4, #0
+ cset x11, eq
+ madd w10, w0, w11, wzr
+ adrp x16, struct_obj_8 + 28
+ ldrsh w12, [x16, #:lo12:struct_obj_8 + 28]
+ orn w4, wzr, w12
+ adrp x16, struct_obj_5 + 2
+ ldrsh w12, [x16, #:lo12:struct_obj_5 + 2]
+ orn w0, w4, w12
+ orr w10, wzr, #1
+ adrp x16, var_2
+ ldrh w17, [x16, #:lo12:var_2]
+ adrp x16, var_34
+ ldrsb w11, [x16, #:lo12:var_34]
+ sdiv w17, w17, w11
+ orn w13, wzr, w17
+ sub w11, w13, #233
+ lsl w10, w10, w11
+ movn w16, #49, lsl #0
+ orr w10, w10, w16
+ orr w17, w0, w10
+ adrp x16, struct_obj_8 + 8
+ ldrsb w2, [x16, #:lo12:struct_obj_8 + 8]
+ bic w2, w17, w2
+ cbz w2, .L278
+.L278:
+ adrp x16, var_62
+ ldrh w17, [x16, #:lo12:var_62]
+ adrp x16, var_8
+ ldrh w9, [x16, #:lo12:var_8]
+ cmp w9, #0
+ cset x12, le
+ and w9, w17, w12
+ cbz w9, .L329
+ adrp x16, struct_obj_1
+ ldrsh w4, [x16, #:lo12:struct_obj_1]
+ adrp x16, struct_obj_3 + 4
+ ldrh w8, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w8, .L330
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w12, [x16, #:lo12:var_9]
+ sub w7, w12, #12288
+ sub w7, w7, #1187
+ lsl w6, w9, w7
+ cmp w6, #0
+ cset x10, ne
+ b .L331
+.L330:
+ movz w10, #0, lsl #0
+.L331:
+ adrp x16, var_27
+ ldrsh w6, [x16, #:lo12:var_27]
+ cmp w6, #0
+ cset x2, eq
+ adrp x16, var_10
+ ldrh w6, [x16, #:lo12:var_10]
+ adrp x16, var_60
+ ldrsh w29, [x16, #:lo12:var_60]
+ cmp w6, w29
+ cset x5, le
+ sub w17, w2, w5
+ cbz w17, .L332
+ movn w17, #19779, lsl #0
+ orr w7, wzr, #-128
+ adrp x16, var_40
+ ldrsb w9, [x16, #:lo12:var_40]
+ madd w14, w9, w7, wzr
+ madd w29, w14, w17, wzr
+ cmp w29, #0
+ cset x2, ne
+ b .L333
+.L332:
+ movz w2, #0, lsl #0
+.L333:
+ movn w16, #76, lsl #0
+ eor w9, w8, w16
+ adrp x16, var_30
+ ldrh w12, [x16, #:lo12:var_30]
+ orr w5, wzr, w12, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w14, w5, w16
+ and w0, w9, w14
+ adrp x16, struct_obj_2
+ ldrsh w3, [x16, #:lo12:struct_obj_2]
+ sub w11, wzr, w3
+ sub w11, wzr, w11
+ adrp x16, var_1
+ ldrh w5, [x16, #:lo12:var_1]
+ sub w15, wzr, w5
+ madd w11, w11, w15, wzr
+ cmp w10, #4
+ cset x13, ne
+ cmp w11, w13
+ cset x4, gt
+ cmp w0, w4
+ cset x15, ge
+ adrp x16, struct_obj_9 + 8
+ ldrsh w3, [x16, #:lo12:struct_obj_9 + 8]
+ add w12, w15, w3
+ add w3, w12, #57344
+ add w3, w3, #1750
+ sbfiz w17, w3, 0, 8
+ cmp w17, w2
+ cset x15, gt
+ adrp x16, var_43
+ ldrh w17, [x16, #:lo12:var_43]
+ adrp x16, struct_obj_5 + 6
+ ldrsh w7, [x16, #:lo12:struct_obj_5 + 6]
+ add w12, w17, w7
+ movz w16, #26468, lsl #0
+ cmp w12, w16
+ cset x10, lt
+ sub w2, wzr, w10
+ cmp w2, #43
+ cset x29, gt
+ and w15, w15, w29
+ adrp x16, var_53
+ ldrsh w12, [x16, #:lo12:var_53]
+ cbnz w12, .L334
+ adrp x16, var_61
+ ldrsb w13, [x16, #:lo12:var_61]
+ ubfiz w13, w13, 0, 16
+ cmp w13, #0
+ cset x13, ne
+ cbnz w13, .L334
+ orr w2, wzr, #1
+ cbnz w2, .L334
+ cbnz w6, .L334
+ adrp x16, var_44
+ ldrh w10, [x16, #:lo12:var_44]
+ cmp w10, #0
+ cset x4, ne
+.L334:
+ adrp x16, struct_obj_4 + 10
+ ldrh w7, [x16, #:lo12:struct_obj_4 + 10]
+ cbz w8, .L335
+ adrp x16, var_17
+ ldrsh w12, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w6, [x16, #:lo12:var_9]
+ sub w6, w6, #12288
+ sub w6, w6, #1187
+ lsl w13, w12, w6
+ cmp w13, #0
+ cset x10, ne
+ b .L336
+.L335:
+ movz w10, #0, lsl #0
+.L336:
+ cmp w10, #4
+ cset x4, ne
+ cmp w11, w4
+ cset x17, gt
+ cbz w8, .L337
+ adrp x16, var_17
+ ldrsh w12, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w3, [x16, #:lo12:var_9]
+ sub w0, w3, #12288
+ sub w0, w0, #1187
+ lsl w10, w12, w0
+ cmp w10, #0
+ cset x12, ne
+ b .L338
+.L337:
+ movz w12, #0, lsl #0
+.L338:
+ adrp x16, struct_obj_4 + 16
+ ldrsb w2, [x16, #:lo12:struct_obj_4 + 16]
+ movn w16, #27631, lsl #0
+ and w29, w2, w16
+ sub w17, wzr, w8
+ movz w16, #4355, lsl #0
+ cmp w17, w16
+ cset x5, gt
+ sub w10, w5, #1
+ and w13, w9, w14
+ cmp w12, #4
+ cset x14, ne
+ cmp w11, w14
+ cset x9, gt
+ cmp w13, w9
+ cset x5, ge
+ movz w16, #7584, lsl #0
+ cmp w5, w16
+ cset x8, le
+ cmp w10, w8
+ cset x6, le
+ eor w5, w29, w6
+ sub w29, wzr, w5
+ sub w9, wzr, w29
+ adrp x16, struct_obj_10 + 4
+ strb w9, [x16, #:lo12:struct_obj_10 + 4]
+ orr w2, wzr, #1
+ movz w12, #0, lsl #0
+ adrp x16, var_43
+ ldrh w8, [x16, #:lo12:var_43]
+ cmp w8, #0
+ csel x4, x2, x12, ne
+ cbnz w4, .L339
+ adrp x16, var_25
+ ldrsb w0, [x16, #:lo12:var_25]
+ cmp w0, #0
+ cset x8, ne
+ b .L340
+.L339:
+ orr w8, wzr, #1
+.L340:
+ adrp x16, struct_obj_3 + 4
+ ldrh w6, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w6, .L341
+ adrp x16, var_17
+ ldrsh w17, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w7, [x16, #:lo12:var_9]
+ sub w2, w7, #12288
+ sub w2, w2, #1187
+ lsl w9, w17, w2
+ cmp w9, #0
+ cset x9, ne
+ b .L342
+.L341:
+ movz w9, #0, lsl #0
+.L342:
+ movn w16, #76, lsl #0
+ eor w12, w6, w16
+ adrp x16, var_30
+ ldrh w3, [x16, #:lo12:var_30]
+ orr w3, wzr, w3, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w13, w3, w16
+ and w0, w12, w13
+ adrp x16, struct_obj_2
+ ldrsh w7, [x16, #:lo12:struct_obj_2]
+ sub w13, wzr, w7
+ sub w11, wzr, w13
+ adrp x16, var_1
+ ldrh w29, [x16, #:lo12:var_1]
+ sub w19, wzr, w29
+ madd w7, w11, w19, wzr
+ cmp w9, #4
+ cset x10, ne
+ cmp w7, w10
+ cset x17, gt
+ cbz w6, .L343
+ adrp x16, var_17
+ ldrsh w4, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w17, [x16, #:lo12:var_9]
+ sub w13, w17, #12288
+ sub w13, w13, #1187
+ lsl w10, w4, w13
+ cmp w10, #0
+ cset x17, ne
+ b .L344
+.L343:
+ movz w17, #0, lsl #0
+.L344:
+ adrp x16, var_7
+ ldrsb w4, [x16, #:lo12:var_7]
+ sub w2, wzr, w4
+ cbnz w2, .L345
+ adrp x16, struct_obj_4 + 16
+ ldrsb w5, [x16, #:lo12:struct_obj_4 + 16]
+ cbnz w5, .L346
+ adrp x16, var_12
+ ldrh w5, [x16, #:lo12:var_12]
+ cmp w5, #0
+ cset x10, ne
+ b .L347
+.L346:
+ orr w10, wzr, #1
+ b .L347
+.L345:
+ orr w10, wzr, #1
+.L347:
+ orr w9, wzr, #1
+ sub w13, wzr, w6
+ movz w16, #4355, lsl #0
+ cmp w13, w16
+ cset x2, gt
+ sub w2, w2, #1
+ cmp w17, #4
+ cset x4, ne
+ cmp w7, w4
+ cset x5, gt
+ cmp w0, w5
+ cset x5, ge
+ movz w16, #7584, lsl #0
+ cmp w5, w16
+ cset x14, le
+ cmp w2, w14
+ cset x13, le
+ orn w2, wzr, w13
+ cmp w2, w10
+ cset x2, eq
+ adrp x16, var_27
+ ldrsh w17, [x16, #:lo12:var_27]
+ movn w16, #97, lsl #0
+ and w13, w17, w16
+ cmp w9, w6
+ cset x29, ne
+ cmp w13, w29
+ cset x9, le
+ cmp w2, w9
+ cset x5, le
+ cmp w8, w5
+ b.eq .L348
+ cbz w6, .L349
+ adrp x16, var_17
+ ldrsh w9, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w8, [x16, #:lo12:var_9]
+ sub w4, w8, #12288
+ sub w4, w4, #1187
+ lsl w15, w9, w4
+ cmp w15, #0
+ cset x4, ne
+ b .L350
+.L349:
+ movz w4, #0, lsl #0
+.L350:
+ cmp w4, #4
+ cset x9, ne
+ cmp w7, w9
+ cset x15, gt
+ cbz w6, .L351
+ adrp x16, var_17
+ ldrsh w2, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w8, [x16, #:lo12:var_9]
+ sub w29, w8, #12288
+ sub w29, w29, #1187
+ lsl w29, w2, w29
+ cmp w29, #0
+ cset x14, ne
+ b .L352
+.L351:
+ movz w14, #0, lsl #0
+.L352:
+ cmp w14, #4
+ cset x8, ne
+ cmp w7, w8
+ cset x1, gt
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w13, w3, w16
+ cbz w6, .L353
+ adrp x16, var_17
+ ldrsh w15, [x16, #:lo12:var_17]
+ adrp x16, var_9
+ ldrh w1, [x16, #:lo12:var_9]
+ sub w1, w1, #12288
+ sub w1, w1, #1187
+ lsl w4, w15, w1
+ cmp w4, #0
+ cset x3, ne
+ b .L354
+.L353:
+ movz w3, #0, lsl #0
+.L354:
+ and w15, w12, w13
+ madd w1, w11, w19, wzr
+ cmp w3, #4
+ cset x17, ne
+ cmp w1, w17
+ cset x9, gt
+ b .L355
+.L348:
+ adrp x16, struct_obj_8 + 24
+ ldrh w12, [x16, #:lo12:struct_obj_8 + 24]
+ orr w8, w15, w12
+ cbnz w8, .L356
+ adrp x16, var_22
+ ldrsb w6, [x16, #:lo12:var_22]
+ cmp w6, #0
+ cset x5, ne
+ b .L357
+.L356:
+ orr w5, wzr, #1
+.L357:
+ orn w3, wzr, w5
+ adrp x16, struct_obj_4 + 2
+ ldrsb w14, [x16, #:lo12:struct_obj_4 + 2]
+ cmp w14, #30
+ cset x4, ge
+ adrp x16, struct_obj_8 + 26
+ ldrsb w9, [x16, #:lo12:struct_obj_8 + 26]
+ adrp x16, struct_obj_8 + 2
+ ldrsh w8, [x16, #:lo12:struct_obj_8 + 2]
+ cbnz w8, .L358
+ adrp x16, var_38
+ ldrsb w5, [x16, #:lo12:var_38]
+ cmp w5, #0
+ cset x4, ne
+ b .L359
+.L358:
+ orr w4, wzr, #1
+.L359:
+ adrp x16, var_57
+ ldrsb w10, [x16, #:lo12:var_57]
+ adrp x16, var_37
+ ldrsb w11, [x16, #:lo12:var_37]
+ and w7, w10, w11
+ cbnz w7, .L360
+ adrp x16, var_5
+ ldrh w10, [x16, #:lo12:var_5]
+ orn w6, wzr, w10
+ cmp w6, #0
+ cset x8, ne
+ b .L361
+.L360:
+ orr w8, wzr, #1
+.L361:
+ adrp x16, var_21
+ ldrsb w3, [x16, #:lo12:var_21]
+ cmp w3, #0
+ cset x2, eq
+ adrp x16, var_55
+ ldrsb w3, [x16, #:lo12:var_55]
+ madd w7, w3, w1, wzr
+ madd w2, w2, w7, wzr
+ ubfiz w11, w2, 0, 16
+ adrp x16, var_56
+ ldrh w10, [x16, #:lo12:var_56]
+ madd w1, w10, w9, wzr
+ cmp w4, w1
+ cset x9, le
+ cmp w9, w8
+ cset x12, gt
+ cmp w11, w12
+ cset x4, le
+ adrp x16, var_62
+ ldrh w14, [x16, #:lo12:var_62]
+ cmp w4, w14
+ cset x0, le
+ adrp x16, var_42
+ strb w0, [x16, #:lo12:var_42]
+.L355:
+ movn w11, #94, lsl #0
+ adrp x16, struct_obj_9 + 8
+ ldrsh w2, [x16, #:lo12:struct_obj_9 + 8]
+ sub w17, w2, #38
+ adrp x16, var_48
+ ldrh w9, [x16, #:lo12:var_48]
+ madd w17, w17, w9, wzr
+ madd w7, w17, w11, wzr
+ cmp w7, #110
+ b.ge .L362
+ movz w10, #5919, lsl #0
+ movk w10, #5, lsl #16
+ movn w13, #974, lsl #0
+ adrp x16, struct_obj_9 + 2
+ ldrsb w8, [x16, #:lo12:struct_obj_9 + 2]
+ madd w12, w8, w13, wzr
+ adrp x16, var_9
+ ldrh w15, [x16, #:lo12:var_9]
+ adrp x16, struct_obj_3
+ ldrsh w3, [x16, #:lo12:struct_obj_3]
+ madd w2, w15, w3, wzr
+ sdiv w9, w12, w2
+ movz w7, #9108, lsl #0
+ movk w7, #2, lsl #16
+ adrp x16, struct_obj_8 + 6
+ ldrsh w6, [x16, #:lo12:struct_obj_8 + 6]
+ cmp w6, #0
+ cset x13, eq
+ madd w17, w13, w7, wzr
+ madd w5, w9, w17, wzr
+ madd w5, w5, w10, wzr
+ cbnz w5, .L363
+ adrp x16, struct_obj_4 + 2
+ ldrsb w9, [x16, #:lo12:struct_obj_4 + 2]
+ ubfiz w3, w9, 0, 16
+.L363:
+ adrp x16, struct_obj_3 + 4
+ ldrh w14, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w14, .L364
+ adrp x16, var_17
+ ldrsh w7, [x16, #:lo12:var_17]
+ sub w12, w15, #12288
+ sub w12, w12, #1187
+ lsl w1, w7, w12
+ cmp w1, #0
+ cset x6, ne
+ b .L365
+.L364:
+ movz w6, #0, lsl #0
+.L365:
+ movn w16, #76, lsl #0
+ eor w10, w14, w16
+ adrp x16, var_30
+ ldrh w13, [x16, #:lo12:var_30]
+ orr w11, wzr, w13, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w9, w11, w16
+ and w5, w10, w9
+ adrp x16, struct_obj_2
+ ldrsh w3, [x16, #:lo12:struct_obj_2]
+ sub w12, wzr, w3
+ sub w2, wzr, w12
+ adrp x16, var_1
+ ldrh w9, [x16, #:lo12:var_1]
+ sub w29, wzr, w9
+ madd w2, w2, w29, wzr
+ cmp w6, #4
+ cset x29, ne
+ cmp w2, w29
+ cset x4, gt
+ adrp x16, var_7
+ ldrsb w10, [x16, #:lo12:var_7]
+ sub w4, wzr, w10
+ cbnz w4, .L366
+ adrp x16, struct_obj_4 + 16
+ ldrsb w7, [x16, #:lo12:struct_obj_4 + 16]
+.L366:
+ sub w6, wzr, w14
+ movz w16, #4355, lsl #0
+ cmp w6, w16
+ cset x7, gt
+ adrp x16, var_27
+ ldrsh w3, [x16, #:lo12:var_27]
+ movn w16, #97, lsl #0
+ and w0, w3, w16
+ adrp x16, var_18
+ ldrsb w12, [x16, #:lo12:var_18]
+ ubfiz w3, w12, 0, 16
+ cbnz w3, .L367
+ cbz w14, .L368
+ adrp x16, var_17
+ ldrsh w1, [x16, #:lo12:var_17]
+ sub w9, w15, #12288
+ sub w9, w9, #1187
+ lsl w8, w1, w9
+ cmp w8, #0
+ cset x29, ne
+ b .L369
+.L368:
+ movz w29, #0, lsl #0
+.L369:
+ cmp w29, #4
+ cset x6, ne
+ cmp w2, w6
+ cset x6, gt
+ cbz w14, .L370
+ adrp x16, var_17
+ ldrsh w6, [x16, #:lo12:var_17]
+ sub w3, w15, #12288
+ sub w3, w3, #1187
+ lsl w15, w6, w3
+ cmp w15, #0
+ cset x10, ne
+ b .L371
+.L370:
+ movz w10, #0, lsl #0
+.L371:
+ cbnz w4, .L372
+ adrp x16, struct_obj_4 + 16
+ ldrsb w13, [x16, #:lo12:struct_obj_4 + 16]
+ cbnz w13, .L373
+ adrp x16, var_12
+ ldrh w17, [x16, #:lo12:var_12]
+ cmp w17, #0
+ cset x1, ne
+ b .L374
+.L373:
+ orr w1, wzr, #1
+ b .L374
+.L372:
+ orr w1, wzr, #1
+.L374:
+ orr w11, wzr, #1
+ sub w12, w7, #1
+ cmp w10, #4
+ cset x15, ne
+ cmp w2, w15
+ cset x29, gt
+ cmp w5, w29
+ cset x3, ge
+ movz w16, #7584, lsl #0
+ cmp w3, w16
+ cset x5, le
+ cmp w12, w5
+ cset x29, le
+ orn w12, wzr, w29
+ cmp w12, w1
+ cset x8, eq
+ cmp w11, w14
+ cset x17, ne
+ cmp w0, w17
+ cset x15, le
+ cmp w8, w15
+ b.gt .L375
+ adrp x16, struct_obj_8 + 18
+ ldrsh w0, [x16, #:lo12:struct_obj_8 + 18]
+ cmp w0, #0
+ cset x0, ne
+ cbnz w0, .L367
+.L375:
+ orr w0, wzr, #1
+ eor w0, w0, #1
+ cbz w0, .L329
+.L367:
+ orr w0, wzr, #1
+ cbnz w0, .L329
+ adrp x16, var_45
+ ldrsb w0, [x16, #:lo12:var_45]
+ cbz w0, .L329
+ adrp x16, struct_obj_8 + 26
+ ldrsb w0, [x16, #:lo12:struct_obj_8 + 26]
+ cbnz w0, .L329
+ adrp x16, var_23
+ ldrh w0, [x16, #:lo12:var_23]
+ cmp w0, #0
+ cset x0, ne
+ b .L329
+.L362:
+ adrp x16, var_17
+ ldrsh w12, [x16, #:lo12:var_17]
+ adrp x16, var_60
+ ldrsh w3, [x16, #:lo12:var_60]
+ cbnz w3, .L376
+ adrp x16, struct_obj_9 + 26
+ ldrsh w11, [x16, #:lo12:struct_obj_9 + 26]
+ cmp w11, #0
+ cset x7, ne
+ b .L377
+.L376:
+ orr w7, wzr, #1
+.L377:
+ sbfiz w9, w3, 0, 8
+ adrp x16, struct_obj_8 + 28
+ ldrsh w8, [x16, #:lo12:struct_obj_8 + 28]
+ and w5, w9, w8
+ asr w7, w5, w7
+ cbnz w7, .L378
+ adrp x16, struct_obj_3 + 4
+ ldrh w5, [x16, #:lo12:struct_obj_3 + 4]
+.L378:
+ adrp x16, var_62
+ ldrh w5, [x16, #:lo12:var_62]
+ add w6, w2, w5
+ adrp x16, struct_obj_2
+ ldrsh w5, [x16, #:lo12:struct_obj_2]
+ cmp w5, #0
+ cset x15, eq
+ adrp x16, struct_obj_3 + 4
+ ldrh w11, [x16, #:lo12:struct_obj_3 + 4]
+ cbz w11, .L379
+ adrp x16, var_9
+ ldrh w4, [x16, #:lo12:var_9]
+ sub w13, w4, #12288
+ sub w13, w13, #1187
+ lsl w9, w12, w13
+ cmp w9, #0
+ cset x12, ne
+ b .L380
+.L379:
+ movz w12, #0, lsl #0
+.L380:
+ movn w16, #76, lsl #0
+ eor w14, w11, w16
+ adrp x16, var_30
+ ldrh w4, [x16, #:lo12:var_30]
+ orr w15, wzr, w4, asr #7
+ movz w16, #65483, lsl #0
+ movk w16, #8191, lsl #16
+ orr w13, w15, w16
+ and w13, w14, w13
+ sub w15, wzr, w5
+ sub w17, wzr, w15
+ adrp x16, var_1
+ ldrh w7, [x16, #:lo12:var_1]
+ sub w14, wzr, w7
+ madd w3, w17, w14, wzr
+ cmp w12, #4
+ cset x5, ne
+ cmp w3, w5
+ cset x8, gt
+ adrp x16, var_7
+ ldrsb w0, [x16, #:lo12:var_7]
+ sub w0, wzr, w0
+ cbnz w0, .L381
+ adrp x16, struct_obj_4 + 16
+ ldrsb w0, [x16, #:lo12:struct_obj_4 + 16]
+.L381:
+ adrp x16, var_37
+ ldrsb w0, [x16, #:lo12:var_37]
+ movz w0, #0, lsl #0
+ adrp x16, var_52
+ strh w0, [x16, #:lo12:var_52]
+.L329:
+ ldr x19, [sp, #16]
+ ldr x20, [sp, #24]
+ ldr x30, [sp, #8]
+ add sp, sp, #32
+ ret x30
+ .type foo, @function
+ .size foo, . - foo
diff --git a/multiple_labels_crash_test/hash.c b/multiple_labels_crash_test/hash.c
new file mode 100644
index 00000000..a979bdc1
--- /dev/null
+++ b/multiple_labels_crash_test/hash.c
@@ -0,0 +1,3 @@
+void hash(unsigned long long int *seed, unsigned long long int const v) {
+ *seed ^= v + 0x9e3779b9 + ((*seed)<<6) + ((*seed)>>2);
+}
diff --git a/multiple_labels_crash_test/init.c b/multiple_labels_crash_test/init.c
new file mode 100644
index 00000000..d3c7cfcc
--- /dev/null
+++ b/multiple_labels_crash_test/init.c
@@ -0,0 +1,209 @@
+#include "init.h"
+
+const unsigned short var_1 = 64966;
+const unsigned short var_2 = 17784;
+signed char var_3 = 58;
+const unsigned short var_4 = 3656;
+unsigned short var_5 = 17583;
+const unsigned short var_6 = 40663;
+const signed char var_7 = 42;
+unsigned short var_8 = 14662;
+unsigned short var_9 = 13482;
+unsigned short var_10 = 21751;
+const short var_11 = 9782;
+const unsigned short var_12 = 29985;
+short var_13 = -23903;
+const signed char var_14 = 26;
+const unsigned short var_15 = 38613;
+unsigned short var_16 = 7910;
+short var_17 = 32667;
+signed char var_18 = 77;
+signed char var_19 = 69;
+unsigned short var_20 = 49524;
+const signed char var_21 = -59;
+const signed char var_22 = 114;
+const unsigned short var_23 = 43999;
+short var_24 = -4596;
+signed char var_25 = 127;
+const unsigned short var_26 = 14598;
+const short var_27 = 15321;
+short var_28 = 13394;
+const unsigned short var_29 = 51752;
+const unsigned short var_30 = 42705;
+const short var_31 = -23514;
+unsigned short var_32 = 46800;
+const unsigned short var_33 = 40302;
+const signed char var_34 = -74;
+unsigned short var_35 = 14428;
+
+
+short var_36 = 27385;
+signed char var_37 = 116;
+signed char var_38 = 47;
+unsigned short var_39 = 28164;
+signed char var_40 = 68;
+unsigned short var_41 = 48535;
+signed char var_42 = -56;
+unsigned short var_43 = 63272;
+unsigned short var_44 = 53605;
+signed char var_45 = -76;
+unsigned short var_46 = 37656;
+signed char var_47 = -2;
+unsigned short var_48 = 20934;
+signed char var_49 = -21;
+unsigned short var_50 = 46979;
+short var_51 = -11787;
+short var_52 = 9874;
+short var_53 = 13740;
+short var_54 = -24909;
+signed char var_55 = -12;
+unsigned short var_56 = 20186;
+signed char var_57 = -80;
+signed char var_58 = 48;
+unsigned short var_59 = 59812;
+short var_60 = 21585;
+signed char var_61 = -16;
+unsigned short var_62 = 49246;
+short var_63 = 21666;
+signed char var_64 = -18;
+short var_65 = -12846;
+
+
+signed char var_70 = 63;
+short var_78 = -3444;
+unsigned short var_82 = 58294;
+short var_90 = -25718;
+unsigned short var_94 = 54118;
+short var_100 = 16012;
+short var_106 = 6394;
+unsigned short var_123 = 42864;
+short var_129 = 18229;
+signed char var_143 = 92;
+short var_152 = -25759;
+signed char var_156 = -88;
+signed char var_162 = 86;
+short var_178 = -15567;
+signed char var_217 = 37;
+short var_234 = 29976;
+signed char var_240 = 29;
+unsigned short var_241 = 39297;
+signed char var_260 = -30;
+signed char var_268 = 13;
+short var_284 = -4345;
+unsigned short var_297 = 16067;
+signed char var_314 = -126;
+unsigned short var_358 = 48899;
+short var_359 = 5585;
+signed char var_367 = 57;
+unsigned short var_392 = 6146;
+signed char var_468 = -7;
+signed char var_500 = 28;
+short var_514 = -27356;
+signed char var_522 = 67;
+signed char var_543 = -115;
+unsigned short var_544 = 38397;
+signed char var_547 = 105;
+signed char var_549 = 62;
+short var_558 = -1976;
+signed char var_591 = 78;
+
+
+struct_5 struct_obj_1;
+struct_5 struct_obj_2;
+struct_5 struct_obj_3;
+struct_2 struct_obj_4;
+
+
+struct_1 struct_obj_5;
+struct_5 struct_obj_6;
+struct_1 struct_obj_7;
+struct_4 struct_obj_8;
+struct_2 struct_obj_9;
+struct_1 struct_obj_10;
+
+
+
+
+
+
+
+
+
+
+
+
+void init () {
+ struct_obj_1.member_5_0 = (short) (-13981);
+ struct_obj_1.member_5_1 = (unsigned short) (32569);
+ struct_obj_1.member_5_2 = (unsigned short) (55905);
+ struct_obj_1.member_5_3 = (short) (740);
+ struct_obj_2.member_5_0 = (short) (-16520);
+ struct_obj_2.member_5_1 = (unsigned short) (25768);
+ struct_obj_2.member_5_2 = (unsigned short) (41445);
+ struct_obj_2.member_5_3 = (short) (25458);
+ struct_obj_3.member_5_0 = (short) (-27814);
+ struct_obj_3.member_5_1 = (unsigned short) (32840);
+ struct_obj_3.member_5_2 = (unsigned short) (59825);
+ struct_obj_3.member_5_3 = (short) (-26656);
+ struct_obj_4.member_2_0 = (short) (7610);
+ struct_obj_4.member_2_1.member_1_0 = (signed char) (86);
+ struct_obj_4.member_2_1.member_1_1 = (short) (-29951);
+ struct_obj_4.member_2_1.member_1_2 = (signed char) (-57);
+ struct_obj_4.member_2_1.member_1_3 = (short) (-1514);
+ struct_obj_4.member_2_2 = (unsigned short) (30795);
+ struct_obj_4.member_2_3.member_1_0 = (signed char) (17);
+ struct_obj_4.member_2_3.member_1_1 = (short) (-21792);
+ struct_obj_4.member_2_3.member_1_2 = (signed char) (-78);
+ struct_obj_4.member_2_3.member_1_3 = (short) (-19417);
+ struct_obj_4.member_2_4 = (short) (-19205);
+ struct_obj_4.member_2_5 = (unsigned short) (10096);
+ struct_obj_4.member_2_6 = (unsigned short) (56048);
+ struct_obj_4.member_2_7 = (short) (-9525);
+ struct_obj_5.member_1_0 = (signed char) (-105);
+ struct_obj_5.member_1_1 = (short) (28953);
+ struct_obj_5.member_1_2 = (signed char) (-80);
+ struct_obj_5.member_1_3 = (short) (-20984);
+ struct_obj_6.member_5_0 = (short) (30730);
+ struct_obj_6.member_5_1 = (unsigned short) (44652);
+ struct_obj_6.member_5_2 = (unsigned short) (45968);
+ struct_obj_6.member_5_3 = (short) (12419);
+ struct_obj_7.member_1_0 = (signed char) (-74);
+ struct_obj_7.member_1_1 = (short) (-6639);
+ struct_obj_7.member_1_2 = (signed char) (-119);
+ struct_obj_7.member_1_3 = (short) (13879);
+ struct_obj_8.member_4_0 = (unsigned short) (17346);
+ struct_obj_8.member_4_1.member_3_0 = (short) (657);
+ struct_obj_8.member_4_1.member_3_1.member_1_0 = (signed char) (-103);
+ struct_obj_8.member_4_1.member_3_1.member_1_1 = (short) (25291);
+ struct_obj_8.member_4_1.member_3_1.member_1_2 = (signed char) (-76);
+ struct_obj_8.member_4_1.member_3_1.member_1_3 = (short) (-25024);
+ struct_obj_8.member_4_2 = (signed char) (42);
+ struct_obj_8.member_4_3 = (unsigned short) (57223);
+ struct_obj_8.member_4_4 = (signed char) (58);
+ struct_obj_8.member_4_5 = (short) (-1330);
+ struct_obj_8.member_4_6 = (short) (-13828);
+ struct_obj_8.member_4_7 = (unsigned short) (26678);
+ struct_obj_8.member_4_8 = (unsigned short) (52711);
+ struct_obj_8.member_4_9.member_1_0 = (signed char) (6);
+ struct_obj_8.member_4_9.member_1_1 = (short) (13897);
+ struct_obj_8.member_4_9.member_1_2 = (signed char) (-94);
+ struct_obj_8.member_4_9.member_1_3 = (short) (-30110);
+ struct_obj_9.member_2_0 = (short) (-24156);
+ struct_obj_9.member_2_1.member_1_0 = (signed char) (40);
+ struct_obj_9.member_2_1.member_1_1 = (short) (31967);
+ struct_obj_9.member_2_1.member_1_2 = (signed char) (-36);
+ struct_obj_9.member_2_1.member_1_3 = (short) (21679);
+ struct_obj_9.member_2_2 = (unsigned short) (40629);
+ struct_obj_9.member_2_3.member_1_0 = (signed char) (116);
+ struct_obj_9.member_2_3.member_1_1 = (short) (-741);
+ struct_obj_9.member_2_3.member_1_2 = (signed char) (101);
+ struct_obj_9.member_2_3.member_1_3 = (short) (24485);
+ struct_obj_9.member_2_4 = (short) (13544);
+ struct_obj_9.member_2_5 = (unsigned short) (26978);
+ struct_obj_9.member_2_6 = (unsigned short) (9057);
+ struct_obj_9.member_2_7 = (short) (21085);
+ struct_obj_10.member_1_0 = (signed char) (94);
+ struct_obj_10.member_1_1 = (short) (28577);
+ struct_obj_10.member_1_2 = (signed char) (-56);
+ struct_obj_10.member_1_3 = (short) (-21782);
+} \ No newline at end of file
diff --git a/multiple_labels_crash_test/init.h b/multiple_labels_crash_test/init.h
new file mode 100644
index 00000000..d3b5b008
--- /dev/null
+++ b/multiple_labels_crash_test/init.h
@@ -0,0 +1,181 @@
+void hash(unsigned long long int *seed, unsigned long long int const v);
+
+extern const unsigned short var_1;
+extern const unsigned short var_2;
+extern signed char var_3;
+extern const unsigned short var_4;
+extern unsigned short var_5;
+extern const unsigned short var_6;
+extern const signed char var_7;
+extern unsigned short var_8;
+extern unsigned short var_9;
+extern unsigned short var_10;
+extern const short var_11;
+extern const unsigned short var_12;
+extern short var_13;
+extern const signed char var_14;
+extern const unsigned short var_15;
+extern unsigned short var_16;
+extern short var_17;
+extern signed char var_18;
+extern signed char var_19;
+extern unsigned short var_20;
+extern const signed char var_21;
+extern const signed char var_22;
+extern const unsigned short var_23;
+extern short var_24;
+extern signed char var_25;
+extern const unsigned short var_26;
+extern const short var_27;
+extern short var_28;
+extern const unsigned short var_29;
+extern const unsigned short var_30;
+extern const short var_31;
+extern unsigned short var_32;
+extern const unsigned short var_33;
+extern const signed char var_34;
+extern unsigned short var_35;
+
+
+extern short var_36;
+extern signed char var_37;
+extern signed char var_38;
+extern unsigned short var_39;
+extern signed char var_40;
+extern unsigned short var_41;
+extern signed char var_42;
+extern unsigned short var_43;
+extern unsigned short var_44;
+extern signed char var_45;
+extern unsigned short var_46;
+extern signed char var_47;
+extern unsigned short var_48;
+extern signed char var_49;
+extern unsigned short var_50;
+extern short var_51;
+extern short var_52;
+extern short var_53;
+extern short var_54;
+extern signed char var_55;
+extern unsigned short var_56;
+extern signed char var_57;
+extern signed char var_58;
+extern unsigned short var_59;
+extern short var_60;
+extern signed char var_61;
+extern unsigned short var_62;
+extern short var_63;
+extern signed char var_64;
+extern short var_65;
+
+
+extern signed char var_70;
+extern short var_78;
+extern unsigned short var_82;
+extern short var_90;
+extern unsigned short var_94;
+extern short var_100;
+extern short var_106;
+extern unsigned short var_123;
+extern short var_129;
+extern signed char var_143;
+extern short var_152;
+extern signed char var_156;
+extern signed char var_162;
+extern short var_178;
+extern signed char var_217;
+extern short var_234;
+extern signed char var_240;
+extern unsigned short var_241;
+extern signed char var_260;
+extern signed char var_268;
+extern short var_284;
+extern unsigned short var_297;
+extern signed char var_314;
+extern unsigned short var_358;
+extern short var_359;
+extern signed char var_367;
+extern unsigned short var_392;
+extern signed char var_468;
+extern signed char var_500;
+extern short var_514;
+extern signed char var_522;
+extern signed char var_543;
+extern unsigned short var_544;
+extern signed char var_547;
+extern signed char var_549;
+extern short var_558;
+extern signed char var_591;
+
+
+typedef struct {
+ signed char member_1_0;
+ short member_1_1;
+ signed char member_1_2;
+ short member_1_3;
+} struct_1;
+
+typedef struct {
+ short member_2_0;
+ struct_1 member_2_1;
+ unsigned short member_2_2;
+ struct_1 member_2_3;
+ short member_2_4;
+ unsigned short member_2_5;
+ unsigned short member_2_6;
+ short member_2_7;
+} struct_2;
+
+typedef struct {
+ short member_3_0;
+ struct_1 member_3_1;
+} struct_3;
+
+typedef struct {
+ unsigned short member_4_0;
+ struct_3 member_4_1;
+ signed char member_4_2;
+ unsigned short member_4_3;
+ signed char member_4_4;
+ short member_4_5;
+ short member_4_6;
+ unsigned short member_4_7;
+ unsigned short member_4_8;
+ struct_1 member_4_9;
+} struct_4;
+
+typedef struct {
+ short member_5_0;
+ unsigned short member_5_1;
+ unsigned short member_5_2;
+ short member_5_3;
+} struct_5;
+
+typedef struct {
+ signed char member_6_0;
+ unsigned short member_6_1;
+ short member_6_2;
+ struct_3 member_6_3;
+ struct_3 member_6_4;
+ signed char member_6_5;
+ short member_6_6;
+} struct_6;
+
+
+
+extern struct_5 struct_obj_1;
+extern struct_5 struct_obj_2;
+extern struct_5 struct_obj_3;
+extern struct_2 struct_obj_4;
+
+
+extern struct_1 struct_obj_5;
+extern struct_5 struct_obj_6;
+extern struct_1 struct_obj_7;
+extern struct_4 struct_obj_8;
+extern struct_2 struct_obj_9;
+extern struct_1 struct_obj_10;
+
+
+
+
diff --git a/test/aarch64/README.md b/test/aarch64/README.md
new file mode 100644
index 00000000..f943489c
--- /dev/null
+++ b/test/aarch64/README.md
@@ -0,0 +1,15 @@
+# Testing the Machblock --> Asmblock translation
+1. Get the reference version of compcert-aarch in the father's directory if this repo (checkout `aarch64-ref`)
+2. Compile both repo for aarch64
+3. CD in this folder (`test/aarch64`)
+4. Launch `./asmb_aarch64_gen_test.sh`
+
+## Options
+The script takes following options :
+- `-c` to clear generated files at the end
+- `-w` to suppress warnings from Compcert
+
+## Tests files
+The variable `DIRS` in the script takes the list of directories containing c files.
+The tests under `test/aarch64/c` are simpler and useful to debug only one feature at a time.
+Most of them comes from [here](https://cis.temple.edu/~ingargio/cis71/code/).
diff --git a/test/aarch64/c/add_return.c b/test/aarch64/c/add_return.c
new file mode 100644
index 00000000..c29aeb16
--- /dev/null
+++ b/test/aarch64/c/add_return.c
@@ -0,0 +1 @@
+int main(int r) { return r+1; }
diff --git a/test/aarch64/c/addresses.c b/test/aarch64/c/addresses.c
new file mode 100644
index 00000000..e3cb5201
--- /dev/null
+++ b/test/aarch64/c/addresses.c
@@ -0,0 +1,32 @@
+/* addresses.c -- Playing with addresses of variables and their contents:
+ * what is done by C with variables, addresses, and values.
+ */
+
+#include <stdio.h>
+
+void moo(int a, int * b);
+
+int main(void) {
+ int x;
+ int *y;
+
+ x=1;
+ y=&x;
+ printf("Address of x = %d, value of x = %d\n", &x, x);
+ printf("Address of y = %d, value of y = %d, value of *y = %d\n", &y, y, *y);
+ moo(9,y);
+}
+
+void moo(int a, int *b){
+ printf("Address of a = %d, value of a = %d\n", &a, a);
+ printf("Address of b = %d, value of b = %d, value of *b = %d\n", &b, b, *b);
+}
+
+/* Output from running this program on my computer:
+
+Address of x = 536869640, value of x = 1
+Address of y = 536869632, value of y = 536869640, value of *y = 1
+Address of a = 536869608, value of a = 9
+Address of b = 536869600, value of b = 536869640, value of *b = 1
+
+ */
diff --git a/test/aarch64/c/arith.c b/test/aarch64/c/arith.c
new file mode 100644
index 00000000..02df141b
--- /dev/null
+++ b/test/aarch64/c/arith.c
@@ -0,0 +1,16 @@
+int main(int num1, int num2)
+{
+ int sum, sub, mult, mod;
+ float div;
+
+ /*
+ * Perform all arithmetic operations
+ */
+ sum = num1 + num2;
+ sub = num1 - num2;
+ mult = num1 * num2;
+ div = (float)num1 / num2;
+ mod = num1 % num2;
+
+ return sum + sub + mult + div + mod;
+}
diff --git a/test/aarch64/c/arith_print.c b/test/aarch64/c/arith_print.c
new file mode 100644
index 00000000..d404a151
--- /dev/null
+++ b/test/aarch64/c/arith_print.c
@@ -0,0 +1,19 @@
+int main()
+{
+ int num1 = 2;
+ int num2 = 4;
+ int sum, sub, mult, mod;
+ float div;
+
+ /*
+ * Perform all arithmetic operations
+ */
+ sum = num1 + num2;
+ sub = num1 - num2;
+ mult = num1 * num2;
+ div = (float)num1 / num2;
+ mod = num1 % num2;
+
+ printf("%d", sum + sub + mult + div + mod);
+ return;
+}
diff --git a/test/aarch64/c/armstrong.c b/test/aarch64/c/armstrong.c
new file mode 100644
index 00000000..c5d838f9
--- /dev/null
+++ b/test/aarch64/c/armstrong.c
@@ -0,0 +1,21 @@
+int main()
+{
+ int n,sum,i,t,a,z;
+
+ for(i = 1; i <= 500; i++)
+ {
+ t = i; // as we need to retain the original number
+ sum = 0;
+ while(t != 0)
+ {
+ a = t%10;
+ sum += a*a*a;
+ t = t/10;
+ }
+
+ if(sum == i)
+ z += i;
+ }
+
+ return 0;
+}
diff --git a/test/aarch64/c/array1.c b/test/aarch64/c/array1.c
new file mode 100644
index 00000000..5840ca66
--- /dev/null
+++ b/test/aarch64/c/array1.c
@@ -0,0 +1,64 @@
+/* array1.c -- Simple operations with arrays.
+ */
+
+#include <stdio.h>
+#define N 10
+
+void oneWay(void);
+void anotherWay(void);
+
+int main(void) {
+ printf("\noneWay:\n");
+ oneWay();
+ printf("\nantherWay:\n");
+ anotherWay();
+}
+
+/*Array initialized with aggregate */
+void oneWay(void) {
+ int vect[N] = {1,2,3,4,5,6,7,8,9,0};
+ int i;
+
+ for (i=0; i<N; i++)
+ printf("i = %2d vect[i] = %2d\n", i, vect[i]);
+}
+
+/*Array initialized with loop */
+void anotherWay(void) {
+ int vect[N];
+ int i;
+
+ for (i=0; i<N; i++)
+ vect[i] = i+1;
+
+ for (i=0; i<N; i++)
+ printf("i = %2d vect[i] = %2d\n", i, vect[i]);
+}
+
+/* The output of this program is
+
+oneWay:
+i = 0 vect[i] = 1
+i = 1 vect[i] = 2
+i = 2 vect[i] = 3
+i = 3 vect[i] = 4
+i = 4 vect[i] = 5
+i = 5 vect[i] = 6
+i = 6 vect[i] = 7
+i = 7 vect[i] = 8
+i = 8 vect[i] = 9
+i = 9 vect[i] = 0
+
+antherWay:
+i = 0 vect[i] = 1
+i = 1 vect[i] = 2
+i = 2 vect[i] = 3
+i = 3 vect[i] = 4
+i = 4 vect[i] = 5
+i = 5 vect[i] = 6
+i = 6 vect[i] = 7
+i = 7 vect[i] = 8
+i = 8 vect[i] = 9
+i = 9 vect[i] = 10
+
+ */
diff --git a/test/aarch64/c/array2.c b/test/aarch64/c/array2.c
new file mode 100644
index 00000000..389e1596
--- /dev/null
+++ b/test/aarch64/c/array2.c
@@ -0,0 +1,74 @@
+/* array2.c -- Read/writing/reversing integer arrays
+ */
+
+#include <stdio.h>
+
+#define NMAX 10
+
+void intSwap(int *x, int *y);
+int getIntArray(int a[], int nmax, int sentinel);
+void printIntArray(int a[], int n);
+void reverseIntArray(int a[], int n);
+
+int main(void) {
+ int x[NMAX];
+ int hmny;
+
+ hmny = getIntArray(x, NMAX, 0);
+ printf("The array was: \n");
+ printIntArray(x,hmny);
+ reverseIntArray(x,hmny);
+ printf("after reverse it is:\n");
+ printIntArray(x,hmny);
+}
+
+void intSwap(int *x, int *y)
+ /* It swaps the content of x and y */
+{
+ int temp = *x;
+ *x = *y;
+ *y = temp;
+}
+
+void printIntArray(int a[], int n)
+ /* n is the number of elements in the array a.
+ * These values are printed out, five per line. */
+{
+ int i;
+
+ for (i=0; i<n; ){
+ printf("\t%d ", a[i++]);
+ if (i%5==0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int getIntArray(int a[], int nmax, int sentinel)
+ /* It reads up to nmax integers and stores then in a; sentinel
+ * terminates input. */
+{
+ int n = 0;
+ int temp;
+
+ do {
+ printf("Enter integer [%d to terminate] : ", sentinel);
+ scanf("%d", &temp);
+ if (temp==sentinel) break;
+ if (n==nmax)
+ printf("array is full\n");
+ else
+ a[n++] = temp;
+ }while (1);
+ return n;
+}
+
+void reverseIntArray(int a[], int n)
+ /* It reverse the order of the first n elements of a */
+{
+ int i;
+
+ for(i=0;i<n/2;i++){
+ intSwap(&a[i],&a[n-i-1]);
+ }
+}
diff --git a/test/aarch64/c/biggest_of_3_int.c b/test/aarch64/c/biggest_of_3_int.c
new file mode 100644
index 00000000..346908fc
--- /dev/null
+++ b/test/aarch64/c/biggest_of_3_int.c
@@ -0,0 +1,10 @@
+int main(int a, int b, int c) {
+ if ((a > b) && (a > c)) {
+ return a;
+ } else if (b > c) {
+ return b;
+ } else {
+ return c;
+ }
+ return 0;
+}
diff --git a/test/aarch64/c/bitwise1.c b/test/aarch64/c/bitwise1.c
new file mode 100644
index 00000000..d20641de
--- /dev/null
+++ b/test/aarch64/c/bitwise1.c
@@ -0,0 +1,8 @@
+int main()
+{
+ int x = 6, y = 4;
+ x = x^y;
+ y = x^876987^x | y << 42;
+
+ return ~x^y;
+}
diff --git a/test/aarch64/c/cpintarray.c b/test/aarch64/c/cpintarray.c
new file mode 100644
index 00000000..8049fdfb
--- /dev/null
+++ b/test/aarch64/c/cpintarray.c
@@ -0,0 +1,108 @@
+/* cpintarray.c -- Example showing how addresses and arrays are alike
+ */
+
+#include <stdio.h>
+#define SIZE 8
+
+void cpIntArray(int *a, int *b, int n)
+/*It copies n integers starting at b into a*/
+{
+ for(;n>0;n--)
+ *a++=*b++;
+}
+
+
+void printIntArray(int a[], int n)
+ /* n is the number of elements in the array a.
+ * These values are printed out, five per line. */
+{
+ int i;
+
+ for (i=0; i<n; ){
+ printf("\t%d ", a[i++]);
+ if (i%5==0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+int getIntArray(int a[], int nmax, int sentinel)
+ /* It reads up to nmax integers and stores then in a; sentinel
+ * terminates input. */
+{
+ int n = 0;
+ int temp;
+
+ do {
+ printf("Enter integer [%d to terminate] : ", sentinel);
+ scanf("%d", &temp);
+ if (temp==sentinel) break;
+ if (n==nmax)
+ printf("array is full\n");
+ else
+ a[n++] = temp;
+ }while (1);
+ return n;
+}
+
+int main(void){
+ int x[SIZE], nx;
+ int y[SIZE], ny;
+
+ printf("Read the x array:\n");
+ nx = getIntArray(x,SIZE,0);
+ printf("The x array is:\n");
+ printIntArray(x,nx);
+
+ printf("Read the y array:\n");
+ ny = getIntArray(y,SIZE,0);
+ printf("The y array is:\n");
+ printIntArray(y,ny);
+
+ cpIntArray(x+2,y+3,4);
+ /*Notice the expression 'x+2'. x is interpreted as the address for
+ the beginning of the x array. +2 sais to increment that address
+ by two units, in accordance with the type of x, which is
+ an integer array. Thus we move from x to two integer locations
+ past it, that is to the location of x[2]. The same reasoning applied
+ to 'y+3'.
+ */
+ printf("Printing x after having copied 4 elements\n"
+ "from y starting at y[3] into x starting at x[2]\n");
+ printIntArray(x,nx);
+}
+
+/* Here is the interaction in a run of this program:
+
+Read the x array:
+Enter integer [0 to terminate] : 1
+Enter integer [0 to terminate] : 3
+Enter integer [0 to terminate] : 5
+Enter integer [0 to terminate] : 7
+Enter integer [0 to terminate] : 9
+Enter integer [0 to terminate] : 11
+Enter integer [0 to terminate] : 13
+Enter integer [0 to terminate] : 15
+Enter integer [0 to terminate] : 0
+The x array is:
+ 1 3 5 7 9
+ 11 13 15
+Read the y array:
+Enter integer [0 to terminate] : 2
+Enter integer [0 to terminate] : 4
+Enter integer [0 to terminate] : 6
+Enter integer [0 to terminate] : 8
+Enter integer [0 to terminate] : 10
+Enter integer [0 to terminate] : 12
+Enter integer [0 to terminate] : 14
+Enter integer [0 to terminate] : 16
+Enter integer [0 to terminate] : 0
+The y array is:
+ 2 4 6 8 10
+ 12 14 16
+Printing x after having copied 4 elements
+from y starting at y[3] into x starting at x[2]
+ 1 3 8 10 12
+ 14 13 15
+
+ */
diff --git a/test/aarch64/c/enum1.c b/test/aarch64/c/enum1.c
new file mode 100644
index 00000000..d1f6b48d
--- /dev/null
+++ b/test/aarch64/c/enum1.c
@@ -0,0 +1,52 @@
+/* enum1.c -- Starting to use enumerated types: Printing for each
+ * day of the week, today, yesterday, and tomorrow, both
+ * as a string and as a number.
+ */
+
+#include <stdio.h>
+
+/* Introducing an enumerated data type */
+enum days {monday,tuesday,wednesday,thursday,friday,saturday,sunday};
+typedef enum days days; // This allows us to use "days" as an abbreviation
+ // for "enum days"
+
+/* Two useful functions */
+days yesterday(days today){
+ return (today+6)%7;
+}
+days tomorrow(days today){
+ return (today+1)%7;
+}
+
+// A useful array: thedays is an array of constant (i.e you cannot
+// modify them) pointers to constant (i.e. you cannot modify them) strings
+const char * const thedays[] =
+ {"monday", "tuesday", "wednesday", "thursday",
+ "friday", "saturday", "sunday"};
+
+int main(void){
+ days today;
+
+ printf("today \tyesterday \ttomorrow\n"
+ "============================================\n");
+ for (today=monday;today<=sunday;today++)
+ printf("%s = %d \t %s = %d \t %s = %d\n",
+ thedays[today], today,
+ thedays[yesterday(today)], yesterday(today),
+ thedays[tomorrow(today)], tomorrow(today));
+}
+
+/*
+ The output is:
+
+today yesterday tomorrow
+============================================
+monday = 0 sunday = 6 tuesday = 1
+tuesday = 1 monday = 0 wednesday = 2
+wednesday = 2 tuesday = 1 thursday = 3
+thursday = 3 wednesday = 2 friday = 4
+friday = 4 thursday = 3 saturday = 5
+saturday = 5 friday = 4 sunday = 6
+sunday = 6 saturday = 5 monday = 0
+
+*/
diff --git a/test/aarch64/c/enum2.c b/test/aarch64/c/enum2.c
new file mode 100644
index 00000000..a18acb80
--- /dev/null
+++ b/test/aarch64/c/enum2.c
@@ -0,0 +1,50 @@
+/* enum2.c -- Starting to use enumerated types: Printing for each
+ * day of the week, today, yesterday, and tomorrow, both
+ * as a string and as a number. We use typedef
+ */
+
+#include <stdio.h>
+
+/* Introducing an enumerated data type */
+typedef enum {monday,tuesday,wednesday,thursday,friday,saturday,sunday} days;
+
+/* Two useful functions */
+days yesterday(days today);
+days tomorrow(days today);
+
+char *thedays[] = {"monday", "tuesday", "wednesday", "thursday",
+ "friday", "saturday", "sunday"};
+
+int main(void){
+ days today;
+
+ printf("today \tyesterday \ttomorrow\n"
+ "============================================\n");
+ for (today=monday;today<=sunday;today++)
+ printf("%s = %d \t %s = %d \t %s = %d\n",
+ thedays[today], today,
+ thedays[yesterday(today)], yesterday(today),
+ thedays[tomorrow(today)], tomorrow(today));
+}
+
+days yesterday(days today){
+ return (today+6)%7;
+}
+days tomorrow(days today){
+ return (today+1)%7;
+}
+
+/*
+ The output is:
+
+today yesterday tomorrow
+============================================
+monday = 0 sunday = 6 tuesday = 1
+tuesday = 1 monday = 0 wednesday = 2
+wednesday = 2 tuesday = 1 thursday = 3
+thursday = 3 wednesday = 2 friday = 4
+friday = 4 thursday = 3 saturday = 5
+saturday = 5 friday = 4 sunday = 6
+sunday = 6 saturday = 5 monday = 0
+
+*/
diff --git a/test/aarch64/c/floop.c b/test/aarch64/c/floop.c
new file mode 100644
index 00000000..30270892
--- /dev/null
+++ b/test/aarch64/c/floop.c
@@ -0,0 +1,8 @@
+int main(int x)
+{
+ int y = 4;
+ int s = 23;
+ for(int i = 0; i <= x; i++)
+ y << s;
+ return y;
+}
diff --git a/test/aarch64/c/floor.c b/test/aarch64/c/floor.c
new file mode 100644
index 00000000..33a57af3
--- /dev/null
+++ b/test/aarch64/c/floor.c
@@ -0,0 +1,29 @@
+int main(int n)
+{
+ int x = 1, i;
+
+ /* for positive values */
+ if (n > 0)
+ {
+ for (; x <= n >> 1;)
+ {
+ x = x << 1;
+ }
+ n = x;
+ }
+ /* for negative values */
+ else
+ {
+ n = ~n;
+ n = n + 1;
+ for (; x <= n >> 1;)
+ {
+ x = x << 1;
+ }
+ x = x << 1;
+ x = ~x;
+ x = x + 1;
+ n = x;
+ }
+ return n;
+}
diff --git a/test/aarch64/c/funcs.c b/test/aarch64/c/funcs.c
new file mode 100644
index 00000000..49e610d6
--- /dev/null
+++ b/test/aarch64/c/funcs.c
@@ -0,0 +1,36 @@
+/* funcs.c -- More examples of functions
+ */
+
+#include <stdio.h>
+
+int getint(void); /*It prompts user to enter an integer, which it returns*/
+
+int getmax(int a, int b, int c); /*It returns value of largest of a, b, c*/
+
+/* Main program: Using the various functions */
+int main (void) {
+ int x, y, z;
+
+ x = getint();
+ y = getint();
+ z = getint();
+ printf("The largest of %d, %d, and %d is %d\n", x, y, z, getmax(x,y,z));
+}
+
+int getint(void) {
+ int a;
+
+ printf("Please enter an integer > ");
+ scanf("%d", &a);
+ return(a);
+}
+
+int getmax(int a, int b, int c){
+ int m = a;
+
+ if (m<b)
+ m = b;
+ if (m<c)
+ m = c;
+ return(m);
+}
diff --git a/test/aarch64/c/hello.c b/test/aarch64/c/hello.c
new file mode 100644
index 00000000..0279269e
--- /dev/null
+++ b/test/aarch64/c/hello.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(void) {
+ printf("Hello World!\n");
+ return 0;
+}
diff --git a/test/aarch64/c/if.c b/test/aarch64/c/if.c
new file mode 100644
index 00000000..7d2e249a
--- /dev/null
+++ b/test/aarch64/c/if.c
@@ -0,0 +1,7 @@
+int main(int x)
+{
+ if (x > 27)
+ return 11;
+ else x--;
+ return x;
+}
diff --git a/test/aarch64/c/msb_pos.c b/test/aarch64/c/msb_pos.c
new file mode 100644
index 00000000..f2e7fe09
--- /dev/null
+++ b/test/aarch64/c/msb_pos.c
@@ -0,0 +1,20 @@
+/* Function to find the MSB bit position */
+int main(int n)
+{
+ int i = 0, bit;
+ while (i < 32)
+ {
+ bit = n & 0x80000000;
+ if (bit == -0x80000000)
+ {
+ bit = 1;
+ }
+
+ if (bit == 1)
+ break;
+
+ n = n << 1;
+ i++;
+ }
+ return i;
+}
diff --git a/test/aarch64/c/power2.c b/test/aarch64/c/power2.c
new file mode 100644
index 00000000..64707df9
--- /dev/null
+++ b/test/aarch64/c/power2.c
@@ -0,0 +1,42 @@
+/* power2.c -- Print out powers of 2: 1, 2, 4, 8, .. up to 2^N
+ */
+
+#include <stdio.h>
+#define N 16
+
+int main(void) {
+ int n; /* The current exponent */
+ int val = 1; /* The current power of 2 */
+
+ printf("\t n \t 2^n\n");
+ printf("\t================\n");
+ for (n=0; n<=N; n++) {
+ printf("\t%3d \t %6d\n", n, val);
+ val = 2*val;
+ }
+ return 0;
+}
+
+/* It prints out :
+
+ n 2^n
+ ================
+ 0 1
+ 1 2
+ 2 4
+ 3 8
+ 4 16
+ 5 32
+ 6 64
+ 7 128
+ 8 256
+ 9 512
+ 10 1024
+ 11 2048
+ 12 4096
+ 13 8192
+ 14 16384
+ 15 32768
+ 16 65536
+
+*/
diff --git a/test/aarch64/c/prime.c b/test/aarch64/c/prime.c
new file mode 100644
index 00000000..6c51db32
--- /dev/null
+++ b/test/aarch64/c/prime.c
@@ -0,0 +1,23 @@
+/* prime1.c It prompts the user to enter an integer N. It prints out
+ * if it is a prime or not. If not, it prints out a factor of N.
+ */
+
+#include <stdio.h>
+
+int main(int n) {
+ int i;
+ int flag;
+
+ flag = 1;
+ for (i=2; (i<(n/2)) && flag; ) { /* May be we do not need to test
+ values of i greater than the square root of n? */
+ if ((n % i) == 0) /* If true n is divisible by i */
+ flag = 0;
+ else
+ i++;
+ }
+
+ if (flag)
+ return 1;
+ return 0;
+}
diff --git a/test/aarch64/c/random.c b/test/aarch64/c/random.c
new file mode 100644
index 00000000..50aa5737
--- /dev/null
+++ b/test/aarch64/c/random.c
@@ -0,0 +1,50 @@
+/* Generating random number sequences using the formula (linear congruence)
+ x[k+1] = (a*x[k] + c)mod m
+ where a, c, and m are parameters set by the user and passed as command line
+ parameters together with a seed i.e. x[0]
+ As a simple example try a=7, c=1, m=13, and seed=5
+ A more sophisticated selection would be a=69069, c=0,
+ m=2^32=4294967296, and seed=31
+ It will print out, in a sort of random order, up to m-1 distinct values.
+ Then it loops.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+static long seed = 13;
+static long a;
+static long c;
+static long m;
+
+void random_init(long s) {
+ if (s != 0) seed = s;
+}
+
+long random() {
+ seed = (a*seed + c)%m;
+ return seed;
+ }
+
+int main(int argc, char * argv[]) {
+ if (argc != 5) {
+ printf("usage: %s a, c, m, seed\n", argv[0]);
+ return 1;
+ }
+ a = atoi(argv[1]);
+ c = atoi(argv[2]);
+ m = atoi(argv[3]);
+ long s = atoi(argv[4]);
+ random_init(s);
+ int k;
+ for (k = 0; k < m-1; k++) {
+ printf("%8ld", random());
+ if (k % 8 == 7) { // after 8 elements go to a new line
+ printf("\n");
+ sleep(1); // sleep for a second
+ }
+ }
+ printf("\n");
+ return 0;
+}
diff --git a/test/aarch64/c/simple_op.c b/test/aarch64/c/simple_op.c
new file mode 100644
index 00000000..7c43b081
--- /dev/null
+++ b/test/aarch64/c/simple_op.c
@@ -0,0 +1,8 @@
+int main(int argc, char ** argv)
+{
+ int n, m;
+ n = n + 1;
+ n = n * 7;
+ n / (8 - 2);
+ return n;
+}
diff --git a/test/aarch64/c/wloop.c b/test/aarch64/c/wloop.c
new file mode 100644
index 00000000..5ba67419
--- /dev/null
+++ b/test/aarch64/c/wloop.c
@@ -0,0 +1,8 @@
+int main(int x)
+{
+ int y = 4;
+ int s = 23;
+ while(s < x)
+ y << s;
+ return y;
+}
diff --git a/test/aarch64/gen_tests/asmb_aarch64_gen_test.sh b/test/aarch64/gen_tests/asmb_aarch64_gen_test.sh
new file mode 100755
index 00000000..660ff7aa
--- /dev/null
+++ b/test/aarch64/gen_tests/asmb_aarch64_gen_test.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+CLEAN=0
+WOFF=0
+while getopts ':cw' 'OPTKEY'; do
+ case ${OPTKEY} in
+ c) CLEAN=1;;
+ w) WOFF=1;;
+ esac
+done
+
+DIRS=(
+ ../c/*.c # Special simple tests
+ ../../c/*.c
+ ../../clightgen/*.c
+ ../../compression/*.c
+ ../../cse2/*.c
+
+ # Monniaux test directory
+ ../../monniaux/binary_search/*.c
+ ../../monniaux/complex/*.c
+ #../../monniaux/crypto-algorithms/*.c # Warnings
+ ../../monniaux/cse2/*.c
+ #../../monniaux/des/*.c # Unsupported feature?
+ ../../monniaux/expect/*.c
+ ../../monniaux/fill_buffer/*.c
+ ../../monniaux/genann/*.c
+ #../../monniaux/heptagon_radio_transmitter/*.c # Warnings
+ ../../monniaux/idea/*.c
+ ../../monniaux/jumptable/*.c
+ ../../monniaux/licm/*.c
+ ../../monniaux/longjmp/*.c
+ ../../monniaux/loop/*.c
+ ../../monniaux/lustrev4_lustrec_heater_control/*.c
+ ../../monniaux/lustrev4_lv4_heater_control/*.c
+ ../../monniaux/lustrev4_lv6-en-2cgc_heater_control/*.c
+ #../../monniaux/lustrev6-carlightV2/*.c # Warnings
+ #../../monniaux/lustrev6-convertible-2cgc/*.c # Unsupported feature?
+ ../../monniaux/lustrev6-convertible-en-2cgc/*.c
+ #../../monniaux/lustrev6-convertible/*.c # Warnings
+ ../../monniaux/madd/*.c
+ #../../monniaux/math/*.c # Unsupported feature?
+ ../../monniaux/memcpy/*.c
+ #../../monniaux/micro-bunzip/*.c # Warnings
+ ../../monniaux/moves/*.c
+ ../../monniaux/multithreaded_volatile/*.c
+ ../../monniaux/nand/*.c
+ #../../monniaux/ncompress/*.c # Warnings
+ ../../monniaux/number_theoretic_transform/*.c
+ ../../monniaux/predicated/*.c
+ ../../monniaux/regalloc/*.c
+ ../../monniaux/rotate/*.c
+ ../../monniaux/scheduling/*.c
+ ../../monniaux/send_through/*.c
+ ../../monniaux/tiny-AES-c/*.c
+ ../../monniaux/varargs/*.c
+ ../../monniaux/xor_and_mat/*.c
+ #../../monniaux/zlib-1.2.11/*.c # Warnings
+)
+#FILES=../c/*.c
+CCOMP_BBLOCKS="../../../ccomp -fno-postpass"
+CCOMP_REF="../../../../CompCert_aarch64-ref/ccomp"
+COUNT=0
+
+if [ $WOFF -eq 1 ]
+then
+ CCOMP_BBLOCKS="${CCOMP_BBLOCKS} -w"
+ CCOMP_REF="${CCOMP_REF} -w"
+fi
+
+for files in ${DIRS[@]}
+do
+ for f in $files
+ do
+ BNAME=$(basename -s .c $f)
+ SNAME="$BNAME".s
+ SREFNAME="$BNAME"_ref.s
+ ./$CCOMP_BBLOCKS -S $f -o $SNAME
+ ./$CCOMP_REF -dmach -S $f -o $SREFNAME
+ #diff -I '^//*' <(cut -c-5 $SNAME) <(cut -c-5 $SREFNAME) > /dev/null 2>&1
+ diff -I '^//*' $SNAME $SREFNAME > /dev/null 2>&1
+
+ error=$?
+ if [ $error -eq 0 ]
+ then
+ echo "[$BNAME] OK"
+ COUNT=$((COUNT + 1))
+ elif [ $error -eq 1 ]
+ then
+ echo "[$BNAME] FAIL"
+ diff -I '^//*' -y $SNAME $SREFNAME
+ exit 1
+ else
+ echo "[$BNAME] FAIL"
+ echo "[WARNING] There was something wrong with the diff command !"
+ exit 1
+ fi
+ done
+done
+
+echo "[TOTAL] $COUNT tests PASSED"
+
+if [ $CLEAN -eq 1 ]
+then
+ rm *.s *.mach
+fi
diff --git a/test/aarch64/postpass_tests/postpass_exec_c_test.sh b/test/aarch64/postpass_tests/postpass_exec_c_test.sh
new file mode 100755
index 00000000..73422990
--- /dev/null
+++ b/test/aarch64/postpass_tests/postpass_exec_c_test.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+CLEAN=0
+WOFF=0
+SRC=""
+while getopts ':cwi:' 'OPTKEY'; do
+ case ${OPTKEY} in
+ c) CLEAN=1;;
+ w) WOFF=1;;
+ i) SRC=${OPTARG};;
+ esac
+done
+
+CCOMP="../../../ccomp -static"
+
+if [ $WOFF -eq 1 ]
+then
+ CCOMP="${CCOMP} -w"
+fi
+
+BNAME=$(basename -s .c $SRC)
+SNAME="$BNAME".s
+SREFNAME="$BNAME"_ref.s
+ENAME="$BNAME"
+EREFNAME="$BNAME"_ref
+./$CCOMP -S $SRC -o $SNAME
+./$CCOMP -fno-postpass -S $SRC -o $SREFNAME
+./$CCOMP $SRC -o $ENAME
+./$CCOMP -fno-postpass $SRC -o $EREFNAME
+
+#diff -I '^//*' -y $SNAME $SREFNAME
+
+if [ $CLEAN -eq 1 ]
+then
+ rm $SNAME $SREFNAME $ENAME $EREFNAME
+fi