1 <!-- main body for int_fp_mv.mdwn (without fmvis/fishmv) and ls006.fpintmv.mdwn -->
4 Tables that are used by
5 `mffpr[s][.]`/`mtfpr[s]`/`cffpr[o][.]`/`ctfpr[s][.]`:
7 ## `IT` -- Integer Type
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` |
16 ## `CVM` -- Float to Integer Conversion Mode
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 |
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
34 # Move To/From Floating-Point Register Instructions
36 These instructions perform a copy from one register file to another, as if by
37 using a GPR/FPR store, followed by a FPR/GPR load.
39 ## Move From Floating-Point Register
46 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
47 |-----|------|-------|-------|-------|----|--------|
48 | PO | RT | // | FRB | XO | Rc | X-Form |
54 The contents of `FPR[FRB]` are placed into `GPR[RT]`.
56 Special Registers altered:
64 `mffpr` is equivalent to the combination of `stfd` followed by `ld`.
68 `mffpr` is a separate instruction from `mfvsrd` because `mfvsrd` requires
69 VSX which may not be available on simpler implementations.
70 Additionally, SVP64 may treat VSX instructions differently than SFFS
71 instructions in a future version of the architecture.
75 ## Move From Floating-Point Register Single
82 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
83 |-----|------|-------|-------|-------|----|--------|
84 | PO | RT | // | FRB | XO | Rc | X-Form |
87 RT <- [0] * 32 || SINGLE((FRB))
90 The contents of `FPR[FRB]` are converted to BFP32 by using `SINGLE`, then
91 zero-extended to 64-bits, and the result stored in `GPR[RT]`.
93 Special Registers altered:
101 `mffprs` is equivalent to the combination of `stfs` followed by `lwz`.
107 ## Move To Floating-Point Register
113 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
114 |-----|------|-------|-------|-------|----|--------|
115 | PO | FRT | // | RB | XO | // | X-Form |
121 The contents of `GPR[RB]` are placed into `FPR[FRT]`.
123 Special Registers altered:
131 `mtfpr` is equivalent to the combination of `std` followed by `lfd`.
135 `mtfpr` is a separate instruction from `mtvsrd` because `mtvsrd` requires
136 VSX which may not be available on simpler implementations.
137 Additionally, SVP64 may treat VSX instructions differently than SFFS
138 instructions in a future version of the architecture.
142 ## Move To Floating-Point Register Single
148 | 0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
149 |-----|------|-------|-------|-------|----|--------|
150 | PO | FRT | // | RB | XO | // | X-Form |
153 FRT <- DOUBLE((RB)[32:63])
156 The contents of bits 32:63 of `GPR[RB]` are converted to BFP64 by using
157 `DOUBLE`, then the result is stored in `GPR[RT]`.
159 Special Registers altered:
167 `mtfprs` is equivalent to the combination of `stw` followed by `lfs`.
173 # Conversion To/From Floating-Point Register Instructions
175 ## Convert To Floating-Point Register
182 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
183 |-----|------|-------|-------|-------|-------|----|--------|
184 | PO | FRT | IT | // | RB | XO | Rc | X-Form |
187 if IT[0] = 0 then # 32-bit int -> 64-bit float
188 # rounding never necessary, so don't touch FPSCR
189 # based off xvcvsxwdp
190 if IT = 0 then # Signed 32-bit
191 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
192 else # IT = 1 -- Unsigned 32-bit
193 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
194 FRT <- bfp64_CONVERT_FROM_BFP(src)
196 # rounding may be necessary. based off xscvuxdsp
199 case(0): # Signed 32-bit
200 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
201 case(1): # Unsigned 32-bit
202 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
203 case(2): # Signed 64-bit
204 src <- bfp_CONVERT_FROM_SI64((RB))
205 default: # Unsigned 64-bit
206 src <- bfp_CONVERT_FROM_UI64((RB))
207 rnd <- bfp_ROUND_TO_BFP64(0b0, FPSCR.RN, src)
208 result <- bfp64_CONVERT_FROM_BFP(rnd)
209 cls <- fprf_CLASS_BFP64(result)
211 if xx_flag = 1 then SetFX(FPSCR.XX)
218 <!-- note the PowerISA spec. explicitly has empty lines before/after SetFX,
219 don't remove them -->
221 Convert from a unsigned/signed 32/64-bit integer in RB to a 64-bit
224 If converting from a unsigned/signed 32-bit integer to a 64-bit float,
225 rounding is never necessary, so `FPSCR` is unmodified and exceptions are
226 never raised. Otherwise, `FPSCR` is modified and exceptions are raised
229 Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point
232 Special Registers altered:
236 FPRF FR FI FX XX (if IT[0]=1)
241 | Assembly Alias | Full Instruction |
242 |--------------------|---------------------|
243 | `ctfprw FRT, RB` | `ctfpr FRT, RB, 0` |
244 | `ctfprw. FRT, RB` | `ctfpr. FRT, RB, 0` |
245 | `ctfpruw FRT, RB` | `ctfpr FRT, RB, 1` |
246 | `ctfpruw. FRT, RB` | `ctfpr. FRT, RB, 1` |
247 | `ctfprd FRT, RB` | `ctfpr FRT, RB, 2` |
248 | `ctfprd. FRT, RB` | `ctfpr. FRT, RB, 2` |
249 | `ctfprud FRT, RB` | `ctfpr FRT, RB, 3` |
250 | `ctfprud. FRT, RB` | `ctfpr. FRT, RB, 3` |
256 ## Convert To Floating-Point Register Single
263 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
264 |-----|------|-------|-------|-------|-------|----|--------|
265 | PO | FRT | IT | // | RB | XO | Rc | X-Form |
268 # rounding may be necessary. based off xscvuxdsp
271 case(0): # Signed 32-bit
272 src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
273 case(1): # Unsigned 32-bit
274 src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
275 case(2): # Signed 64-bit
276 src <- bfp_CONVERT_FROM_SI64((RB))
277 default: # Unsigned 64-bit
278 src <- bfp_CONVERT_FROM_UI64((RB))
279 rnd <- bfp_ROUND_TO_BFP32(FPSCR.RN, src)
280 result32 <- bfp32_CONVERT_FROM_BFP(rnd)
281 cls <- fprf_CLASS_BFP32(result32)
282 result <- DOUBLE(result32)
284 if xx_flag = 1 then SetFX(FPSCR.XX)
291 <!-- note the PowerISA spec. explicitly has empty lines before/after SetFX,
292 don't remove them -->
294 Convert from a unsigned/signed 32/64-bit integer in RB to a 32-bit
295 float in FRT, following the usual 32-bit float in 64-bit float format.
296 `FPSCR` is modified and exceptions are raised as usual.
298 Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point
301 Special Registers altered:
310 | Assembly Alias | Full Instruction |
311 |---------------------|---------------------|
312 | `ctfprws FRT, RB` | `ctfpr FRT, RB, 0` |
313 | `ctfprws. FRT, RB` | `ctfpr. FRT, RB, 0` |
314 | `ctfpruws FRT, RB` | `ctfpr FRT, RB, 1` |
315 | `ctfpruws. FRT, RB` | `ctfpr. FRT, RB, 1` |
316 | `ctfprds FRT, RB` | `ctfpr FRT, RB, 2` |
317 | `ctfprds. FRT, RB` | `ctfpr. FRT, RB, 2` |
318 | `ctfpruds FRT, RB` | `ctfpr FRT, RB, 3` |
319 | `ctfpruds. FRT, RB` | `ctfpr. FRT, RB, 3` |
325 ## Convert From Floating-Point Register
328 cffpr RT, FRB, CVM, IT
329 cffpr. RT, FRB, CVM, IT
330 cffpro RT, FRB, CVM, IT
331 cffpro. RT, FRB, CVM, IT
334 | 0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21 | 22-30 | 31 | Form |
335 |-----|------|-------|-------|-------|----|-------|----|---------|
336 | PO | RT | IT | CVM | FRB | OE | XO | Rc | XO-Form |
339 # based on xscvdpuxws
341 src <- bfp_CONVERT_FROM_BFP64((FRB))
344 case(0): # Signed 32-bit
345 range_min <- bfp_CONVERT_FROM_SI32(0x8000_0000)
346 range_max <- bfp_CONVERT_FROM_SI32(0x7FFF_FFFF)
347 js_mask <- 0x0000_0000_FFFF_FFFF
348 case(1): # Unsigned 32-bit
349 range_min <- bfp_CONVERT_FROM_UI32(0)
350 range_max <- bfp_CONVERT_FROM_UI32(0xFFFF_FFFF)
351 js_mask <- 0x0000_0000_FFFF_FFFF
352 case(2): # Signed 64-bit
353 range_min <- bfp_CONVERT_FROM_SI64(-0x8000_0000_0000_0000)
354 range_max <- bfp_CONVERT_FROM_SI64(0x7FFF_FFFF_FFFF_FFFF)
355 js_mask <- 0xFFFF_FFFF_FFFF_FFFF
356 default: # Unsigned 64-bit
357 range_min <- bfp_CONVERT_FROM_UI64(0)
358 range_max <- bfp_CONVERT_FROM_UI64(0xFFFF_FFFF_FFFF_FFFF)
359 js_mask <- 0xFFFF_FFFF_FFFF_FFFF
361 if (CVM[2] = 1) | (FPSCR.RN = 0b01) then
362 rnd <- bfp_ROUND_TO_INTEGER_TRUNC(src)
363 else if FPSCR.RN = 0b00 then
364 rnd <- bfp_ROUND_TO_INTEGER_NEAR_EVEN(src)
365 else if FPSCR.RN = 0b10 then
366 rnd <- bfp_ROUND_TO_INTEGER_CEIL(src)
367 else if FPSCR.RN = 0b11 then
368 rnd <- bfp_ROUND_TO_INTEGER_FLOOR(src)
371 case(0, 1): # OpenPower semantics
373 result <- si64_CONVERT_FROM_BFP(range_min)
374 else if bfp_COMPARE_GT(rnd, range_max) then
375 result <- ui64_CONVERT_FROM_BFP(range_max)
376 else if bfp_COMPARE_LT(rnd, range_min) then
377 result <- si64_CONVERT_FROM_BFP(range_min)
378 else if IT[1] = 1 then # Unsigned 32/64-bit
379 result <- ui64_CONVERT_FROM_BFP(rnd)
380 else # Signed 32/64-bit
381 result <- si64_CONVERT_FROM_BFP(rnd)
382 case(2, 3): # Java/Saturating semantics
385 else if bfp_COMPARE_GT(rnd, range_max) then
386 result <- ui64_CONVERT_FROM_BFP(range_max)
387 else if bfp_COMPARE_LT(rnd, range_min) then
388 result <- si64_CONVERT_FROM_BFP(range_min)
389 else if IT[1] = 1 then # Unsigned 32/64-bit
390 result <- ui64_CONVERT_FROM_BFP(rnd)
391 else # Signed 32/64-bit
392 result <- si64_CONVERT_FROM_BFP(rnd)
393 default: # JavaScript semantics
394 # CVM = 6, 7 are illegal instructions
395 # using a 128-bit intermediate works here because the largest type
396 # this instruction can convert from has 53 significand bits, and
397 # the largest type this instruction can convert to has 64 bits,
398 # and the sum of those is strictly less than the 128 bits of the
399 # intermediate result.
400 limit <- bfp_CONVERT_FROM_UI128([1] * 128)
401 if IsInf(rnd) | IsNaN(rnd) then
403 else if bfp_COMPARE_GT(bfp_ABSOLUTE(rnd), limit) then
406 result128 <- si128_CONVERT_FROM_BFP(rnd)
407 result <- result128[64:127] & js_mask
410 case(0): # Signed 32-bit
411 result <- EXTS64(result[32:63])
412 result_bfp <- bfp_CONVERT_FROM_SI32(result[32:63])
413 case(1): # Unsigned 32-bit
414 result <- EXTZ64(result[32:63])
415 result_bfp <- bfp_CONVERT_FROM_UI32(result[32:63])
416 case(2): # Signed 64-bit
417 result_bfp <- bfp_CONVERT_FROM_SI64(result)
418 default: # Unsigned 64-bit
419 result_bfp <- bfp_CONVERT_FROM_UI64(result)
421 overflow <- 0 # signals SO only when OE = 1
422 if IsNaN(src) | ¬bfp_COMPARE_EQ(rnd, result_bfp) then
423 overflow <- 1 # signals SO only when OE = 1
428 xx_flag <- ¬bfp_COMPARE_EQ(src, result_bfp)
429 inc_flag <- bfp_COMPARE_GT(bfp_ABSOLUTE(result_bfp), bfp_ABSOLUTE(src))
431 if vxsnan_flag = 1 then SetFX(FPSCR.VXSNAN)
432 if vxcvi_flag = 1 then SetFX(FPSCR.VXCVI)
433 if xx_flag = 1 then SetFX(FPSCR.XX)
435 vx_flag <- vxsnan_flag | vxcvi_flag
436 vex_flag <- FPSCR.VE & vx_flag
439 FPSCR.FPRF <- undefined
447 Convert from 64-bit float in FRB to a unsigned/signed 32/64-bit integer
448 in RT, with the conversion overflow/rounding semantics following the
449 chosen `CVM` value. `FPSCR` is modified and exceptions are raised as usual.
451 These instructions have an Rc=1 mode which sets CR0 in the normal
452 way for any instructions producing a GPR result. Additionally, when OE=1,
453 if the numerical value of the FP number is not 100% accurately preserved
454 (due to truncation or saturation and including when the FP number was
455 NaN) then this is considered to be an Integer Overflow condition, and
456 CR0.SO, XER.SO and XER.OV are all set as normal for any GPR instructions
457 that overflow. When `RT` is not written (`vex_flag = 1`), all CR0 bits
458 except SO are undefined.
460 Special Registers altered:
464 XER SO, OV, OV32 (if OE=1)
465 FPRF=0bUUUUU FR FI FX XX VXSNAN VXCV
470 | Assembly Alias | Full Instruction |
471 |--------------------------|---------------------------|
472 | `cffprw RT, FRB, CVM` | `cffpr RT, FRB, CVM, 0` |
473 | `cffprw. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 0` |
474 | `cffprwo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 0` |
475 | `cffprwo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 0` |
476 | `cffpruw RT, FRB, CVM` | `cffpr RT, FRB, CVM, 1` |
477 | `cffpruw. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 1` |
478 | `cffpruwo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 1` |
479 | `cffpruwo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 1` |
480 | `cffprd RT, FRB, CVM` | `cffpr RT, FRB, CVM, 2` |
481 | `cffprd. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 2` |
482 | `cffprdo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 2` |
483 | `cffprdo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 2` |
484 | `cffprud RT, FRB, CVM` | `cffpr RT, FRB, CVM, 3` |
485 | `cffprud. RT, FRB, CVM` | `cffpr. RT, FRB, CVM, 3` |
486 | `cffprudo RT, FRB, CVM` | `cffpro RT, FRB, CVM, 3` |
487 | `cffprudo. RT, FRB, CVM` | `cffpro. RT, FRB, CVM, 3` |