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