From c6e2d351c97c120b74e794b412e4f5b3f8a1d952 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 3 Jul 2023 20:13:09 -0700 Subject: [PATCH] rewrite cvt_fp_to_int_overview.mdwn to be more like a specification. --- .../sv/int_fp_mv/cvt_fp_to_int_overview.mdwn | 180 ++++++------------ 1 file changed, 55 insertions(+), 125 deletions(-) diff --git a/openpower/sv/int_fp_mv/cvt_fp_to_int_overview.mdwn b/openpower/sv/int_fp_mv/cvt_fp_to_int_overview.mdwn index a3175ae3f..f2c05222b 100644 --- a/openpower/sv/int_fp_mv/cvt_fp_to_int_overview.mdwn +++ b/openpower/sv/int_fp_mv/cvt_fp_to_int_overview.mdwn @@ -4,131 +4,61 @@ IEEE 754 doesn't specify what results are obtained when converting a NaN or out-of-range floating-point value to integer, so different programming -languages and ISAs have made different choices. Below is an overview -of the different variants, listing the languages and hardware that -implements each variant. - -For convenience, those different conversion semantics will be given names -based on which common ISA or programming language uses them, since there -may not be an established name for them: - -**Standard OpenPower conversion** - -This conversion performs "saturation with NaN converted to minimum -valid integer". This is also exactly the same as the x86 ISA conversion -semantics. OpenPOWER however has instructions for both: - -* rounding mode read from FPSCR -* rounding mode always set to truncate - -**Java/Saturating conversion** - -For the sake of simplicity, the FP -> Integer conversion semantics -generalized from those used by Java's semantics (and Rust's `as` -operator) will be referred to as [Java/Saturating conversion -semantics](#fp-to-int-java-saturating-conversion-semantics). - -Those same semantics are used in some way by all of the following -languages (not necessarily for the default conversion method): - -* Java's - [FP -> Integer conversion](https://docs.oracle.com/javase/specs/jls/se16/html/jls-5.html#jls-5.1.3) - (only for long/int results) -* Rust's FP -> Integer conversion using the - [`as` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics) -* LLVM's - [`llvm.fptosi.sat`](https://llvm.org/docs/LangRef.html#llvm-fptosi-sat-intrinsic) and - [`llvm.fptoui.sat`](https://llvm.org/docs/LangRef.html#llvm-fptoui-sat-intrinsic) intrinsics -* SPIR-V's OpenCL dialect's - [`OpConvertFToU`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToU) and - [`OpConvertFToS`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToS) - instructions when decorated with - [the `SaturatedConversion` decorator](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_decoration_a_decoration). -* WebAssembly has also introduced - [trunc_sat_u](ttps://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-u) and - [trunc_sat_s](https://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-s) - -**JavaScript conversion** - -For the sake of simplicity, the FP -> Integer conversion -semantics generalized from those used by JavaScripts's `ToInt32` -abstract operation will be referred to as [JavaScript conversion -semantics](#fp-to-int-javascript-conversion-semantics). - -This instruction is present in ARM assembler as FJCVTZS - - -**Rc=1 and OE=1** - -All of these instructions have an Rc=1 mode which sets CR0 -in the normal way for any instructions producing a GPR result. -Additionally, when OE=1, if the numerical value of the FP number -is not 100% accurately preserved (due to truncation or saturation -and including when the FP number was NaN) then this is considered -to be an integer Overflow condition, and CR0.SO, XER.SO and XER.OV -are all set as normal for any GPR instructions that overflow. - -\newpage{} - -### FP to Integer Conversion Simplified Pseudo-code - -Key for pseudo-code: - -| term | result type | definition | -|---------------------------|-------------|-----------------------------------------------------------------------------------------------| -| `fp` | -- | `f32` or `f64` (or other types from SimpleV) | -| `int` | -- | `u32`/`u64`/`i32`/`i64` (or other types from SimpleV) | -| `uint` | -- | the unsigned integer of the same bit-width as `int` | -| `int::BITS` | `int` | the bit-width of `int` | -| `uint::MIN_VALUE` | `uint` | the minimum value `uint` can store: `0` | -| `uint::MAX_VALUE` | `uint` | the maximum value `uint` can store: `2^int::BITS - 1` | -| `int::MIN_VALUE` | `int` | the minimum value `int` can store : `-2^(int::BITS-1)` | -| `int::MAX_VALUE` | `int` | the maximum value `int` can store : `2^(int::BITS-1) - 1` | -| `int::VALUE_COUNT` | Integer | the number of different values `int` can store (`2^int::BITS`). too big to fit in `int`. | -| `rint(fp, rounding_mode)` | `fp` | rounds the floating-point value `fp` to an integer according to rounding mode `rounding_mode` | - -
-OpenPower conversion semantics (section A.2 page 1009 (page 1035) of -Power ISA v3.1B): - -``` - def fp_to_int_open_power(v: fp) -> int: - if v is NaN: - return int::MIN_VALUE - if v >= int::MAX_VALUE: - return int::MAX_VALUE - if v <= int::MIN_VALUE: - return int::MIN_VALUE - return (int)rint(v, rounding_mode) -``` - -
-[Java/Saturating conversion semantics](https://docs.oracle.com/javase/specs/jls/se16/html/jls-5.html#jls-5.1.3) -(only for long/int results) -(with adjustment to add non-truncate rounding modes): - -``` - def fp_to_int_java_saturating(v: fp) -> int: - if v is NaN: - return 0 - if v >= int::MAX_VALUE: - return int::MAX_VALUE - if v <= int::MIN_VALUE: - return int::MIN_VALUE - return (int)rint(v, rounding_mode) -``` - -
-Section 7.1 of the ECMAScript / JavaScript -[conversion semantics](https://262.ecma-international.org/11.0/#sec-toint32) -(with adjustment to add non-truncate rounding modes): +languages and ISAs have made different choices. The different conversion +modes supported by the `cffpr` instruction are as follows: + +* P-Type: + This type of conversion is that used by most other PowerISA instructions, + as well as commonly used floating-point to integer conversions on x86. + +* S-Type: + This type of conversion is used for WebAssembly's + [`trunc_sat_u`](https://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-u) + and + [trunc_sat_s](https://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-s) + instructions, as well as several notable programming languages: + + * Java's conversion from + [`float`/`double` to `long`/`int`](https://docs.oracle.com/javase/specs/jls/se16/html/jls-5.html#jls-5.1.3) + * Rust's [`as` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics) + * LLVM's [`llvm.fptosi.sat`](https://llvm.org/docs/LangRef.html#llvm-fptosi-sat-intrinsic) and + [`llvm.fptoui.sat`](https://llvm.org/docs/LangRef.html#llvm-fptoui-sat-intrinsic) intrinsics + * SPIR-V's OpenCL dialect's + [`OpConvertFToU`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToU) and + [`OpConvertFToS`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToS) + instructions when decorated with + [the `SaturatedConversion` decorator](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_decoration_a_decoration). + +* E-Type: + This type of conversion is used for + [ECMAScript's `ToInt32` abstract operation](https://262.ecma-international.org/14.0/#sec-toint32). + + This type of conversion is also implemented in ARMv8.3A as the `FJCVTZS` + instruction. + + +### Floating-point to Integer Conversion Semantics Summary + +Let `rounded` be the result of `bfp_ROUND_TO_INTEGER(rmode, input)`. +Let `w` be the number of bits in the result's type. +The result of Floating-point to Integer conversion is as follows: ``` - def fp_to_int_java_script(v: fp) -> int: - if v is NaN or infinite: - return 0 - v = rint(v, rounding_mode) # assume no loss of precision in result - v = v mod int::VALUE_COUNT # 2^32 for i32, 2^64 for i64, result is non-negative - bits = (uint)v - return (int)bits ++--------+------------+-----------------------------------------------------------------------+ +| Kind | Result's | Category of rounded | +| | Signedness +-----------+-----------+-----------+-----------+-----------+-----------+ +| | | NaN | +Infinity | -Infinity | > Maximum | < Minimum | Otherwise | +| | | | | | Possible | Possible | | +| | | | | | Result | Result | | ++--------+------------+-----------+-----------+-----------+-----------+-----------+-----------+ +| P-Type | Unsigned | 0 | 2^w - 1 | 0 | 2^w - 1 | 0 | rounded | +| +------------+-----------+-----------+-----------+-----------+-----------+-----------+ +| | Signed | -2^(w-1) | 2^(w-1)-1 | -2^(w-1) | 2^(w-1)-1 | -2^(w-1) | rounded | ++--------+------------+-----------+-----------+-----------+-----------+-----------+-----------+ +| S-Type | Unsigned | 0 | 2^w - 1 | 0 | 2^w - 1 | 0 | rounded | +| +------------+-----------+-----------+-----------+-----------+-----------+-----------+ +| | Signed | 0 | 2^(w-1)-1 | -2^(w-1) | 2^(w-1)-1 | -2^(w-1) | rounded | ++--------+------------+-----------+-----------+-----------+-----------+-----------+-----------+ +| E-Type | Either | 0 | rounded & (2^w - 1) | ++--------+------------+-----------------------------------+-----------------------------------+ ``` -- 2.30.2