aboutsummaryrefslogtreecommitdiffstats
path: root/riscV/Asm.v
diff options
context:
space:
mode:
authorSylvain Boulmé <sylvain.boulme@univ-grenoble-alpes.fr>2021-03-23 19:12:19 +0100
committerSylvain Boulmé <sylvain.boulme@univ-grenoble-alpes.fr>2021-03-23 19:12:19 +0100
commitdcb523736e82d72b03fa8d055bf74472dba7345c (patch)
tree71e797c92d45dca509527043d233c51b2ed8fc86 /riscV/Asm.v
parent3e953ef41f736ed5b7db699b1adf21d46cb5b8db (diff)
parent6bf310dd678285dc193798e89fc2c441d8430892 (diff)
downloadcompcert-kvx-dcb523736e82d72b03fa8d055bf74472dba7345c.tar.gz
compcert-kvx-dcb523736e82d72b03fa8d055bf74472dba7345c.zip
Merge branch 'master' into merge_master_8.13.1
PARTIAL MERGE (PARTLY BROKEN). See unsolved conflicts in: aarch64/TO_MERGE and riscV/TO_MERGE WARNING: interface of va_args and assembly sections have changed
Diffstat (limited to 'riscV/Asm.v')
-rw-r--r--riscV/Asm.v1199
1 files changed, 0 insertions, 1199 deletions
diff --git a/riscV/Asm.v b/riscV/Asm.v
deleted file mode 100644
index 5d3518f2..00000000
--- a/riscV/Asm.v
+++ /dev/null
@@ -1,1199 +0,0 @@
-(* *********************************************************************)
-(* *)
-(* The Compcert verified compiler *)
-(* *)
-(* Xavier Leroy, INRIA Paris-Rocquencourt *)
-(* Prashanth Mundkur, SRI International *)
-(* *)
-(* 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. *)
-(* *)
-(* The contributions by Prashanth Mundkur are reused and adapted *)
-(* under the terms of a Contributor License Agreement between *)
-(* SRI International and INRIA. *)
-(* *)
-(* *********************************************************************)
-
-(** Abstract syntax and semantics for RISC-V assembly language. *)
-
-Require Import Coqlib.
-Require Import Maps.
-Require Import AST.
-Require Import Integers.
-Require Import Floats.
-Require Import Values.
-Require Import Memory.
-Require Import Events.
-Require Import Globalenvs.
-Require Import Smallstep.
-Require Import Locations.
-Require Stacklayout.
-Require Import Conventions.
-Require ExtValues.
-
-(** * Abstract syntax *)
-
-(** Integer registers. X0 is treated specially because it always reads
- as zero and is never used as a destination of an instruction. *)
-
-Inductive ireg: Type :=
- | X1: ireg | X2: ireg | X3: ireg | X4: ireg | X5: ireg
- | X6: ireg | X7: ireg | X8: ireg | X9: ireg | X10: ireg
- | X11: ireg | X12: ireg | X13: ireg | X14: ireg | X15: ireg
- | X16: ireg | X17: ireg | X18: ireg | X19: ireg | X20: ireg
- | X21: ireg | X22: ireg | X23: ireg | X24: ireg | X25: ireg
- | X26: ireg | X27: ireg | X28: ireg | X29: ireg | X30: ireg
- | X31: ireg.
-
-Inductive ireg0: Type :=
- | X0: ireg0 | X: ireg -> ireg0.
-
-Coercion X: ireg >-> ireg0.
-
-(** Floating-point registers *)
-
-Inductive freg: Type :=
- | F0: freg | F1: freg | F2: freg | F3: freg
- | F4: freg | F5: freg | F6: freg | F7: freg
- | F8: freg | F9: freg | F10: freg | F11: freg
- | F12: freg | F13: freg | F14: freg | F15: freg
- | F16: freg | F17: freg | F18: freg | F19: freg
- | F20: freg | F21: freg | F22: freg | F23: freg
- | F24: freg | F25: freg | F26: freg | F27: freg
- | F28: freg | F29: freg | F30: freg | F31: freg.
-
-Definition ireg_eq: forall (x y: ireg), {x=y} + {x<>y}.
-Proof. decide equality. Defined.
-
-Definition ireg0_eq: forall (x y: ireg0), {x=y} + {x<>y}.
-Proof. decide equality. apply ireg_eq. Defined.
-
-Lemma freg_eq: forall (x y: freg), {x=y} + {x<>y}.
-Proof. decide equality. Defined.
-
-(** We model the following registers of the RISC-V architecture. *)
-
-Inductive preg: Type :=
- | IR: ireg -> preg (**r integer registers *)
- | FR: freg -> preg (**r double-precision float registers *)
- | PC: preg. (**r program counter *)
-
-Coercion IR: ireg >-> preg.
-Coercion FR: freg >-> preg.
-
-Lemma preg_eq: forall (x y: preg), {x=y} + {x<>y}.
-Proof. decide equality. apply ireg_eq. apply freg_eq. Defined.
-
-Module PregEq.
- Definition t := preg.
- Definition eq := preg_eq.
-End PregEq.
-
-Module Pregmap := EMap(PregEq).
-
-(** Conventional names for stack pointer ([SP]) and return address ([RA]). *)
-
-Notation "'SP'" := X2 (only parsing) : asm.
-Notation "'RA'" := X1 (only parsing) : asm.
-
-(** Offsets for load and store instructions. An offset is either an
- immediate integer or the low part of a symbol. *)
-
-Inductive offset : Type :=
- | Ofsimm (ofs: ptrofs)
- | Ofslow (id: ident) (ofs: ptrofs).
-
-(** The RISC-V instruction set is composed of several subsets. We model
- the "32I" (32-bit integers), "64I" (64-bit integers),
- "M" (multiplication and division),
- "F" (single-precision floating-point)
- and "D" (double-precision floating-point) subsets.
-
- For 32- and 64-bit integer arithmetic, the RISC-V instruction set comprises
- generic integer operations such as ADD that operate over the full width
- of an integer register (either 32 or 64 bit), plus specific instructions
- such as ADDW that normalize their results to signed 32-bit integers.
- Other instructions such as AND work equally well over 32- and 64-bit
- integers, with the convention that 32-bit integers are represented
- sign-extended in 64-bit registers.
-
- This clever design is challenging to formalize in the CompCert value
- model. As a first step, we follow a more traditional approach,
- also used in the x86 port, whereas we have two sets of (pseudo-)
- instructions, one for 32-bit integer arithmetic, with suffix W,
- the other for 64-bit integer arithmetic, with suffix L. The mapping
- to actual instructions is done when printing assembly code, as follows:
- - In 32-bit mode:
- ADDW becomes ADD, ADDL is an error, ANDW becomes AND, ANDL is an error.
- - In 64-bit mode:
- ADDW becomes ADDW, ADDL becomes ADD, ANDW and ANDL both become AND.
-*)
-
-Definition label := positive.
-
-(** A note on immediates: there are various constraints on immediate
- operands to RISC-V instructions. We do not attempt to capture these
- restrictions in the abstract syntax nor in the semantics. The
- assembler will emit an error if immediate operands exceed the
- representable range. Of course, our RISC-V generator (file
- [Asmgen]) is careful to respect this range. *)
-
-Inductive instruction : Type :=
- | Pmv (rd: ireg) (rs: ireg) (**r integer move *)
-
-(** 32-bit integer register-immediate instructions *)
- | Paddiw (rd: ireg) (rs: ireg0) (imm: int) (**r add immediate *)
- | Psltiw (rd: ireg) (rs: ireg0) (imm: int) (**r set-less-than immediate *)
- | Psltiuw (rd: ireg) (rs: ireg0) (imm: int) (**r set-less-than unsigned immediate *)
- | Pandiw (rd: ireg) (rs: ireg0) (imm: int) (**r and immediate *)
- | Poriw (rd: ireg) (rs: ireg0) (imm: int) (**r or immediate *)
- | Pxoriw (rd: ireg) (rs: ireg0) (imm: int) (**r xor immediate *)
- | Pslliw (rd: ireg) (rs: ireg0) (imm: int) (**r shift-left-logical immediate *)
- | Psrliw (rd: ireg) (rs: ireg0) (imm: int) (**r shift-right-logical immediate *)
- | Psraiw (rd: ireg) (rs: ireg0) (imm: int) (**r shift-right-arith immediate *)
- | Pluiw (rd: ireg) (imm: int) (**r load upper-immediate *)
-(** 32-bit integer register-register instructions *)
- | Paddw (rd: ireg) (rs1 rs2: ireg0) (**r integer addition *)
- | Psubw (rd: ireg) (rs1 rs2: ireg0) (**r integer subtraction *)
-
- | Pmulw (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply low *)
- | Pmulhw (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply high signed *)
- | Pmulhuw (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply high unsigned *)
- | Pdivw (rd: ireg) (rs1 rs2: ireg0) (**r integer division *)
- | Pdivuw (rd: ireg) (rs1 rs2: ireg0) (**r unsigned integer division *)
- | Premw (rd: ireg) (rs1 rs2: ireg0) (**r integer remainder *)
- | Premuw (rd: ireg) (rs1 rs2: ireg0) (**r unsigned integer remainder *)
- | Psltw (rd: ireg) (rs1 rs2: ireg0) (**r set-less-than *)
- | Psltuw (rd: ireg) (rs1 rs2: ireg0) (**r set-less-than unsigned *)
- | Pseqw (rd: ireg) (rs1 rs2: ireg0) (**r [rd <- rs1 == rs2] (pseudo) *)
- | Psnew (rd: ireg) (rs1 rs2: ireg0) (**r [rd <- rs1 != rs2] (pseudo) *)
- | Pandw (rd: ireg) (rs1 rs2: ireg0) (**r bitwise and *)
- | Porw (rd: ireg) (rs1 rs2: ireg0) (**r bitwise or *)
- | Pxorw (rd: ireg) (rs1 rs2: ireg0) (**r bitwise xor *)
- | Psllw (rd: ireg) (rs1 rs2: ireg0) (**r shift-left-logical *)
- | Psrlw (rd: ireg) (rs1 rs2: ireg0) (**r shift-right-logical *)
- | Psraw (rd: ireg) (rs1 rs2: ireg0) (**r shift-right-arith *)
-
-(** 64-bit integer register-immediate instructions *)
- | Paddil (rd: ireg) (rs: ireg0) (imm: int64) (**r add immediate *)
- | Psltil (rd: ireg) (rs: ireg0) (imm: int64) (**r set-less-than immediate *)
- | Psltiul (rd: ireg) (rs: ireg0) (imm: int64) (**r set-less-than unsigned immediate *)
- | Pandil (rd: ireg) (rs: ireg0) (imm: int64) (**r and immediate *)
- | Poril (rd: ireg) (rs: ireg0) (imm: int64) (**r or immediate *)
- | Pxoril (rd: ireg) (rs: ireg0) (imm: int64) (**r xor immediate *)
- | Psllil (rd: ireg) (rs: ireg0) (imm: int) (**r shift-left-logical immediate *)
- | Psrlil (rd: ireg) (rs: ireg0) (imm: int) (**r shift-right-logical immediate *)
- | Psrail (rd: ireg) (rs: ireg0) (imm: int) (**r shift-right-arith immediate *)
- | Pluil (rd: ireg) (imm: int64) (**r load upper-immediate *)
-(** 64-bit integer register-register instructions *)
- | Paddl (rd: ireg) (rs1 rs2: ireg0) (**r integer addition *)
- | Psubl (rd: ireg) (rs1 rs2: ireg0) (**r integer subtraction *)
-
- | Pmull (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply low *)
- | Pmulhl (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply high signed *)
- | Pmulhul (rd: ireg) (rs1 rs2: ireg0) (**r integer multiply high unsigned *)
- | Pdivl (rd: ireg) (rs1 rs2: ireg0) (**r integer division *)
- | Pdivul (rd: ireg) (rs1 rs2: ireg0) (**r unsigned integer division *)
- | Preml (rd: ireg) (rs1 rs2: ireg0) (**r integer remainder *)
- | Premul (rd: ireg) (rs1 rs2: ireg0) (**r unsigned integer remainder *)
- | Psltl (rd: ireg) (rs1 rs2: ireg0) (**r set-less-than *)
- | Psltul (rd: ireg) (rs1 rs2: ireg0) (**r set-less-than unsigned *)
- | Pseql (rd: ireg) (rs1 rs2: ireg0) (**r [rd <- rs1 == rs2] (pseudo) *)
- | Psnel (rd: ireg) (rs1 rs2: ireg0) (**r [rd <- rs1 != rs2] (pseudo) *)
- | Pandl (rd: ireg) (rs1 rs2: ireg0) (**r bitwise and *)
- | Porl (rd: ireg) (rs1 rs2: ireg0) (**r bitwise or *)
- | Pxorl (rd: ireg) (rs1 rs2: ireg0) (**r bitwise xor *)
- | Pslll (rd: ireg) (rs1 rs2: ireg0) (**r shift-left-logical *)
- | Psrll (rd: ireg) (rs1 rs2: ireg0) (**r shift-right-logical *)
- | Psral (rd: ireg) (rs1 rs2: ireg0) (**r shift-right-arith *)
-
- | Pcvtl2w (rd: ireg) (rs: ireg0) (**r int64->int32 (pseudo) *)
- | Pcvtw2l (r: ireg) (**r int32 signed -> int64 (pseudo) *)
-
- (* Unconditional jumps. Links are always to X1/RA. *)
- | Pj_l (l: label) (**r jump to label *)
- | Pj_s (symb: ident) (sg: signature) (**r jump to symbol *)
- | Pj_r (r: ireg) (sg: signature) (**r jump register *)
- | Pjal_s (symb: ident) (sg: signature) (**r jump-and-link symbol *)
- | Pjal_r (r: ireg) (sg: signature) (**r jump-and-link register *)
-
- (* Conditional branches, 32-bit comparisons *)
- | Pbeqw (rs1 rs2: ireg0) (l: label) (**r branch-if-equal *)
- | Pbnew (rs1 rs2: ireg0) (l: label) (**r branch-if-not-equal signed *)
- | Pbltw (rs1 rs2: ireg0) (l: label) (**r branch-if-less signed *)
- | Pbltuw (rs1 rs2: ireg0) (l: label) (**r branch-if-less unsigned *)
- | Pbgew (rs1 rs2: ireg0) (l: label) (**r branch-if-greater-or-equal signed *)
- | Pbgeuw (rs1 rs2: ireg0) (l: label) (**r branch-if-greater-or-equal unsigned *)
-
- (* Conditional branches, 64-bit comparisons *)
- | Pbeql (rs1 rs2: ireg0) (l: label) (**r branch-if-equal *)
- | Pbnel (rs1 rs2: ireg0) (l: label) (**r branch-if-not-equal signed *)
- | Pbltl (rs1 rs2: ireg0) (l: label) (**r branch-if-less signed *)
- | Pbltul (rs1 rs2: ireg0) (l: label) (**r branch-if-less unsigned *)
- | Pbgel (rs1 rs2: ireg0) (l: label) (**r branch-if-greater-or-equal signed *)
- | Pbgeul (rs1 rs2: ireg0) (l: label) (**r branch-if-greater-or-equal unsigned *)
-
- (* Loads and stores *)
- | Plb (rd: ireg) (ra: ireg) (ofs: offset) (**r load signed int8 *)
- | Plbu (rd: ireg) (ra: ireg) (ofs: offset) (**r load unsigned int8 *)
- | Plh (rd: ireg) (ra: ireg) (ofs: offset) (**r load signed int16 *)
- | Plhu (rd: ireg) (ra: ireg) (ofs: offset) (**r load unsigned int16 *)
- | Plw (rd: ireg) (ra: ireg) (ofs: offset) (**r load int32 *)
- | Plw_a (rd: ireg) (ra: ireg) (ofs: offset) (**r load any32 *)
- | Pld (rd: ireg) (ra: ireg) (ofs: offset) (**r load int64 *)
- | Pld_a (rd: ireg) (ra: ireg) (ofs: offset) (**r load any64 *)
-
- | Psb (rs: ireg) (ra: ireg) (ofs: offset) (**r store int8 *)
- | Psh (rs: ireg) (ra: ireg) (ofs: offset) (**r store int16 *)
- | Psw (rs: ireg) (ra: ireg) (ofs: offset) (**r store int32 *)
- | Psw_a (rs: ireg) (ra: ireg) (ofs: offset) (**r store any32 *)
- | Psd (rs: ireg) (ra: ireg) (ofs: offset) (**r store int64 *)
- | Psd_a (rs: ireg) (ra: ireg) (ofs: offset) (**r store any64 *)
-
- (* Synchronization *)
- | Pfence (**r fence *)
-
- (* floating point register move *)
- | Pfmv (rd: freg) (rs: freg) (**r move *)
- | Pfmvxs (rd: ireg) (rs: freg) (**r bitwise move FP single to integer register *)
- | Pfmvxd (rd: ireg) (rs: freg) (**r bitwise move FP double to integer register *)
- | Pfmvsx (rd: freg) (rs: ireg) (**r bitwise move integer register to FP single *)
- | Pfmvdx (rd: freg) (rs: ireg) (**r bitwise move integer register to FP double*)
-
- (* 32-bit (single-precision) floating point *)
- | Pfls (rd: freg) (ra: ireg) (ofs: offset) (**r load float *)
- | Pfss (rs: freg) (ra: ireg) (ofs: offset) (**r store float *)
-
- | Pfnegs (rd: freg) (rs: freg) (**r negation *)
- | Pfabss (rd: freg) (rs: freg) (**r absolute value *)
-
- | Pfadds (rd: freg) (rs1 rs2: freg) (**r addition *)
- | Pfsubs (rd: freg) (rs1 rs2: freg) (**r subtraction *)
- | Pfmuls (rd: freg) (rs1 rs2: freg) (**r multiplication *)
- | Pfdivs (rd: freg) (rs1 rs2: freg) (**r division *)
- | Pfmins (rd: freg) (rs1 rs2: freg) (**r minimum *)
- | Pfmaxs (rd: freg) (rs1 rs2: freg) (**r maximum *)
-
- | Pfeqs (rd: ireg) (rs1 rs2: freg) (**r compare equal *)
- | Pflts (rd: ireg) (rs1 rs2: freg) (**r compare less-than *)
- | Pfles (rd: ireg) (rs1 rs2: freg) (**r compare less-than/equal *)
-
- | Pfsqrts (rd: freg) (rs: freg) (**r square-root *)
-
- | Pfmadds (rd: freg) (rs1 rs2 rs3: freg) (**r fused multiply-add *)
- | Pfmsubs (rd: freg) (rs1 rs2 rs3: freg) (**r fused multiply-sub *)
- | Pfnmadds (rd: freg) (rs1 rs2 rs3: freg) (**r fused negated multiply-add *)
- | Pfnmsubs (rd: freg) (rs1 rs2 rs3: freg) (**r fused negated multiply-sub *)
-
- | Pfcvtws (rd: ireg) (rs: freg) (**r float32 -> int32 conversion *)
- | Pfcvtwus (rd: ireg) (rs: freg) (**r float32 -> unsigned int32 conversion *)
- | Pfcvtsw (rd: freg) (rs: ireg0) (**r int32 -> float32 conversion *)
- | Pfcvtswu (rd: freg) (rs: ireg0) (**r unsigned int32 -> float32 conversion *)
-
- | Pfcvtls (rd: ireg) (rs: freg) (**r float32 -> int64 conversion *)
- | Pfcvtlus (rd: ireg) (rs: freg) (**r float32 -> unsigned int64 conversion *)
- | Pfcvtsl (rd: freg) (rs: ireg0) (**r int64 -> float32 conversion *)
- | Pfcvtslu (rd: freg) (rs: ireg0) (**r unsigned int 64-> float32 conversion *)
-
- (* 64-bit (double-precision) floating point *)
- | Pfld (rd: freg) (ra: ireg) (ofs: offset) (**r load 64-bit float *)
- | Pfld_a (rd: freg) (ra: ireg) (ofs: offset) (**r load any64 *)
- | Pfsd (rd: freg) (ra: ireg) (ofs: offset) (**r store 64-bit float *)
- | Pfsd_a (rd: freg) (ra: ireg) (ofs: offset) (**r store any64 *)
-
- | Pfnegd (rd: freg) (rs: freg) (**r negation *)
- | Pfabsd (rd: freg) (rs: freg) (**r absolute value *)
-
- | Pfaddd (rd: freg) (rs1 rs2: freg) (**r addition *)
- | Pfsubd (rd: freg) (rs1 rs2: freg) (**r subtraction *)
- | Pfmuld (rd: freg) (rs1 rs2: freg) (**r multiplication *)
- | Pfdivd (rd: freg) (rs1 rs2: freg) (**r division *)
- | Pfmind (rd: freg) (rs1 rs2: freg) (**r minimum *)
- | Pfmaxd (rd: freg) (rs1 rs2: freg) (**r maximum *)
-
- | Pfeqd (rd: ireg) (rs1 rs2: freg) (**r compare equal *)
- | Pfltd (rd: ireg) (rs1 rs2: freg) (**r compare less-than *)
- | Pfled (rd: ireg) (rs1 rs2: freg) (**r compare less-than/equal *)
-
- | Pfsqrtd (rd: freg) (rs: freg) (**r square-root *)
-
- | Pfmaddd (rd: freg) (rs1 rs2 rs3: freg) (**r fused multiply-add *)
- | Pfmsubd (rd: freg) (rs1 rs2 rs3: freg) (**r fused multiply-sub *)
- | Pfnmaddd (rd: freg) (rs1 rs2 rs3: freg) (**r fused negated multiply-add *)
- | Pfnmsubd (rd: freg) (rs1 rs2 rs3: freg) (**r fused negated multiply-sub *)
-
- | Pfcvtwd (rd: ireg) (rs: freg) (**r float -> int32 conversion *)
- | Pfcvtwud (rd: ireg) (rs: freg) (**r float -> unsigned int32 conversion *)
- | Pfcvtdw (rd: freg) (rs: ireg0) (**r int32 -> float conversion *)
- | Pfcvtdwu (rd: freg) (rs: ireg0) (**r unsigned int32 -> float conversion *)
-
- | Pfcvtld (rd: ireg) (rs: freg) (**r float -> int64 conversion *)
- | Pfcvtlud (rd: ireg) (rs: freg) (**r float -> unsigned int64 conversion *)
- | Pfcvtdl (rd: freg) (rs: ireg0) (**r int64 -> float conversion *)
- | Pfcvtdlu (rd: freg) (rs: ireg0) (**r unsigned int64 -> float conversion *)
-
- | Pfcvtds (rd: freg) (rs: freg) (**r float32 -> float *)
- | Pfcvtsd (rd: freg) (rs: freg) (**r float -> float32 *)
-
- (* Pseudo-instructions *)
- | Pallocframe (sz: Z) (pos: ptrofs) (**r allocate new stack frame *)
- | Pfreeframe (sz: Z) (pos: ptrofs) (**r deallocate stack frame and restore previous frame *)
- | Plabel (lbl: label) (**r define a code label *)
- | Ploadsymbol (rd: ireg) (id: ident) (ofs: ptrofs) (**r load the address of a symbol *)
- | Ploadsymbol_high (rd: ireg) (id: ident) (ofs: ptrofs) (**r load the high part of the address of a symbol *)
- | Ploadli (rd: ireg) (i: int64) (**r load an immediate int64 *)
- | Ploadfi (rd: freg) (f: float) (**r load an immediate float *)
- | Ploadsi (rd: freg) (f: float32) (**r load an immediate single *)
- | Pbtbl (r: ireg) (tbl: list label) (**r N-way branch through a jump table *)
- | Pbuiltin: external_function -> list (builtin_arg preg)
- -> builtin_res preg -> instruction (**r built-in function (pseudo) *)
- | Pselectl (rd: ireg) (rb: ireg0) (rt: ireg0) (rf: ireg0)
- | Pnop : instruction. (**r nop instruction *)
-
-
-(** The pseudo-instructions are the following:
-
-- [Plabel]: define a code label at the current program point.
-
-- [Ploadsymbol]: load the address of a symbol in an integer register.
- Expands to the [la] assembler pseudo-instruction, which does the right
- thing even if we are in PIC mode.
-
-- [Ploadli rd ival]: load an immediate 64-bit integer into an integer
- register rd. Expands to a load from an address in the constant data section,
- using the integer register x31 as temporary:
-<<
- lui x31, %hi(lbl)
- ld rd, %lo(lbl)(x31)
-lbl:
- .quad ival
->>
-
-- [Ploadfi rd fval]: similar to [Ploadli] but loads a double FP constant fval
- into a float register rd.
-
-- [Ploadsi rd fval]: similar to [Ploadli] but loads a single FP constant fval
- into a float register rd.
-
-- [Pallocframe sz pos]: in the formal semantics, this
- pseudo-instruction allocates a memory block with bounds [0] and
- [sz], stores the value of the stack pointer at offset [pos] in this
- block, and sets the stack pointer to the address of the bottom of
- this block.
- In the printed ASM assembly code, this allocation is:
-<<
- mv x30, sp
- sub sp, sp, #sz
- sw x30, #pos(sp)
->>
- This cannot be expressed in our memory model, which does not reflect
- the fact that stack frames are adjacent and allocated/freed
- following a stack discipline.
-
-- [Pfreeframe sz pos]: in the formal semantics, this pseudo-instruction
- reads the word at [pos] of the block pointed by the stack pointer,
- frees this block, and sets the stack pointer to the value read.
- In the printed ASM assembly code, this freeing is just an increment of [sp]:
-<<
- add sp, sp, #sz
->>
- Again, our memory model cannot comprehend that this operation
- frees (logically) the current stack frame.
-
-- [Pbtbl reg table]: this is a N-way branch, implemented via a jump table
- as follows:
-<<
- la x31, table
- add x31, x31, reg
- jr x31
-table: .long table[0], table[1], ...
->>
- Note that [reg] contains 4 times the index of the desired table entry.
-
-- [Pseq rd rs1 rs2]: since unsigned comparisons have particular
- semantics for pointers, we cannot encode equality directly using
- xor/sub etc, which have only integer semantics.
-<<
- xor rd, rs1, rs2
- sltiu rd, rd, 1
->>
- The [xor] is omitted if one of [rs1] and [rs2] is [x0].
-
-- [Psne rd rs1 rs2]: similarly for unsigned inequality.
-<<
- xor rd, rs1, rs2
- sltu rd, x0, rd
->>
-*)
-
-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.
-
-(** * Operational semantics *)
-
-(** The semantics operates over a single mapping from registers
- (type [preg]) to values. We maintain
- the convention that integer registers are mapped to values of
- type [Tint] or [Tlong] (in 64 bit mode),
- and float registers to values of type [Tsingle] or [Tfloat]. *)
-
-Definition regset := Pregmap.t val.
-Definition genv := Genv.t fundef unit.
-
-Definition get0w (rs: regset) (r: ireg0) : val :=
- match r with
- | X0 => Vint Int.zero
- | X r => rs r
- end.
-
-Definition get0l (rs: regset) (r: ireg0) : val :=
- match r with
- | X0 => Vlong Int64.zero
- | X r => rs r
- end.
-
-Notation "a # b" := (a b) (at level 1, only parsing) : asm.
-Notation "a ## b" := (get0w a b) (at level 1) : asm.
-Notation "a ### b" := (get0l a b) (at level 1) : asm.
-Notation "a # b <- c" := (Pregmap.set b c a) (at level 1, b at next level) : asm.
-
-Open Scope asm.
-
-(** Undefining some registers *)
-
-Fixpoint undef_regs (l: list preg) (rs: regset) : regset :=
- match l with
- | nil => rs
- | r :: l' => undef_regs l' (rs#r <- Vundef)
- end.
-
-(** Assigning a register pair *)
-
-Definition set_pair (p: rpair preg) (v: val) (rs: regset) : regset :=
- match p with
- | One r => rs#r <- v
- | Twolong rhi rlo => rs#rhi <- (Val.hiword v) #rlo <- (Val.loword v)
- end.
-
-(** Assigning multiple registers *)
-
-Fixpoint set_regs (rl: list preg) (vl: list val) (rs: regset) : regset :=
- match rl, vl with
- | r1 :: rl', v1 :: vl' => set_regs rl' vl' (rs#r1 <- v1)
- | _, _ => rs
- end.
-
-(** Assigning the result of a builtin *)
-
-Fixpoint set_res (res: builtin_res preg) (v: val) (rs: regset) : regset :=
- match res with
- | BR r => rs#r <- v
- | BR_none => rs
- | BR_splitlong hi lo => set_res lo (Val.loword v) (set_res hi (Val.hiword v) rs)
- end.
-
-Section RELSEM.
-
-(** 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.
- case (peq lbl lbl0); intro; 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 + 1) else label_pos lbl (pos + 1) c'
- end.
-
-Variable ge: genv.
-
-(** The two functions below axiomatize how the linker processes
- symbolic references [symbol + offset)] and splits their
- actual values into a 20-bit high part [%hi(symbol + offset)] and
- a 12-bit low part [%lo(symbol + offset)]. *)
-
-Parameter low_half: genv -> ident -> ptrofs -> ptrofs.
-Parameter high_half: genv -> ident -> ptrofs -> val.
-
-(** The fundamental property of these operations is that, when applied
- to the address of a symbol, their results can be recombined by
- addition, rebuilding the original address. *)
-
-Axiom low_high_half:
- forall id ofs,
- Val.offset_ptr (high_half ge id ofs) (low_half ge id ofs) = Genv.symbol_address ge id ofs.
-
-(** 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. *)
-
-Inductive outcome: Type :=
- | Next: regset -> mem -> outcome
- | Stuck: outcome.
-
-(** Manipulations over the [PC] register: continuing with the next
- instruction ([nextinstr]) or branching to a label ([goto_label]). *)
-
-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.
-
-(** Auxiliaries for memory accesses *)
-
-Definition eval_offset (ofs: offset) : ptrofs :=
- match ofs with
- | Ofsimm n => n
- | Ofslow id delta => low_half ge id delta
- end.
-
-Definition exec_load (chunk: memory_chunk) (rs: regset) (m: mem)
- (d: preg) (a: ireg) (ofs: offset) :=
- match Mem.loadv chunk m (Val.offset_ptr (rs a) (eval_offset ofs)) with
- | None => Stuck
- | Some v => Next (nextinstr (rs#d <- v)) m
- end.
-
-Definition exec_store (chunk: memory_chunk) (rs: regset) (m: mem)
- (s: preg) (a: ireg) (ofs: offset) :=
- match Mem.storev chunk m (Val.offset_ptr (rs a) (eval_offset ofs)) (rs s) with
- | None => Stuck
- | Some m' => Next (nextinstr rs) m'
- end.
-
-(** Evaluating a branch *)
-
-Definition eval_branch (f: function) (l: label) (rs: regset) (m: mem) (res: option bool) : outcome :=
- match res with
- | Some true => goto_label f l rs m
- | Some false => Next (nextinstr rs) m
- | None => Stuck
- end.
-
-(** Execution of a single instruction [i] in initial state [rs] and
- [m]. Return updated state. For instructions that correspond to
- actual RISC-V instructions, the cases are straightforward
- transliterations of the informal descriptions given in the RISC-V
- user-mode specification. 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 RISC-V 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
- | Pmv d s =>
- Next (nextinstr (rs#d <- (rs#s))) m
-
-(** 32-bit integer register-immediate instructions *)
- | Paddiw d s i =>
- Next (nextinstr (rs#d <- (Val.add rs##s (Vint i)))) m
- | Psltiw d s i =>
- Next (nextinstr (rs#d <- (Val.cmp Clt rs##s (Vint i)))) m
- | Psltiuw d s i =>
- Next (nextinstr (rs#d <- (Val.cmpu (Mem.valid_pointer m) Clt rs##s (Vint i)))) m
- | Pandiw d s i =>
- Next (nextinstr (rs#d <- (Val.and rs##s (Vint i)))) m
- | Poriw d s i =>
- Next (nextinstr (rs#d <- (Val.or rs##s (Vint i)))) m
- | Pxoriw d s i =>
- Next (nextinstr (rs#d <- (Val.xor rs##s (Vint i)))) m
- | Pslliw d s i =>
- Next (nextinstr (rs#d <- (Val.shl rs##s (Vint i)))) m
- | Psrliw d s i =>
- Next (nextinstr (rs#d <- (Val.shru rs##s (Vint i)))) m
- | Psraiw d s i =>
- Next (nextinstr (rs#d <- (Val.shr rs##s (Vint i)))) m
- | Pluiw d i =>
- Next (nextinstr (rs#d <- (Vint (Int.shl i (Int.repr 12))))) m
-
-(** 32-bit integer register-register instructions *)
- | Paddw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.add rs##s1 rs##s2))) m
- | Psubw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.sub rs##s1 rs##s2))) m
- | Pmulw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mul rs##s1 rs##s2))) m
- | Pmulhw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mulhs rs##s1 rs##s2))) m
- | Pmulhuw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mulhu rs##s1 rs##s2))) m
- | Pdivw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.divs rs##s1 rs##s2)))) m
- | Pdivuw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.divu rs##s1 rs##s2)))) m
- | Premw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.mods rs##s1 rs##s2)))) m
- | Premuw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.modu rs##s1 rs##s2)))) m
- | Psltw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmp Clt rs##s1 rs##s2))) m
- | Psltuw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpu (Mem.valid_pointer m) Clt rs##s1 rs##s2))) m
- | Pseqw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpu (Mem.valid_pointer m) Ceq rs##s1 rs##s2))) m
- | Psnew d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpu (Mem.valid_pointer m) Cne rs##s1 rs##s2))) m
- | Pandw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.and rs##s1 rs##s2))) m
- | Porw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.or rs##s1 rs##s2))) m
- | Pxorw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.xor rs##s1 rs##s2))) m
- | Psllw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shl rs##s1 rs##s2))) m
- | Psrlw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shru rs##s1 rs##s2))) m
- | Psraw d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shr rs##s1 rs##s2))) m
-
-(** 64-bit integer register-immediate instructions *)
- | Paddil d s i =>
- Next (nextinstr (rs#d <- (Val.addl rs###s (Vlong i)))) m
- | Psltil d s i =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmpl Clt rs###s (Vlong i))))) m
- | Psltiul d s i =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt rs###s (Vlong i))))) m
- | Pandil d s i =>
- Next (nextinstr (rs#d <- (Val.andl rs###s (Vlong i)))) m
- | Poril d s i =>
- Next (nextinstr (rs#d <- (Val.orl rs###s (Vlong i)))) m
- | Pxoril d s i =>
- Next (nextinstr (rs#d <- (Val.xorl rs###s (Vlong i)))) m
- | Psllil d s i =>
- Next (nextinstr (rs#d <- (Val.shll rs###s (Vint i)))) m
- | Psrlil d s i =>
- Next (nextinstr (rs#d <- (Val.shrlu rs###s (Vint i)))) m
- | Psrail d s i =>
- Next (nextinstr (rs#d <- (Val.shrl rs###s (Vint i)))) m
- | Pluil d i =>
- Next (nextinstr (rs#d <- (Vlong (Int64.sign_ext 32 (Int64.shl i (Int64.repr 12)))))) m
-
-(** 64-bit integer register-register instructions *)
- | Paddl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.addl rs###s1 rs###s2))) m
- | Psubl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.subl rs###s1 rs###s2))) m
- | Pmull d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mull rs###s1 rs###s2))) m
- | Pmulhl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mullhs rs###s1 rs###s2))) m
- | Pmulhul d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mullhu rs###s1 rs###s2))) m
- | Pdivl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.divls rs###s1 rs###s2)))) m
- | Pdivul d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.divlu rs###s1 rs###s2)))) m
- | Preml d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.modls rs###s1 rs###s2)))) m
- | Premul d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.modlu rs###s1 rs###s2)))) m
- | Psltl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmpl Clt rs###s1 rs###s2)))) m
- | Psltul d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Clt rs###s1 rs###s2)))) m
- | Pseql d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Ceq rs###s1 rs###s2)))) m
- | Psnel d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.cmplu (Mem.valid_pointer m) Cne rs###s1 rs###s2)))) m
- | Pandl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.andl rs###s1 rs###s2))) m
- | Porl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.orl rs###s1 rs###s2))) m
- | Pxorl d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.xorl rs###s1 rs###s2))) m
- | Pslll d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shll rs###s1 rs###s2))) m
- | Psrll d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shrlu rs###s1 rs###s2))) m
- | Psral d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.shrl rs###s1 rs###s2))) m
-
- | Pcvtl2w d s =>
- Next (nextinstr (rs#d <- (Val.loword rs##s))) m
- | Pcvtw2l r =>
- Next (nextinstr (rs#r <- (Val.longofint rs#r))) m
-
-(** Unconditional jumps. Links are always to X1/RA. *)
- | Pj_l l =>
- goto_label f l rs m
- | Pj_s s sg =>
- Next (rs#PC <- (Genv.symbol_address ge s Ptrofs.zero)) m
- | Pj_r r sg =>
- Next (rs#PC <- (rs#r)) m
- | Pjal_s s sg =>
- Next (rs#PC <- (Genv.symbol_address ge s Ptrofs.zero)
- #RA <- (Val.offset_ptr rs#PC Ptrofs.one)
- ) m
- | Pjal_r r sg =>
- Next (rs#PC <- (rs#r)
- #RA <- (Val.offset_ptr rs#PC Ptrofs.one)
- ) m
-(** Conditional branches, 32-bit comparisons *)
- | Pbeqw s1 s2 l =>
- eval_branch f l rs m (Val.cmpu_bool (Mem.valid_pointer m) Ceq rs##s1 rs##s2)
- | Pbnew s1 s2 l =>
- eval_branch f l rs m (Val.cmpu_bool (Mem.valid_pointer m) Cne rs##s1 rs##s2)
- | Pbltw s1 s2 l =>
- eval_branch f l rs m (Val.cmp_bool Clt rs##s1 rs##s2)
- | Pbltuw s1 s2 l =>
- eval_branch f l rs m (Val.cmpu_bool (Mem.valid_pointer m) Clt rs##s1 rs##s2)
- | Pbgew s1 s2 l =>
- eval_branch f l rs m (Val.cmp_bool Cge rs##s1 rs##s2)
- | Pbgeuw s1 s2 l =>
- eval_branch f l rs m (Val.cmpu_bool (Mem.valid_pointer m) Cge rs##s1 rs##s2)
-
-(** Conditional branches, 64-bit comparisons *)
- | Pbeql s1 s2 l =>
- eval_branch f l rs m (Val.cmplu_bool (Mem.valid_pointer m) Ceq rs###s1 rs###s2)
- | Pbnel s1 s2 l =>
- eval_branch f l rs m (Val.cmplu_bool (Mem.valid_pointer m) Cne rs###s1 rs###s2)
- | Pbltl s1 s2 l =>
- eval_branch f l rs m (Val.cmpl_bool Clt rs###s1 rs###s2)
- | Pbltul s1 s2 l =>
- eval_branch f l rs m (Val.cmplu_bool (Mem.valid_pointer m) Clt rs###s1 rs###s2)
- | Pbgel s1 s2 l =>
- eval_branch f l rs m (Val.cmpl_bool Cge rs###s1 rs###s2)
- | Pbgeul s1 s2 l =>
- eval_branch f l rs m (Val.cmplu_bool (Mem.valid_pointer m) Cge rs###s1 rs###s2)
-
-(** Loads and stores *)
- | Plb d a ofs =>
- exec_load Mint8signed rs m d a ofs
- | Plbu d a ofs =>
- exec_load Mint8unsigned rs m d a ofs
- | Plh d a ofs =>
- exec_load Mint16signed rs m d a ofs
- | Plhu d a ofs =>
- exec_load Mint16unsigned rs m d a ofs
- | Plw d a ofs =>
- exec_load Mint32 rs m d a ofs
- | Plw_a d a ofs =>
- exec_load Many32 rs m d a ofs
- | Pld d a ofs =>
- exec_load Mint64 rs m d a ofs
- | Pld_a d a ofs =>
- exec_load Many64 rs m d a ofs
- | Psb s a ofs =>
- exec_store Mint8unsigned rs m s a ofs
- | Psh s a ofs =>
- exec_store Mint16unsigned rs m s a ofs
- | Psw s a ofs =>
- exec_store Mint32 rs m s a ofs
- | Psw_a s a ofs =>
- exec_store Many32 rs m s a ofs
- | Psd s a ofs =>
- exec_store Mint64 rs m s a ofs
- | Psd_a s a ofs =>
- exec_store Many64 rs m s a ofs
-
-(** Floating point register move *)
- | Pfmv d s =>
- Next (nextinstr (rs#d <- (rs#s))) m
-
-(** 32-bit (single-precision) floating point *)
- | Pfls d a ofs =>
- exec_load Mfloat32 rs m d a ofs
- | Pfss s a ofs =>
- exec_store Mfloat32 rs m s a ofs
-
- | Pfnegs d s =>
- Next (nextinstr (rs#d <- (Val.negfs rs#s))) m
- | Pfabss d s =>
- Next (nextinstr (rs#d <- (Val.absfs rs#s))) m
-
- | Pfadds d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.addfs rs#s1 rs#s2))) m
- | Pfsubs d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.subfs rs#s1 rs#s2))) m
- | Pfmuls d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mulfs rs#s1 rs#s2))) m
- | Pfdivs d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.divfs rs#s1 rs#s2))) m
- | Pfeqs d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpfs Ceq rs#s1 rs#s2))) m
- | Pflts d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpfs Clt rs#s1 rs#s2))) m
- | Pfles d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpfs Cle rs#s1 rs#s2))) m
-
- | Pfcvtws d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.intofsingle rs#s)))) m
- | Pfcvtwus d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.intuofsingle rs#s)))) m
- | Pfcvtsw d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.singleofint rs##s)))) m
- | Pfcvtswu d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.singleofintu rs##s)))) m
-
- | Pfcvtls d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.longofsingle rs#s)))) m
- | Pfcvtlus d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.longuofsingle rs#s)))) m
- | Pfcvtsl d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.singleoflong rs###s)))) m
- | Pfcvtslu d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.singleoflongu rs###s)))) m
-
-(** 64-bit (double-precision) floating point *)
- | Pfld d a ofs =>
- exec_load Mfloat64 rs m d a ofs
- | Pfld_a d a ofs =>
- exec_load Many64 rs m d a ofs
- | Pfsd s a ofs =>
- exec_store Mfloat64 rs m s a ofs
- | Pfsd_a s a ofs =>
- exec_store Many64 rs m s a ofs
-
- | Pfnegd d s =>
- Next (nextinstr (rs#d <- (Val.negf rs#s))) m
- | Pfabsd d s =>
- Next (nextinstr (rs#d <- (Val.absf rs#s))) m
-
- | Pfaddd d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.addf rs#s1 rs#s2))) m
- | Pfsubd d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.subf rs#s1 rs#s2))) m
- | Pfmuld d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.mulf rs#s1 rs#s2))) m
- | Pfdivd d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.divf rs#s1 rs#s2))) m
- | Pfeqd d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpf Ceq rs#s1 rs#s2))) m
- | Pfltd d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpf Clt rs#s1 rs#s2))) m
- | Pfled d s1 s2 =>
- Next (nextinstr (rs#d <- (Val.cmpf Cle rs#s1 rs#s2))) m
-
- | Pfcvtwd d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.intoffloat rs#s)))) m
- | Pfcvtwud d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.intuoffloat rs#s)))) m
- | Pfcvtdw d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.floatofint rs##s)))) m
- | Pfcvtdwu d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.floatofintu rs##s)))) m
-
- | Pfcvtld d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.longoffloat rs#s)))) m
- | Pfcvtlud d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.longuoffloat rs#s)))) m
- | Pfcvtdl d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.floatoflong rs###s)))) m
- | Pfcvtdlu d s =>
- Next (nextinstr (rs#d <- (Val.maketotal (Val.floatoflongu rs###s)))) m
-
- | Pfcvtds d s =>
- Next (nextinstr (rs#d <- (Val.floatofsingle rs#s))) m
- | Pfcvtsd d s =>
- Next (nextinstr (rs#d <- (Val.singleoffloat rs#s))) m
-
- | Pfmvxs d s =>
- Next (nextinstr (rs#d <- (ExtValues.bits_of_single rs#s))) m
- | Pfmvxd d s =>
- Next (nextinstr (rs#d <- (ExtValues.bits_of_float rs#s))) m
-
- | Pfmvsx d s =>
- Next (nextinstr (rs#d <- (ExtValues.single_of_bits rs#s))) m
- | Pfmvdx d s =>
- Next (nextinstr (rs#d <- (ExtValues.float_of_bits rs#s))) 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 Mptr m1 (Val.offset_ptr sp pos) rs#SP with
- | None => Stuck
- | Some m2 => Next (nextinstr (rs #X30 <- (rs SP) #SP <- sp #X31 <- Vundef)) m2
- end
- | Pfreeframe sz pos =>
- match Mem.loadv Mptr 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 #X31 <- Vundef)) m'
- end
- | _ => Stuck
- end
- end
- | Pselectl rd rb rt rf =>
- Next (nextinstr (rs#rd <- (ExtValues.select01_long
- (rs###rb) (rs###rt) (rs###rf)))
- #X31 <- Vundef) m
- | Plabel lbl =>
- Next (nextinstr rs) m
- | Ploadsymbol rd s ofs =>
- Next (nextinstr (rs#rd <- (Genv.symbol_address ge s ofs))) m
- | Ploadsymbol_high rd s ofs =>
- Next (nextinstr (rs#rd <- (high_half ge s ofs))) m
- | Ploadli rd i =>
- Next (nextinstr (rs#X31 <- Vundef #rd <- (Vlong i))) m
- | Ploadfi rd f =>
- Next (nextinstr (rs#X31 <- Vundef #rd <- (Vfloat f))) m
- | Ploadsi rd f =>
- Next (nextinstr (rs#X31 <- Vundef #rd <- (Vsingle f))) m
- | Pbtbl r tbl =>
- match rs r with
- | Vint n =>
- match list_nth_z tbl (Int.unsigned n) with
- | None => Stuck
- | Some lbl => goto_label f lbl (rs#X5 <- Vundef #X31 <- 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. *)
- | Pfence
-
- | Pfmins _ _ _
- | Pfmaxs _ _ _
- | Pfsqrts _ _
- | Pfmadds _ _ _ _
- | Pfmsubs _ _ _ _
- | Pfnmadds _ _ _ _
- | Pfnmsubs _ _ _ _
-
- | Pfmind _ _ _
- | Pfmaxd _ _ _
- | Pfsqrtd _ _
- | Pfmaddd _ _ _ _
- | Pfmsubd _ _ _ _
- | Pfnmaddd _ _ _ _
- | Pfnmsubd _ _ _ _
- | Pnop
- => Stuck
- end.
-
-(** Translation of the LTL/Linear/Mach view of machine registers to
- the RISC-V view. Note that no LTL register maps to [X31]. This
- register is reserved as temporary, to be used by the generated RV32G
- code. *)
-
-Definition preg_of (r: mreg) : preg :=
- match r with
- | R5 => X5 | R6 => X6 | R7 => X7
- | R8 => X8 | R9 => X9 | R10 => X10 | R11 => X11
- | R12 => X12 | R13 => X13 | R14 => X14 | R15 => X15
- | R16 => X16 | R17 => X17 | R18 => X18 | R19 => X19
- | R20 => X20 | R21 => X21 | R22 => X22 | R23 => X23
- | R24 => X24 | R25 => X25 | R26 => X26 | R27 => X27
- | R28 => X28 | R29 => X29 | R30 => X30
-
- | Machregs.F0 => F0 | Machregs.F1 => F1 | Machregs.F2 => F2 | Machregs.F3 => F3
- | Machregs.F4 => F4 | Machregs.F5 => F5 | Machregs.F6 => F6 | Machregs.F7 => F7
- | Machregs.F8 => F8 | Machregs.F9 => F9 | Machregs.F10 => F10 | Machregs.F11 => F11
- | Machregs.F12 => F12 | Machregs.F13 => F13 | Machregs.F14 => F14 | Machregs.F15 => F15
- | Machregs.F16 => F16 | Machregs.F17 => F17 | Machregs.F18 => F18 | Machregs.F19 => F19
- | Machregs.F20 => F20 | Machregs.F21 => F21 | Machregs.F22 => F22 | Machregs.F23 => F23
- | Machregs.F24 => F24 | Machregs.F25 => F25 | Machregs.F26 => F26 | Machregs.F27 => F27
- | Machregs.F28 => F28 | Machregs.F29 => F29 | Machregs.F30 => F30 | Machregs.F31 => F31
- 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 RISC-V 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 (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',
- rs PC = Vptr b ofs ->
- Genv.find_funct_ptr ge b = Some (Internal f) ->
- find_instr (Ptrofs.unsigned ofs) (fn_code f) = Some i ->
- exec_instr f i rs m = Next rs' m' ->
- step (State rs m) E0 (State rs' m')
- | exec_step_builtin:
- forall b ofs f ef args res rs m vargs t vres 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 (Pbuiltin ef args res) ->
- eval_builtin_args ge rs (rs SP) m args vargs ->
- external_call ef ge vargs m t vres m' ->
- rs' = nextinstr
- (set_res res vres
- (undef_regs (map preg_of (destroyed_by_builtin ef))
- (rs#X31 <- Vundef))) ->
- 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,
- let ge := Genv.globalenv p in
- let rs0 :=
- (Pregmap.init Vundef)
- # PC <- (Genv.symbol_address ge p.(prog_main) Ptrofs.zero)
- # SP <- Vnullptr
- # RA <- Vnullptr in
- Genv.init_mem p = Some m0 ->
- initial_state p (State rs0 m0).
-
-Inductive final_state: state -> int -> Prop :=
- | final_state_intro: forall rs m r,
- rs PC = Vnullptr ->
- rs X10 = Vint r ->
- final_state (State rs m) r.
-
-Definition semantics (p: program) :=
- Semantics step (initial_state p) final_state (Genv.globalenv p).
-
-(** Determinacy of the [Asm] semantics. *)
-
-Remark extcall_arguments_determ:
- forall rs m sg args1 args2,
- extcall_arguments rs m sg args1 -> extcall_arguments rs m sg args2 -> args1 = args2.
-Proof.
- intros until m.
- assert (A: forall l v1 v2,
- extcall_arg rs m l v1 -> extcall_arg rs m l v2 -> v1 = v2).
- { intros. inv H; inv H0; congruence. }
- assert (B: forall p v1 v2,
- extcall_arg_pair rs m p v1 -> extcall_arg_pair rs m p v2 -> v1 = v2).
- { intros. inv H; inv H0.
- eapply A; eauto.
- f_equal; eapply A; eauto. }
- assert (C: forall ll vl1, list_forall2 (extcall_arg_pair rs m) ll vl1 ->
- forall vl2, list_forall2 (extcall_arg_pair rs m) ll vl2 -> vl1 = vl2).
- {
- induction 1; intros vl2 EA; inv EA.
- auto.
- f_equal; eauto. }
- intros. eapply C; eauto.
-Qed.
-
-Lemma semantics_determinate: forall p, determinate (semantics p).
-Proof.
-Ltac Equalities :=
- match goal with
- | [ H1: ?a = ?b, H2: ?a = ?c |- _ ] =>
- rewrite H1 in H2; inv H2; Equalities
- | _ => idtac
- end.
- intros; constructor; simpl; intros.
-- (* determ *)
- inv H; inv H0; Equalities.
- split. constructor. auto.
- discriminate.
- discriminate.
- assert (vargs0 = vargs) by (eapply eval_builtin_args_determ; eauto). subst vargs0.
- exploit external_call_determ. eexact H5. eexact H11. intros [A B].
- split. auto. intros. destruct B; auto. subst. auto.
- assert (args0 = args) by (eapply extcall_arguments_determ; eauto). subst args0.
- exploit external_call_determ. eexact H3. eexact H8. intros [A B].
- split. auto. intros. destruct B; auto. subst. auto.
-- (* trace length *)
- red; intros. inv H; simpl.
- omega.
- eapply external_call_trace_length; eauto.
- eapply external_call_trace_length; eauto.
-- (* initial states *)
- inv H; inv H0. f_equal. congruence.
-- (* final no step *)
- assert (NOTNULL: forall b ofs, Vnullptr <> Vptr b ofs).
- { intros; unfold Vnullptr; destruct Archi.ptr64; congruence. }
- inv H. unfold Vzero in H0. red; intros; red; intros.
- inv H; rewrite H0 in *; eelim NOTNULL; eauto.
-- (* final states *)
- inv H; inv H0. congruence.
-Qed.
-
-(** Classification functions for processor registers (used in Asmgenproof). *)
-
-Definition data_preg (r: preg) : bool :=
- match r with
- | IR RA => false
- | IR X31 => false
- | IR _ => true
- | FR _ => true
- | PC => false
- end.