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