Immediate Tables
Tables that are used by
mffpr[s][.]
/mtfpr[s]
/cffpr[o][.]
/ctfpr[s][.]
:
IT
-- Integer Type
IT |
Integer Type | Assembly Alias Mnemonic |
---|---|---|
0 | Signed 32-bit | <op>w |
1 | Unsigned 32-bit | <op>uw |
2 | Signed 64-bit | <op>d |
3 | Unsigned 64-bit | <op>ud |
CVM
-- Float to Integer Conversion Mode
CVM |
rounding_mode |
Semantics |
---|---|---|
000 | from FPSCR |
P-Type |
001 | Truncate | P-Type |
010 | from FPSCR |
S-Type |
011 | Truncate | S-Type |
100 | from FPSCR |
E-Type |
101 | Truncate | E-Type |
rest | -- | invalid |
\newpage{}
Move To/From Floating-Point Register Instructions
These instructions perform a copy from one register file to another, as if by using a GPR/FPR store, followed by a FPR/GPR load.
Move From Floating-Point Register
mffpr RT, FRB
mffpr. RT, FRB
0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|
PO | RT | // | FRB | XO | Rc | X-Form |
RT <- (FRB)
The contents of FPR[FRB]
are placed into GPR[RT]
.
Special Registers altered:
CR0 (if Rc=1)
Architecture Note:
mffpr
is equivalent to the combination of stfd
followed by ld
.
Architecture Note:
mffpr
is a separate instruction from mfvsrd
because mfvsrd
requires
VSX which may not be available on simpler implementations.
Additionally, SVP64 may treat VSX instructions differently than SFFS
instructions in a future version of the architecture.
Move From Floating-Point Register Single
mffprs RT, FRB
mffprs. RT, FRB
0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|
PO | RT | // | FRB | XO | Rc | X-Form |
RT <- [0] * 32 || SINGLE((FRB))
The contents of FPR[FRB]
are converted to BFP32 by using SINGLE
, then
zero-extended to 64-bits, and the result stored in GPR[RT]
.
Special Registers altered:
CR0 (if Rc=1)
Architecture Note:
mffprs
is equivalent to the combination of stfs
followed by lwz
.
\newpage{}
Move To Floating-Point Register
mtfpr FRT, RB
0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|
PO | FRT | // | RB | XO | // | X-Form |
FRT <- (RB)
The contents of GPR[RB]
are placed into FPR[FRT]
.
Special Registers altered:
None
Architecture Note:
mtfpr
is equivalent to the combination of std
followed by lfd
.
Architecture Note:
mtfpr
is a separate instruction from mtvsrd
because mtvsrd
requires
VSX which may not be available on simpler implementations.
Additionally, SVP64 may treat VSX instructions differently than SFFS
instructions in a future version of the architecture.
Move To Floating-Point Register Single
mtfprs FRT, RB
0-5 | 6-10 | 11-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|
PO | FRT | // | RB | XO | // | X-Form |
FRT <- DOUBLE((RB)[32:63])
The contents of bits 32:63 of GPR[RB]
are converted to BFP64 by using
DOUBLE
, then the result is stored in GPR[RT]
.
Special Registers altered:
None
Architecture Note:
mtfprs
is equivalent to the combination of stw
followed by lfs
.
\newpage{}
Conversion To/From Floating-Point Register Instructions
Convert To Floating-Point Register
ctfpr FRT, RB, IT
ctfpr. FRT, RB, IT
0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|---|
PO | FRT | IT | // | RB | XO | Rc | X-Form |
if IT[0] = 0 then # 32-bit int -> 64-bit float
# rounding never necessary, so don't touch FPSCR
# based off xvcvsxwdp
if IT = 0 then # Signed 32-bit
src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
else # IT = 1 -- Unsigned 32-bit
src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
FRT <- bfp64_CONVERT_FROM_BFP(src)
else
# rounding may be necessary. based off xscvuxdsp
reset_xflags()
switch(IT)
case(0): # Signed 32-bit
src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
case(1): # Unsigned 32-bit
src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
case(2): # Signed 64-bit
src <- bfp_CONVERT_FROM_SI64((RB))
default: # Unsigned 64-bit
src <- bfp_CONVERT_FROM_UI64((RB))
rnd <- bfp_ROUND_TO_BFP64(0b0, FPSCR.RN, src)
result <- bfp64_CONVERT_FROM_BFP(rnd)
cls <- fprf_CLASS_BFP64(result)
if xx_flag = 1 then SetFX(FPSCR.XX)
FRT <- result
FPSCR.FPRF <- cls
FPSCR.FR <- inc_flag
FPSCR.FI <- xx_flag
Convert from a unsigned/signed 32/64-bit integer in RB to a 64-bit float in FRT.
If converting from a unsigned/signed 32-bit integer to a 64-bit float,
rounding is never necessary, so FPSCR
is unmodified and exceptions are
never raised. Otherwise, FPSCR
is modified and exceptions are raised
as usual.
Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point operations.
Special Registers altered:
CR1 (if Rc=1)
FPRF FR FI FX XX (if IT[0]=1)
Assembly Aliases
Assembly Alias | Full Instruction |
---|---|
ctfprw FRT, RB |
ctfpr FRT, RB, 0 |
ctfprw. FRT, RB |
ctfpr. FRT, RB, 0 |
ctfpruw FRT, RB |
ctfpr FRT, RB, 1 |
ctfpruw. FRT, RB |
ctfpr. FRT, RB, 1 |
ctfprd FRT, RB |
ctfpr FRT, RB, 2 |
ctfprd. FRT, RB |
ctfpr. FRT, RB, 2 |
ctfprud FRT, RB |
ctfpr FRT, RB, 3 |
ctfprud. FRT, RB |
ctfpr. FRT, RB, 3 |
\newpage{}
Convert To Floating-Point Register Single
ctfprs FRT, RB, IT
ctfprs. FRT, RB, IT
0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21-30 | 31 | Form |
---|---|---|---|---|---|---|---|
PO | FRT | IT | // | RB | XO | Rc | X-Form |
# rounding may be necessary. based off xscvuxdsp
reset_xflags()
switch(IT)
case(0): # Signed 32-bit
src <- bfp_CONVERT_FROM_SI32((RB)[32:63])
case(1): # Unsigned 32-bit
src <- bfp_CONVERT_FROM_UI32((RB)[32:63])
case(2): # Signed 64-bit
src <- bfp_CONVERT_FROM_SI64((RB))
default: # Unsigned 64-bit
src <- bfp_CONVERT_FROM_UI64((RB))
rnd <- bfp_ROUND_TO_BFP32(FPSCR.RN, src)
result32 <- bfp32_CONVERT_FROM_BFP(rnd)
cls <- fprf_CLASS_BFP32(result32)
result <- DOUBLE(result32)
if xx_flag = 1 then SetFX(FPSCR.XX)
FRT <- result
FPSCR.FPRF <- cls
FPSCR.FR <- inc_flag
FPSCR.FI <- xx_flag
Convert from a unsigned/signed 32/64-bit integer in RB to a 32-bit
float in FRT, following the usual 32-bit float in 64-bit float format.
FPSCR
is modified and exceptions are raised as usual.
Rc=1 tests FRT and sets CR1, exactly like all other Scalar Floating-Point operations.
Special Registers altered:
CR1 (if Rc=1)
FPRF FR FI FX XX
Assembly Aliases
Assembly Alias | Full Instruction |
---|---|
ctfprws FRT, RB |
ctfpr FRT, RB, 0 |
ctfprws. FRT, RB |
ctfpr. FRT, RB, 0 |
ctfpruws FRT, RB |
ctfpr FRT, RB, 1 |
ctfpruws. FRT, RB |
ctfpr. FRT, RB, 1 |
ctfprds FRT, RB |
ctfpr FRT, RB, 2 |
ctfprds. FRT, RB |
ctfpr. FRT, RB, 2 |
ctfpruds FRT, RB |
ctfpr FRT, RB, 3 |
ctfpruds. FRT, RB |
ctfpr. FRT, RB, 3 |
\newpage{}
Convert From Floating-Point Register
cffpr RT, FRB, CVM, IT
cffpr. RT, FRB, CVM, IT
cffpro RT, FRB, CVM, IT
cffpro. RT, FRB, CVM, IT
0-5 | 6-10 | 11-12 | 13-15 | 16-20 | 21 | 22-30 | 31 | Form |
---|---|---|---|---|---|---|---|---|
PO | RT | IT | CVM | FRB | OE | XO | Rc | XO-Form |
# based on xscvdpuxws
reset_xflags()
src <- bfp_CONVERT_FROM_BFP64((FRB))
switch(IT)
case(0): # Signed 32-bit
range_min <- bfp_CONVERT_FROM_SI32(0x8000_0000)
range_max <- bfp_CONVERT_FROM_SI32(0x7FFF_FFFF)
js_mask <- 0x0000_0000_FFFF_FFFF
case(1): # Unsigned 32-bit
range_min <- bfp_CONVERT_FROM_UI32(0)
range_max <- bfp_CONVERT_FROM_UI32(0xFFFF_FFFF)
js_mask <- 0x0000_0000_FFFF_FFFF
case(2): # Signed 64-bit
range_min <- bfp_CONVERT_FROM_SI64(-0x8000_0000_0000_0000)
range_max <- bfp_CONVERT_FROM_SI64(0x7FFF_FFFF_FFFF_FFFF)
js_mask <- 0xFFFF_FFFF_FFFF_FFFF
default: # Unsigned 64-bit
range_min <- bfp_CONVERT_FROM_UI64(0)
range_max <- bfp_CONVERT_FROM_UI64(0xFFFF_FFFF_FFFF_FFFF)
js_mask <- 0xFFFF_FFFF_FFFF_FFFF
if (CVM[2] = 1) | (FPSCR.RN = 0b01) then
rnd <- bfp_ROUND_TO_INTEGER_TRUNC(src)
else if FPSCR.RN = 0b00 then
rnd <- bfp_ROUND_TO_INTEGER_NEAR_EVEN(src)
else if FPSCR.RN = 0b10 then
rnd <- bfp_ROUND_TO_INTEGER_CEIL(src)
else if FPSCR.RN = 0b11 then
rnd <- bfp_ROUND_TO_INTEGER_FLOOR(src)
switch(CVM)
case(0, 1): # P-Type
if IsNaN(rnd) then
result <- si64_CONVERT_FROM_BFP(range_min)
else if bfp_COMPARE_GT(rnd, range_max) then
result <- ui64_CONVERT_FROM_BFP(range_max)
else if bfp_COMPARE_LT(rnd, range_min) then
result <- si64_CONVERT_FROM_BFP(range_min)
else if IT[1] = 1 then # Unsigned 32/64-bit
result <- ui64_CONVERT_FROM_BFP(rnd)
else # Signed 32/64-bit
result <- si64_CONVERT_FROM_BFP(rnd)
case(2, 3): # S-Type
if IsNaN(rnd) then
result <- [0] * 64
else if bfp_COMPARE_GT(rnd, range_max) then
result <- ui64_CONVERT_FROM_BFP(range_max)
else if bfp_COMPARE_LT(rnd, range_min) then
result <- si64_CONVERT_FROM_BFP(range_min)
else if IT[1] = 1 then # Unsigned 32/64-bit
result <- ui64_CONVERT_FROM_BFP(rnd)
else # Signed 32/64-bit
result <- si64_CONVERT_FROM_BFP(rnd)
default: # E-Type
# CVM = 6, 7 are illegal instructions
# using a 128-bit intermediate works here because the largest type
# this instruction can convert from has 53 significand bits, and
# the largest type this instruction can convert to has 64 bits,
# and the sum of those is strictly less than the 128 bits of the
# intermediate result.
limit <- bfp_CONVERT_FROM_UI128([1] * 128)
if IsInf(rnd) | IsNaN(rnd) then
result <- [0] * 64
else if bfp_COMPARE_GT(bfp_ABSOLUTE(rnd), limit) then
result <- [0] * 64
else
result128 <- si128_CONVERT_FROM_BFP(rnd)
result <- result128[64:127] & js_mask
switch(IT)
case(0): # Signed 32-bit
result <- EXTS64(result[32:63])
result_bfp <- bfp_CONVERT_FROM_SI32(result[32:63])
case(1): # Unsigned 32-bit
result <- EXTZ64(result[32:63])
result_bfp <- bfp_CONVERT_FROM_UI32(result[32:63])
case(2): # Signed 64-bit
result_bfp <- bfp_CONVERT_FROM_SI64(result)
default: # Unsigned 64-bit
result_bfp <- bfp_CONVERT_FROM_UI64(result)
overflow <- 0 # signals SO only when OE = 1
if IsNaN(src) | ¬bfp_COMPARE_EQ(rnd, result_bfp) then
overflow <- 1 # signals SO only when OE = 1
vxcvi_flag <- 1
xx_flag <- 0
inc_flag <- 0
else
xx_flag <- ¬bfp_COMPARE_EQ(src, result_bfp)
inc_flag <- bfp_COMPARE_GT(bfp_ABSOLUTE(result_bfp), bfp_ABSOLUTE(src))
if vxsnan_flag = 1 then SetFX(FPSCR.VXSNAN)
if vxcvi_flag = 1 then SetFX(FPSCR.VXCVI)
if xx_flag = 1 then SetFX(FPSCR.XX)
vx_flag <- vxsnan_flag | vxcvi_flag
vex_flag <- FPSCR.VE & vx_flag
if vex_flag = 0 then
RT <- result
FPSCR.FPRF <- undefined
FPSCR.FR <- inc_flag
FPSCR.FI <- xx_flag
else
FPSCR.FR <- 0
FPSCR.FI <- 0
Convert from 64-bit float in FRB to a unsigned/signed 32/64-bit integer
in RT, with the conversion overflow/rounding semantics following the
chosen CVM
value. FPSCR
is modified and exceptions are raised as usual.
This instruction has an Rc=1 mode which sets CR0 in the normal
way for any instructions producing a GPR result. Additionally, when OE=1,
if the numerical value of the FP number is not 100% accurately preserved
(due to truncation or saturation and including when the FP number was
NaN) then this is considered to be an Integer Overflow condition, and
CR0.SO, XER.SO and XER.OV are all set as normal for any GPR instructions
that overflow. When RT
is not written (vex_flag = 1
), all CR0 bits
except SO are undefined.
Special Registers altered:
CR0 (if Rc=1)
XER SO, OV, OV32 (if OE=1)
FPRF=0bUUUUU FR FI FX XX VXSNAN VXCV
Assembly Aliases
Assembly Alias | Full Instruction |
---|---|
cffprw RT, FRB, CVM |
cffpr RT, FRB, CVM, 0 |
cffprw. RT, FRB, CVM |
cffpr. RT, FRB, CVM, 0 |
cffprwo RT, FRB, CVM |
cffpro RT, FRB, CVM, 0 |
cffprwo. RT, FRB, CVM |
cffpro. RT, FRB, CVM, 0 |
cffpruw RT, FRB, CVM |
cffpr RT, FRB, CVM, 1 |
cffpruw. RT, FRB, CVM |
cffpr. RT, FRB, CVM, 1 |
cffpruwo RT, FRB, CVM |
cffpro RT, FRB, CVM, 1 |
cffpruwo. RT, FRB, CVM |
cffpro. RT, FRB, CVM, 1 |
cffprd RT, FRB, CVM |
cffpr RT, FRB, CVM, 2 |
cffprd. RT, FRB, CVM |
cffpr. RT, FRB, CVM, 2 |
cffprdo RT, FRB, CVM |
cffpro RT, FRB, CVM, 2 |
cffprdo. RT, FRB, CVM |
cffpro. RT, FRB, CVM, 2 |
cffprud RT, FRB, CVM |
cffpr RT, FRB, CVM, 3 |
cffprud. RT, FRB, CVM |
cffpr. RT, FRB, CVM, 3 |
cffprudo RT, FRB, CVM |
cffpro RT, FRB, CVM, 3 |
cffprudo. RT, FRB, CVM |
cffpro. RT, FRB, CVM, 3 |