# 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 | `w` | | 1 | Unsigned 32-bit | `uw` | | 2 | Signed 64-bit | `d` | | 3 | Unsigned 64-bit | `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 | [P-Type]: #fpr-to-gpr-conversion-p-type [S-Type]: #fpr-to-gpr-conversion-s-type [E-Type]: #fpr-to-gpr-conversion-e-type ---------- \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` |