7a36c7f9b277f97aab117216943f77eeda34a916
[libreriscv.git] / openpower / sv / int_fp_mv / moves_and_conversions.mdwn
1 <!-- main body for int_fp_mv.mdwn (without fmvis/fishmv) and ls006.mdwn -->
2 # Immediate Tables
3
4 Tables that are used by
5 `mffpr[s][.]`/`mtfpr[s]`/`cffpr[o][.]`/`ctfpr[s][.]`:
6
7 ## `IT` -- Integer Type
8
9 | `IT` | Integer Type | Assembly Alias Mnemonic |
10 |------|-----------------|-------------------------|
11 | 0 | Signed 32-bit | `<op>w` |
12 | 1 | Unsigned 32-bit | `<op>uw` |
13 | 2 | Signed 64-bit | `<op>d` |
14 | 3 | Unsigned 64-bit | `<op>ud` |
15
16 ## `CVM` -- Float to Integer Conversion Mode
17
18 | `CVM` | `rounding_mode` | Semantics |
19 |-------|-----------------|----------------------------------|
20 | 000 | from `FPSCR` | [OpenPower semantics] |
21 | 001 | Truncate | [OpenPower semantics] |
22 | 010 | from `FPSCR` | [Java/Saturating semantics] |
23 | 011 | Truncate | [Java/Saturating semantics] |
24 | 100 | from `FPSCR` | [JavaScript semantics] |
25 | 101 | Truncate | [JavaScript semantics] |
26 | rest | -- | illegal instruction trap for now |
27
28 [OpenPower semantics]: #fp-to-int-openpower-conversion-semantics
29 [Java/Saturating semantics]: #fp-to-int-java-saturating-conversion-semantics
30 [JavaScript semantics]: #fp-to-int-javascript-conversion-semantics
31
32 ----------
33
34 # Moves
35
36 These instructions perform a straight unaltered bit-level copy from one Register
37 File to another.
38
39 ## Floating Move To GPR
40
41 ```
42 mffpr RT, FRB
43 mffpr. RT, FRB
44 ```
45
46 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
47 |-----|------|-------|-------|-------|----|--------|
48 | PO | RT | // | FRB | XO | Rc | X-Form |
49
50 ```
51 RT <- (FRB)
52 ```
53
54 Move a 64-bit float from a FPR to a GPR, just copying bits of the IEEE 754
55 representation directly. This is equivalent to `stfd` followed by `ld`.
56 As `mffpr` is just copying bits, `FPSCR` is not affected in any way. `mffpr` is
57 similar to `mfvsrd`, except doesn't require VSX, which is useful for SFFS
58 implementations.
59
60 Rc=1 tests RT and sets CR0, exactly like all other Scalar Fixed-Point
61 operations.
62
63 Special Registers altered:
64
65 ```
66 CR0 (if Rc=1)
67 ```
68
69 ----------
70
71 ## Floating Move To GPR Single
72
73 ```
74 mffprs RT, FRB
75 mffprs. RT, FRB
76 ```
77
78 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
79 |-----|------|-------|-------|-------|----|--------|
80 | PO | RT | // | FRB | XO | Rc | X-Form |
81
82 ```
83 RT <- [0] * 32 || SINGLE((FRB)) # SINGLE since that's what stfs uses
84 ```
85
86 Move a BFP32 from a FPR to a GPR, by using `SINGLE` to extract the standard
87 `BFP32` form from FRB and zero-extending the result to 64-bits and storing to
88 RT. This is equivalent to `stfs` followed by `lwz`.
89 As `mffprs` is just copying the BFP32 form, `FPSCR` is not affected in any way.
90
91 Rc=1 tests RT and sets CR0, exactly like all other Scalar Fixed-Point
92 operations.
93
94 Special Registers altered:
95
96 ```
97 CR0 (if Rc=1)
98 ```
99
100 ----------
101
102 \newpage{}
103
104 ## Double-Precision Floating Move From GPR
105
106 ```
107 mtfpr FRT, RB
108 ```
109
110 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
111 |-----|------|-------|-------|-------|----|--------|
112 | PO | FRT | // | RB | XO | // | X-Form |
113
114 ```
115 FRT <- (RB)
116 ```
117
118 move a 64-bit float from a GPR to a FPR, just copying bits of the IEEE 754
119 representation directly. This is equivalent to `std` followed by `lfd`.
120 As `mtfpr` is just copying bits, `FPSCR` is not affected in any way. `mtfpr` is
121 similar to `mtvsrd`, except doesn't require VSX, which is useful for SFFS
122 implementations.
123
124 Special Registers altered:
125
126 ```
127 None
128 ```
129
130 ----------
131
132 ## Floating Move From GPR Single
133
134 ```
135 mtfprs FRT, RB
136 ```
137
138 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
139 |-----|------|-------|-------|-------|----|--------|
140 | PO | FRT | // | RB | XO | // | X-Form |
141
142 ```
143 FRT <- DOUBLE((RB)[32:63]) # DOUBLE since that's what lfs uses
144 ```
145
146 Move a BFP32 from a GPR to a FPR, by using `DOUBLE` on the least significant
147 32-bits of RB to do the standard BFP32 in BFP64 trick and store the result in
148 FRT. This is equivalent to `stw` followed by `lfs`.
149 As `mtfprs` is just copying the BFP32 form, `FPSCR` is not affected in any way.
150
151 Special Registers altered:
152
153 ```
154 None
155 ```
156
157 ----------
158
159 \newpage{}
160
161 # Conversions
162
163 Unlike the move instructions
164 these instructions perform conversions between Integer and
165 Floating Point. Truncation can therefore occur, as well
166 as exceptions.
167
168 ## Double-Precision Floating Convert From Integer In GPR
169
170 ```
171 ctfpr FRT, RB, IT
172 ctfpr. FRT, RB, IT
173 ```
174
175 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
176 |-----|------|-------|-------|-------|-------|----|--------|
177 | PO | FRT | IT | // | RB | XO | Rc | X-Form |
178
179 ```
180 if IT[0] = 0 then # 32-bit int -> 64-bit float
181 # rounding never necessary, so don't touch FPSCR
182 # based off xvcvsxwdp
183 if IT = 0 then # Signed 32-bit
184 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
185 else # IT = 1 -- Unsigned 32-bit
186 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
187 FRT <- bfp64_CONVERT_FROM_BFP(src)
188 else
189 # rounding may be necessary. based off xscvuxdsp
190 reset_xflags()
191 switch(IT)
192 case(0): # Signed 32-bit
193 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
194 case(1): # Unsigned 32-bit
195 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
196 case(2): # Signed 64-bit
197 src <- bfp_CONVERT_FROM_SI64((RB))
198 default: # Unsigned 64-bit
199 src <- bfp_CONVERT_FROM_UI64((RB))
200 rnd <- bfp_ROUND_TO_BFP64(0b0, FPSCR.RN, src)
201 result <- bfp64_CONVERT_FROM_BFP(rnd)
202 cls <- fprf_CLASS_BFP64(result)
203
204 if xx_flag = 1 then SetFX(FPSCR.XX)
205
206 FRT <- result
207 FPSCR.FPRF <- cls
208 FPSCR.FR <- inc_flag
209 FPSCR.FI <- xx_flag
210 ```
211 <!-- note the PowerISA spec. explicitly has empty lines before/after SetFX,
212 don't remove them -->
213
214 Convert from a unsigned/signed 32/64-bit integer in RB to a 64-bit
215 float in FRT.
216
217 If converting from a unsigned/signed 32-bit integer to a 64-bit float,
218 rounding is never necessary, so `FPSCR` is unmodified and exceptions are
219 never raised. Otherwise, `FPSCR` is modified and exceptions are raised
220 as usual.
221
222 Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point
223 operations.
224
225 Special Registers altered:
226
227 ```
228 CR1 (if Rc=1)
229 FPRF FR FI FX XX (if IT[0]=1)
230 ```
231
232 ### Assembly Aliases
233
234 | Assembly Alias | Full Instruction |
235 |----------------------|----------------------|
236 | `ctfprw FRT, RB` | `ctfpr FRT, RB, 0` |
237 | `ctfprw. FRT, RB` | `ctfpr. FRT, RB, 0` |
238 | `ctfpruw FRT, RB` | `ctfpr FRT, RB, 1` |
239 | `ctfpruw. FRT, RB` | `ctfpr. FRT, RB, 1` |
240 | `ctfprd FRT, RB` | `ctfpr FRT, RB, 2` |
241 | `ctfprd. FRT, RB` | `ctfpr. FRT, RB, 2` |
242 | `ctfprud FRT, RB` | `ctfpr FRT, RB, 3` |
243 | `ctfprud. FRT, RB` | `ctfpr. FRT, RB, 3` |
244
245 ----------
246
247 \newpage{}
248
249 ## Floating Convert From Integer In GPR Single
250
251 ```
252 ctfprs FRT, RB, IT
253 ctfprs. FRT, RB, IT
254 ```
255
256 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
257 |-----|------|-------|-------|-------|-------|----|--------|
258 | PO | FRT | IT | // | RB | XO | Rc | X-Form |
259
260 ```
261 # rounding may be necessary. based off xscvuxdsp
262 reset_xflags()
263 switch(IT)
264 case(0): # Signed 32-bit
265 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
266 case(1): # Unsigned 32-bit
267 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
268 case(2): # Signed 64-bit
269 src <- bfp_CONVERT_FROM_SI64((RB))
270 default: # Unsigned 64-bit
271 src <- bfp_CONVERT_FROM_UI64((RB))
272 rnd <- bfp_ROUND_TO_BFP32(FPSCR.RN, src)
273 result32 <- bfp32_CONVERT_FROM_BFP(rnd)
274 cls <- fprf_CLASS_BFP32(result32)
275 result <- DOUBLE(result32)
276
277 if xx_flag = 1 then SetFX(FPSCR.XX)
278
279 FRT <- result
280 FPSCR.FPRF <- cls
281 FPSCR.FR <- inc_flag
282 FPSCR.FI <- xx_flag
283 ```
284 <!-- note the PowerISA spec. explicitly has empty lines before/after SetFX,
285 don't remove them -->
286
287 Convert from a unsigned/signed 32/64-bit integer in RB to a 32-bit
288 float in FRT, following the usual 32-bit float in 64-bit float format.
289 `FPSCR` is modified and exceptions are raised as usual.
290
291 Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point
292 operations.
293
294 Special Registers altered:
295
296 ```
297 CR1 (if Rc=1)
298 FPRF FR FI FX XX
299 ```
300
301 ### Assembly Aliases
302
303 | Assembly Alias | Full Instruction |
304 |----------------------|----------------------|
305 | `ctfprws FRT, RB` | `ctfpr FRT, RB, 0` |
306 | `ctfprws. FRT, RB` | `ctfpr. FRT, RB, 0` |
307 | `ctfpruws FRT, RB` | `ctfpr FRT, RB, 1` |
308 | `ctfpruws. FRT, RB` | `ctfpr. FRT, RB, 1` |
309 | `ctfprds FRT, RB` | `ctfpr FRT, RB, 2` |
310 | `ctfprds. FRT, RB` | `ctfpr. FRT, RB, 2` |
311 | `ctfpruds FRT, RB` | `ctfpr FRT, RB, 3` |
312 | `ctfpruds. FRT, RB` | `ctfpr. FRT, RB, 3` |
313
314 ----------
315
316 \newpage{}
317
318 ## Floating-point to Integer Conversion Overview
319
320 <div id="fpr-to-gpr-conversion-mode"></div>
321
322 IEEE 754 doesn't specify what results are obtained when converting a NaN
323 or out-of-range floating-point value to integer, so different programming
324 languages and ISAs have made different choices. Below is an overview
325 of the different variants, listing the languages and hardware that
326 implements each variant.
327
328 For convenience, those different conversion semantics will be given names
329 based on which common ISA or programming language uses them, since there
330 may not be an established name for them:
331
332 **Standard OpenPower conversion**
333
334 This conversion performs "saturation with NaN converted to minimum
335 valid integer". This is also exactly the same as the x86 ISA conversion
336 semantics. OpenPOWER however has instructions for both:
337
338 * rounding mode read from FPSCR
339 * rounding mode always set to truncate
340
341 **Java/Saturating conversion**
342
343 For the sake of simplicity, the FP -> Integer conversion semantics
344 generalized from those used by Java's semantics (and Rust's `as`
345 operator) will be referred to as [Java/Saturating conversion
346 semantics](#fp-to-int-java-saturating-conversion-semantics).
347
348 Those same semantics are used in some way by all of the following
349 languages (not necessarily for the default conversion method):
350
351 * Java's
352 [FP -> Integer conversion](https://docs.oracle.com/javase/specs/jls/se16/html/jls-5.html#jls-5.1.3)
353 (only for long/int results)
354 * Rust's FP -> Integer conversion using the
355 [`as` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics)
356 * LLVM's
357 [`llvm.fptosi.sat`](https://llvm.org/docs/LangRef.html#llvm-fptosi-sat-intrinsic) and
358 [`llvm.fptoui.sat`](https://llvm.org/docs/LangRef.html#llvm-fptoui-sat-intrinsic) intrinsics
359 * SPIR-V's OpenCL dialect's
360 [`OpConvertFToU`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToU) and
361 [`OpConvertFToS`](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#OpConvertFToS)
362 instructions when decorated with
363 [the `SaturatedConversion` decorator](https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html#_a_id_decoration_a_decoration).
364 * WebAssembly has also introduced
365 [trunc_sat_u](ttps://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-u) and
366 [trunc_sat_s](https://webassembly.github.io/spec/core/exec/numerics.html#op-trunc-sat-s)
367
368 **JavaScript conversion**
369
370 For the sake of simplicity, the FP -> Integer conversion
371 semantics generalized from those used by JavaScripts's `ToInt32`
372 abstract operation will be referred to as [JavaScript conversion
373 semantics](#fp-to-int-javascript-conversion-semantics).
374
375 This instruction is present in ARM assembler as FJCVTZS
376 <https://developer.arm.com/documentation/dui0801/g/hko1477562192868>
377
378 **Rc=1 and OE=1**
379
380 All of these instructions have an Rc=1 mode which sets CR0
381 in the normal way for any instructions producing a GPR result.
382 Additionally, when OE=1, if the numerical value of the FP number
383 is not 100% accurately preserved (due to truncation or saturation
384 and including when the FP number was NaN) then this is considered
385 to be an integer Overflow condition, and CR0.SO, XER.SO and XER.OV
386 are all set as normal for any GPR instructions that overflow.
387
388 \newpage{}
389
390 ### FP to Integer Conversion Simplified Pseudo-code
391
392 Key for pseudo-code:
393
394 | term | result type | definition |
395 |---------------------------|-------------|----------------------------------------------------------------------------------------------------|
396 | `fp` | -- | `f32` or `f64` (or other types from SimpleV) |
397 | `int` | -- | `u32`/`u64`/`i32`/`i64` (or other types from SimpleV) |
398 | `uint` | -- | the unsigned integer of the same bit-width as `int` |
399 | `int::BITS` | `int` | the bit-width of `int` |
400 | `uint::MIN_VALUE` | `uint` | the minimum value `uint` can store: `0` |
401 | `uint::MAX_VALUE` | `uint` | the maximum value `uint` can store: `2^int::BITS - 1` |
402 | `int::MIN_VALUE` | `int` | the minimum value `int` can store : `-2^(int::BITS-1)` |
403 | `int::MAX_VALUE` | `int` | the maximum value `int` can store : `2^(int::BITS-1) - 1` |
404 | `int::VALUE_COUNT` | Integer | the number of different values `int` can store (`2^int::BITS`). too big to fit in `int`. |
405 | `rint(fp, rounding_mode)` | `fp` | rounds the floating-point value `fp` to an integer according to rounding mode `rounding_mode` |
406
407 <div id="fp-to-int-openpower-conversion-semantics"></div>
408 OpenPower conversion semantics (section A.2 page 1009 (page 1035) of
409 Power ISA v3.1B):
410
411 ```
412 def fp_to_int_open_power<fp, int>(v: fp) -> int:
413 if v is NaN:
414 return int::MIN_VALUE
415 if v >= int::MAX_VALUE:
416 return int::MAX_VALUE
417 if v <= int::MIN_VALUE:
418 return int::MIN_VALUE
419 return (int)rint(v, rounding_mode)
420 ```
421
422 <div id="fp-to-int-java-saturating-conversion-semantics"></div>
423 [Java/Saturating conversion semantics](https://docs.oracle.com/javase/specs/jls/se16/html/jls-5.html#jls-5.1.3)
424 (only for long/int results)
425 (with adjustment to add non-truncate rounding modes):
426
427 ```
428 def fp_to_int_java_saturating<fp, int>(v: fp) -> int:
429 if v is NaN:
430 return 0
431 if v >= int::MAX_VALUE:
432 return int::MAX_VALUE
433 if v <= int::MIN_VALUE:
434 return int::MIN_VALUE
435 return (int)rint(v, rounding_mode)
436 ```
437
438 <div id="fp-to-int-javascript-conversion-semantics"></div>
439 Section 7.1 of the ECMAScript / JavaScript
440 [conversion semantics](https://262.ecma-international.org/11.0/#sec-toint32)
441 (with adjustment to add non-truncate rounding modes):
442
443 ```
444 def fp_to_int_java_script<fp, int>(v: fp) -> int:
445 if v is NaN or infinite:
446 return 0
447 v = rint(v, rounding_mode) # assume no loss of precision in result
448 v = v mod int::VALUE_COUNT # 2^32 for i32, 2^64 for i64, result is non-negative
449 bits = (uint)v
450 return (int)bits
451 ```
452
453 ----------
454
455 \newpage{}
456
457 ## Double-Precision Floating Convert To Integer In GPR
458
459 ```
460 cffpr RT, FRB, CVM, IT
461 cffpr. RT, FRB, CVM, IT
462 cffpro RT, FRB, CVM, IT
463 cffpro. RT, FRB, CVM, IT
464 ```
465
466 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21 | 22-30 | 31 | Form |
467 |-----|------|-------|-------|-------|----|-------|----|---------|
468 | PO | RT | IT | CVM | FRB | OE | XO | Rc | XO-Form |
469
470 ```
471 # based on xscvdpuxws
472 reset_xflags()
473 src <- bfp_CONVERT_FROM_BFP64((FRB))
474
475 switch(IT)
476 case(0): # Signed 32-bit
477 range_min <- bfp_CONVERT_FROM_SI32(0x8000_0000)
478 range_max <- bfp_CONVERT_FROM_SI32(0x7FFF_FFFF)
479 js_mask <- 0x0000_0000_FFFF_FFFF
480 case(1): # Unsigned 32-bit
481 range_min <- bfp_CONVERT_FROM_UI32(0)
482 range_max <- bfp_CONVERT_FROM_UI32(0xFFFF_FFFF)
483 js_mask <- 0x0000_0000_FFFF_FFFF
484 case(2): # Signed 64-bit
485 range_min <- bfp_CONVERT_FROM_SI64(-0x8000_0000_0000_0000)
486 range_max <- bfp_CONVERT_FROM_SI64(0x7FFF_FFFF_FFFF_FFFF)
487 js_mask <- 0xFFFF_FFFF_FFFF_FFFF
488 default: # Unsigned 64-bit
489 range_min <- bfp_CONVERT_FROM_UI64(0)
490 range_max <- bfp_CONVERT_FROM_UI64(0xFFFF_FFFF_FFFF_FFFF)
491 js_mask <- 0xFFFF_FFFF_FFFF_FFFF
492
493 if (CVM[2] = 1) | (FPSCR.RN = 0b01) then
494 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(src)
495 else if FPSCR.RN = 0b00 then
496 rnd <- bfp_ROUND_TO_INTEGER_NEAR_EVEN(src)
497 else if FPSCR.RN = 0b10 then
498 rnd <- bfp_ROUND_TO_INTEGER_CEIL(src)
499 else if FPSCR.RN = 0b11 then
500 rnd <- bfp_ROUND_TO_INTEGER_FLOOR(src)
501
502 switch(CVM)
503 case(0, 1): # OpenPower semantics
504 if IsNaN(rnd) then
505 result <- si64_CONVERT_FROM_BFP(range_min)
506 else if bfp_COMPARE_GT(rnd, range_max) then
507 result <- ui64_CONVERT_FROM_BFP(range_max)
508 else if bfp_COMPARE_LT(rnd, range_min) then
509 result <- si64_CONVERT_FROM_BFP(range_min)
510 else if IT[1] = 1 then # Unsigned 32/64-bit
511 result <- ui64_CONVERT_FROM_BFP(rnd)
512 else # Signed 32/64-bit
513 result <- si64_CONVERT_FROM_BFP(rnd)
514 case(2, 3): # Java/Saturating semantics
515 if IsNaN(rnd) then
516 result <- [0] * 64
517 else if bfp_COMPARE_GT(rnd, range_max) then
518 result <- ui64_CONVERT_FROM_BFP(range_max)
519 else if bfp_COMPARE_LT(rnd, range_min) then
520 result <- si64_CONVERT_FROM_BFP(range_min)
521 else if IT[1] = 1 then # Unsigned 32/64-bit
522 result <- ui64_CONVERT_FROM_BFP(rnd)
523 else # Signed 32/64-bit
524 result <- si64_CONVERT_FROM_BFP(rnd)
525 default: # JavaScript semantics
526 # CVM = 6, 7 are illegal instructions
527 # using a 128-bit intermediate works here because the largest type
528 # this instruction can convert from has 53 significand bits, and
529 # the largest type this instruction can convert to has 64 bits,
530 # and the sum of those is strictly less than the 128 bits of the
531 # intermediate result.
532 limit <- bfp_CONVERT_FROM_UI128([1] * 128)
533 if IsInf(rnd) | IsNaN(rnd) then
534 result <- [0] * 64
535 else if bfp_COMPARE_GT(bfp_ABSOLUTE(rnd), limit) then
536 result <- [0] * 64
537 else
538 result128 <- si128_CONVERT_FROM_BFP(rnd)
539 result <- result128[64:127] & js_mask
540
541 switch(IT)
542 case(0): # Signed 32-bit
543 result <- EXTS64(result[32:63])
544 result_bfp <- bfp_CONVERT_FROM_SI32(result[32:63])
545 case(1): # Unsigned 32-bit
546 result <- EXTZ64(result[32:63])
547 result_bfp <- bfp_CONVERT_FROM_UI32(result[32:63])
548 case(2): # Signed 64-bit
549 result_bfp <- bfp_CONVERT_FROM_SI64(result)
550 default: # Unsigned 64-bit
551 result_bfp <- bfp_CONVERT_FROM_UI64(result)
552
553 overflow <- 0 # signals SO only when OE = 1
554 if IsNaN(src) | ¬bfp_COMPARE_EQ(rnd, result_bfp) then
555 overflow <- 1 # signals SO only when OE = 1
556 vxcvi_flag <- 1
557 xx_flag <- 0
558 inc_flag <- 0
559 else
560 xx_flag <- ¬bfp_COMPARE_EQ(src, result_bfp)
561 inc_flag <- bfp_COMPARE_GT(bfp_ABSOLUTE(result_bfp), bfp_ABSOLUTE(src))
562
563 if vxsnan_flag = 1 then SetFX(FPSCR.VXSNAN)
564 if vxcvi_flag = 1 then SetFX(FPSCR.VXCVI)
565 if xx_flag = 1 then SetFX(FPSCR.XX)
566
567 vx_flag <- vxsnan_flag | vxcvi_flag
568 vex_flag <- FPSCR.VE & vx_flag
569 if vex_flag = 0 then
570 RT <- result
571 FPSCR.FPRF <- undefined
572 FPSCR.FR <- inc_flag
573 FPSCR.FI <- xx_flag
574 else
575 FPSCR.FR <- 0
576 FPSCR.FI <- 0
577 ```
578
579 Convert from 64-bit float in FRB to a unsigned/signed 32/64-bit integer
580 in RT, with the conversion overflow/rounding semantics following the
581 chosen `CVM` value. `FPSCR` is modified and exceptions are raised as usual.
582
583 These instructions have an Rc=1 mode which sets CR0 in the normal
584 way for any instructions producing a GPR result. Additionally, when OE=1,
585 if the numerical value of the FP number is not 100% accurately preserved
586 (due to truncation or saturation and including when the FP number was
587 NaN) then this is considered to be an Integer Overflow condition, and
588 CR0.SO, XER.SO and XER.OV are all set as normal for any GPR instructions
589 that overflow. When `RT` is not written (`vex_flag = 1`), all CR0 bits
590 except SO are undefined.
591
592 Special Registers altered:
593
594 ```
595 CR0 (if Rc=1)
596 XER SO, OV, OV32 (if OE=1)
597 FPRF=0bUUUUU FR FI FX XX VXSNAN VXCV
598 ```
599
600 ### Assembly Aliases
601
602 | Assembly Alias | Full Instruction |
603 |---------------------------|----------------------------|
604 | `cffprw RT, FRB, CVM` | `cffpr RT, FRB, CVM, 0` |
605 | `cffprw. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 0` |
606 | `cffprwo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 0` |
607 | `cffprwo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 0` |
608 | `cffpruw RT, FRB, CVM` | `cffpr RT, FRB, CVM, 1` |
609 | `cffpruw. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 1` |
610 | `cffpruwo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 1` |
611 | `cffpruwo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 1` |
612 | `cffprd RT, FRB, CVM` | `cffpr RT, FRB, CVM, 2` |
613 | `cffprd. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 2` |
614 | `cffprdo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 2` |
615 | `cffprdo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 2` |
616 | `cffprud RT, FRB, CVM` | `cffpr RT, FRB, CVM, 3` |
617 | `cffprud. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 3` |
618 | `cffprudo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 3` |
619 | `cffprudo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 3` |