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