* <https://bugs.libre-soc.org/show_bug.cgi?id=230#c76>
* [[int_fp_mv/appendix]]
+Trademarks:
+
+* Rust is a Trademark of the Rust Foundation
+* Java and Javascript are Trademarks of Oracle
+* LLVM is a Trademark of the LLVM Foundation
+* SPIR-V is a Trademark of the Khronos Group
+* OpenCL is a Trademark of Apple, Inc.
+
+Referring to these Trademarks within this document
+is by necessity, in order to put the semantics of each language
+into context, and is considered "fair use" under Trademark
+Law.
+
Introduction:
High-performance CPU/GPU software needs to often convert between integers
the progressive historic development of the Scalar parts of the Power ISA assumed
that VSX would always be there to complement it. However With VMX/VSX
**not available** in the newly-introduced SFFS Compliancy Level, the
-existing non-VSX conversion/data-movement instructions require load/store
+existing non-VSX conversion/data-movement instructions require
+a Vector of load/store
instructions (slow and expensive) to transfer data between the FPRs and
-the GPRs. For a 3D GPU this kills any modern competitive edge.
+the GPRs. For a modern 3D GPU this kills any possibility of a
+competitive edge.
Also, because SimpleV needs efficient scalar instructions in
order to generate efficient vector instructions, adding new instructions
for data-transfer/conversion between FPRs and GPRs multiplies the savings.
Power ISA currently requires a large
number of instructions to get Floating Point constants into registers.
`fmvis` on its own is equivalent to BF16 to FP32/64 conversion,
-but if followed up by `fishmv` an additional 16 bits of accuracy in the
+but if followed up by `frlsi` an additional 16 bits of accuracy in the
mantissa may be achieved.
*IBM may consider it worthwhile to extend these two instructions to
-v3.1 Prefixed (`pfmvis` and `pfishmv`). If so it is recommended that
-`pfmvis` load a full FP32 immediate and `pfishmv` extend the lower
-32-bits to construct a full FP64 immediate.*
+v3.1 Prefixed (`pfmvis` and `pfrlsi`). If so it is recommended that
+`pfmvis` load a full FP32 immediate and `pfrlsi` supplies the three high
+missing exponent bits (numbered 8 to 10) and the lower additional
+29 mantissa bits (23 to 51) needed to construct a full FP64 immediate.*
## Load BF16 Immediate
-`fmvis FRS, FI`
+`fmvis FRS, D`
-Reinterprets `FI << 16` as a 32-bit float, which is then converted to a
+Reinterprets `D << 16` as a 32-bit float, which is then converted to a
64-bit float and written to `FRS`. This is equivalent to reinterpreting
-`FI` as a `BF16` and converting to 64-bit float.
+`D` as a `BF16` and converting to 64-bit float.
There is no need for an Rc=1 variant because this is an immediate loading
instruction.
fp32 = bf16 || [0]*16
FRS = Single_to_Double(fp32)
-## Float Immediate, Second Half <a name="fishmv"></a>
+## Float Replace Lower-Half Single, Immediate <a name="frlsi"></a>
-`fishmv FRS, FI`
+`frlsi FRS, D`
DX-Form:
Strategically similar to how `oris` is used to construct
32-bit Integers, an additional 16-bits of immediate is
inserted into `FRS` to extend its accuracy to
-a full FP32. If a prior `fmvis` instruction had been used to
-set the upper 16-bits of an FP32 value, `fishmv` contains the
+a full FP32 (stored as usual in FP64 Format within the FPR).
+If a prior `fmvis` instruction had been used to
+set the upper 16-bits of an FP32 value, `frlsi` contains the
lower 16-bits.
-The key difference between using `li` and `oris` to construxt 32-bit
-GPR Immediates and `fishmv` is that the `fmvis` will have converted
-the `BF16` to FP64 (Double) format. This is taken into consideration
-as can be seen in the pseudocode below
+The key difference between using `li` and `oris` to construct 32-bit
+GPR Immediates and `frlsi` is that the `fmvis` will have converted
+the `BF16` immediate to FP64 (Double) format.
+This is taken into consideration
+as can be seen in the pseudocode below.
Pseudocode:
# first the upper bits, happens to be +1.0
fmvis f4, 0x3F80 # writes +1.0 to f4
# now write the lower 16 bits of an FP32
-fishmv f4, 0x8000 # writes +1.00390625 to f4
+frlsi f4, 0x8000 # writes +1.00390625 to f4
```
# Moves
This conversion, instead of exact IEEE754 Compliance, performs
"saturation with NaN converted to minimum valid integer". This
-is also exactly the same as the x86 ISA conversion senantics.
+is also exactly the same as the x86 ISA conversion semantics.
OpenPOWER however has instructions for both:
* rounding mode read from FPSCR
[`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**
|--------|------|--------|-------|-------|----|------|
| Major | RT | //Mode | FRA | XO | Rc |X-Form|
+**Rc=1 and OE=1**
+
+All of these insructions 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.
+
**Instructions**
* `fcvttgw RT, FRA, Mode`
Convert from 64-bit float to 32-bit signed integer, writing the result
- to the GPR `RT`. Converts using [mode `Mode`]
+ to the GPR `RT`. Converts using [mode `Mode`]. Similar to `fctiw` or `fctiwz`
* `fcvttguw RT, FRA, Mode`
Convert from 64-bit float to 32-bit unsigned integer, writing the result
- to the GPR `RT`. Converts using [mode `Mode`]
+ to the GPR `RT`. Converts using [mode `Mode`]. Similar to `fctiwu` or `fctiwuz`
* `fcvttgd RT, FRA, Mode`
Convert from 64-bit float to 64-bit signed integer, writing the result
- to the GPR `RT`. Converts using [mode `Mode`]
+ to the GPR `RT`. Converts using [mode `Mode`]. Similar to `fctid` or `fctidz`
* `fcvttgud RT, FRA, Mode`
Convert from 64-bit float to 64-bit unsigned integer, writing the result
- to the GPR `RT`. Converts using [mode `Mode`]
+ to the GPR `RT`. Converts using [mode `Mode`]. Similar to `fctidu` or `fctiduz`
* `fcvtstgw RT, FRA, Mode`
Convert from 32-bit float to 32-bit signed integer, writing the result
to the GPR `RT`. Converts using [mode `Mode`]
| `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` |
-| `int::MIN_VALUE` | `int` | the minimum value `int` can store (`0` if unsigned, `-2^(int::BITS-1)` if signed) |
-| `int::MAX_VALUE` | `int` | the maximum value `int` can store (`2^int::BITS - 1` if unsigned, `2^(int::BITS-1) - 1` if signed) |
+| `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` |
def fp_to_int_java_script<fp, int>(v: fp) -> int:
if v is NaN or infinite:
return 0
- v = rint(v, rounding_mode)
+ 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