diff --git a/arch/ext/Zdinx.yaml b/arch/ext/Zdinx.yaml new file mode 100644 index 000000000..950d3f8bc --- /dev/null +++ b/arch/ext/Zdinx.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Zdinx +long_name: Double-precision floating-point instructions using integer registers +description: + - id: ext-zdinx-instructions + normative: true + text: | + The Zdinx extension adds all of the instructions that the D extension adds, except for the + transfer instructions FLD, FSD, FMV.D.X, FMV.X.D, C.FLD[SP], and C.FSD[SP]. + + - id: ext-zdinx-semantics + normative: true + text: | + The Zdinx variants of these D-extension instructions have the same semantics, except that whenever + such an instruction would have accessed an f register, it instead accesses the x register with the + same number. + + - id: ext-zdinx-rv32regpair + normative: true + text: | + Double-precision operands in RV32Zdinx are held in aligned x-register pairs, i.e., register + numbers must be even. Use of misaligned (odd-numbered) registers for double-width + floating-point operands is reserved. + when(): return MXLEN == 32; + + - id: ext-zdinx-rv32endianness + normative: true + text: | + Regardless of endianness, the lower-numbered register holds the low-order bits, and the + higher-numbered register holds the high-order bits: e.g., bits 31:0 of a double-precision + operand in RV32Zdinx might be held in register x14, with bits 63:32 of that operand held + in x15. + when(): return MXLEN == 32; + + - id: ext-zdinx-rv32x0 + normative: true + text: | + When a double-width floating-point result is written to x0, the entire write takes no effect: + e.g., for RV32Zdinx, writing a double-precision result to x0 does not cause x1 to be written. + when(): return MXLEN == 32; + + - id: ext-zdinx-rv32x1 + normative: true + text: | + When x0 is used as a double-width floating-point operand, the entire operand is zero—i.e., + x1 is not accessed. + when(): return MXLEN == 32; + + - id: ext-zdinx-rv32mempair + normative: false + text: | + Load-pair and store-pair instructions are not provided, so transferring double-precision + operands in RV32Zdinx from or to memory requires two loads or stores. + Register moves need only a single FSGNJ.D instruction, however. + when(): return MXLEN == 32; + +type: unprivileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: Zfinx diff --git a/arch/ext/Zfh.yaml b/arch/ext/Zfh.yaml index 6e931bfc6..c48b03cb3 100644 --- a/arch/ext/Zfh.yaml +++ b/arch/ext/Zfh.yaml @@ -16,3 +16,4 @@ versions: - version: "1.0.0" state: ratified ratification_date: null + requires: F diff --git a/arch/ext/Zfinx.yaml b/arch/ext/Zfinx.yaml new file mode 100644 index 000000000..bd63da21a --- /dev/null +++ b/arch/ext/Zfinx.yaml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Zfinx +long_name: Single-precision floating-point instructions using integer registers +description: + - id: ext-zfinx-instructions + normative: true + text: | + The Zfinx extension adds all of the instructions that the F extension adds, except for the + transfer instructions FLW, FSW, FMV.W.X, FMV.X.W, C.FLW[SP], and C.FSW[SP]. + + - id: ext-zfinx-semantics + normative: true + text: | + The Zfinx variants of these F-extension instructions have the same semantics, except that + whenever such an instruction would have accessed an f register, it instead accesses the + x register with the same number. + +type: unprivileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: Zicsr +conflicts: F diff --git a/arch/ext/Zhinx.yaml b/arch/ext/Zhinx.yaml index 22c969d93..79e0c4156 100644 --- a/arch/ext/Zhinx.yaml +++ b/arch/ext/Zhinx.yaml @@ -4,17 +4,23 @@ $schema: "ext_schema.json#" kind: extension name: Zhinx long_name: Half-precision floating-point instructions using integer registers -description: | - The Zhinx extension provides analogous half-precision floating-point instructions. The Zhinx extension - depends upon the Zfinx extension. - The Zhinx extension adds all of the instructions that the Zfh extension adds, except for the transfer - instructions FLH, FSH, FMV.H.X, and FMV.X.H. - The Zhinx variants of these Zfh-extension instructions have the same semantics, except that whenever - such an instruction would have accessed an f register, it instead accesses the x register with the same - number. +description: + - id: ext-zhinx-instructions + normative: true + text: | + The Zhinx extension adds all of the instructions that the Zfh extension adds, except for the + transfer instructions FLH, FSH, FMV.H.X, and FMV.X.H. + + - id: ext-zhinx-semantics + normative: true + text: | + The Zhinx variants of these Zfh-extension instructions have the same semantics, except that + whenever such an instruction would have accessed an f register, it instead accesses the x + register with the same number. type: unprivileged versions: - version: "1.0.0" state: ratified ratification_date: 2021-11 + requires: Zfinx diff --git a/arch/ext/Zhinxmin.yaml b/arch/ext/Zhinxmin.yaml new file mode 100644 index 000000000..10dd8b7cf --- /dev/null +++ b/arch/ext/Zhinxmin.yaml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=../../schemas/ext_schema.json + +$schema: "ext_schema.json#" +kind: extension +name: Zhinxmin +long_name: Minimal support for half-precision floating-point instructions using integer registers +description: + - id: ext-zhinxmin-instructions + normative: true + text: | + The Zhinxmin extension includes the following instructions from the Zhinx extension: + FCVT.S.H and FCVT.H.S. + when(): return !implemented?(Zdinx); + + - id: ext-zhinxmin-instructions-with-zdinx + normative: true + text: | + The Zhinxmin extension includes the following instructions from the Zhinx extension: + FCVT.S.H, FCVT.H.S, FCVT.D.H, and FCVT.H.D. + when(): return implemented?(Zdinx); + +type: unprivileged +versions: + - version: "1.0.0" + state: ratified + ratification_date: 2021-11 + requires: Zfinx diff --git a/arch/isa/fp.idl b/arch/isa/fp.idl index 335c73ef2..40e425e5f 100644 --- a/arch/isa/fp.idl +++ b/arch/isa/fp.idl @@ -125,16 +125,42 @@ function check_f_ok { arguments Bits encoding description { - Checks if instructions from the `F` extension can be executed, and, if not, + Checks if instructions from a floating point extension can be executed, and, if not, raise an exception. } body { - if (MUTABLE_MISA_F && CSR[misa].F == 0) { - raise(ExceptionCode::IllegalInstruction, mode(), encoding); - } + # All Z*inx extensions depend on Zfinx, so we only have to check if Zfinx is implemented + if (implemented?(ExtensionName::Zfinx)) { + # mstateen0.FCSR disables all modes + if (implemented?(ExtensionName::Smstateen) && (CSR[mstateen0].FCSR == 0)) { + raise(ExceptionCode::IllegalInstruction, mode(), enoding); + } - if (CSR[mstatus].FS == 0) { - raise(ExceptionCode::IllegalInstruction, mode(), encoding); + # sstateen0.FCSR disables all modes except M + if (implemented?(ExtensionName::Sstateen) && + (mode() != PrivilegeMode::M) && + (CSR[sstateen0].FCSR == 0)) { + raise(ExceptionCode::IllegalInstruction, mode(), enoding); + } + + # hstateen0.FCSR disables VS and VU + if (implemented?(ExtensionName::Sstateen) && + implemented?(ExtensionName::H) && + (CSR[misa].H == 1) && + virtual_mode?() && + (CSR[hstateen0].FCSR == 0)) { + raise(ExceptionCode::IllegalInstruction, mode(), enoding); + } + } else if (implemented?(ExtensionName::F)) { + if (MUTABLE_MISA_F && CSR[misa].F == 0) { + raise(ExceptionCode::IllegalInstruction, mode(), encoding); + } + + if (CSR[mstatus].FS == 0) { + raise(ExceptionCode::IllegalInstruction, mode(), encoding); + } + } else { + assert(false, "check_f_ok called when no FP extension is implemented"); } } }