fpu got exception flag right for add/sub/mul/i2f/f2i

This commit is contained in:
Dolu1990 2021-02-05 16:24:14 +01:00
parent 936e5823dc
commit 6170243283
3 changed files with 190 additions and 91 deletions

View File

@ -451,6 +451,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val recoded = CombInit(input.rs1)
val flag = io.port(input.source).completion.flag
val halt = False
val recodedResult = Bits(32 bits)//recoded.asBits.resize(32 bits)
@ -522,6 +523,10 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
is(FpuFloat.NAN){
recodedResult(23, 8 bits).setAll()
when(input.rs1.isCanonical){
recodedResult(31) := False
recodedResult(0, 22 bits) := 0
}
}
}
}
@ -540,8 +545,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
FpuRoundMode.RMM -> (round(1))
)
val result = (Mux(resign, ~unsigned, unsigned) + (resign ^ increment).asUInt)
val overflow = RegNext((input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne+31)) || input.rs1.isInfinity) && !input.rs1.sign || input.rs1.isNan)
val underflow = RegNext((input.rs1.exponent > U(exponentOne+30) || !input.arg(0) || input.rs1.isInfinity) && input.rs1.sign)
val overflow = (input.rs1.exponent > (input.arg(0) ? U(exponentOne+30) | U(exponentOne+31)) || input.rs1.isInfinity) && !input.rs1.sign || input.rs1.isNan
val underflow = (input.rs1.exponent > U(exponentOne+31) || input.arg(0) && unsigned.msb && unsigned(30 downto 0) =/= 0 || !input.arg(0) && (unsigned =/= 0 || increment) || input.rs1.isInfinity) && input.rs1.sign
val isZero = input.rs1.isZero
when(isZero){
result := 0
@ -549,6 +554,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val low = overflow
val high = input.arg(0) ^ overflow
result := (31 -> high, default -> low)
flag.NV := input.valid && input.opcode === FpuOpcode.F2I && fsm.done && !isZero
}
}
@ -648,8 +654,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
scrap setWhen(needShift && mulHigh(0))
val forceZero = input.rs1.isZero || input.rs2.isZero
val forceUnderflow = exp < exponentOne + exponentOne - 127 - 24 // 0x6A //TODO
val forceOverflow = /*exp > exponentOne + exponentOne + 127 || */input.rs1.isInfinity || input.rs2.isInfinity
val forceNan = input.rs1.isNan || input.rs2.isNan || ((input.rs1.isInfinity || input.rs2.isInfinity) && (input.rs1.isZero || input.rs2.isZero))
val forceOverflow = input.rs1.isInfinity || input.rs2.isInfinity
val infinitynan = ((input.rs1.isInfinity || input.rs2.isInfinity) && (input.rs1.isZero || input.rs2.isZero))
val forceNan = input.rs1.isNan || input.rs2.isNan || infinitynan
val output = p.writeFloating()
output.sign := input.rs1.sign ^ input.rs2.sign
@ -657,8 +664,10 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.mantissa := man.asUInt
output.setNormal
val flag = io.port(input.source).completion.flag
when(forceNan) {
output.setNanQuiet
flag.NV setWhen(input.valid && (infinitynan || input.rs1.isNanSignaling || input.rs2.isNanSignaling))
} elsewhen(forceOverflow) {
output.setInfinity
} elsewhen(forceZero) {
@ -936,7 +945,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
val forceZero = xyMantissa === 0 || (input.rs1.isZero && input.rs2.isZero)
// val forceOverflow = exponent === exponentOne + 128 //Handled by writeback rounding
val forceInfinity = (input.rs1.isInfinity || input.rs2.isInfinity)
val forceNan = input.rs1.isNan || input.rs2.isNan || (input.rs1.isInfinity && input.rs2.isInfinity && (input.rs1.sign ^ input.rs2.sign))
val infinityNan = (input.rs1.isInfinity && input.rs2.isInfinity && (input.rs1.sign ^ input.rs2.sign))
val forceNan = input.rs1.isNan || input.rs2.isNan || infinityNan
}
@ -951,6 +961,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
output.roundMode := input.roundMode
output.scrap := (norm.mantissa(1) | norm.mantissa(0) | shifter.roundingScrap)
val flag = io.port(input.source).completion.flag
flag.NV setWhen(input.valid && (norm.infinityNan || input.rs1.isNanSignaling || input.rs2.isNanSignaling))
when(norm.forceNan) {
output.value.setNanQuiet
} elsewhen(norm.forceZero) {
@ -963,21 +976,7 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
} elsewhen(norm.forceInfinity) {
output.value.setInfinity
} /*elsewhen(norm.forceOverflow) {
val doMax = input.roundMode.mux(
FpuRoundMode.RNE -> (False),
FpuRoundMode.RTZ -> (True),
FpuRoundMode.RDN -> (!output.value.sign),
FpuRoundMode.RUP -> (output.value.sign),
FpuRoundMode.RMM -> (False)
)
when(doMax){
output.value.exponent := exponentOne + 127
output.value.mantissa.setAll()
} otherwise {
output.value.setInfinity
}
}*/
}
@ -993,8 +992,9 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
//TODO do not break NAN payload (seems already fine)
val manAggregate = input.value.mantissa @@ input.scrap
val expDif = (exponentOne-126) - input.value.exponent
val discardCount = expDif.msb ? U(0) | expDif.resize(log2Up(p.internalMantissaSize) bits)
val expDif = (exponentOne-126) -^ input.value.exponent
val expSubnormal = !expDif.msb
val discardCount = expSubnormal ? expDif.resize(log2Up(p.internalMantissaSize) bits) | U(0)
val exactMask = (List(True) ++ (0 until p.internalMantissaSize+1).map(_ < discardCount)).asBits.asUInt
val roundAdjusted = (True ## (manAggregate>>1))(discardCount) ## ((manAggregate & exactMask) =/= 0)
@ -1017,8 +1017,18 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
math.mantissa := adder(0, p.internalMantissaSize bits)
val patched = CombInit(math)
val nx,of,uf = False
// val ufPatch = input.roundMode === FpuRoundMode.RUP && !input.value.sign && !input.scrap|| input.roundMode === FpuRoundMode.RDN && input.value.sign && !input.scrap
// when(!math.special && (input.value.exponent <= exponentOne-127 && (math.exponent =/= exponentOne-126 || !input.value.mantissa.lsb || ufPatch)) && roundAdjusted.asUInt =/= 0){
// uf := True
// }
when(!math.special && math.exponent <= exponentOne-127 && roundAdjusted.asUInt =/= 0){ //Do not catch exact 1.17549435E-38 underflow, but, who realy care ?
uf := True
}
when(!math.special && math.exponent >= exponentOne + 128){
// patched.setInfinity
nx := True
of := True
val doMax = input.roundMode.mux(
FpuRoundMode.RNE -> (False),
FpuRoundMode.RTZ -> (True),
@ -1036,6 +1046,8 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
when(!math.special && math.exponent <= exponentOne - 127-23){
nx := True
uf := True
val doMin = input.roundMode.mux(
FpuRoundMode.RNE -> (False),
FpuRoundMode.RTZ -> (False),
@ -1051,6 +1063,14 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
}
}
nx setWhen(!input.value.special && (roundAdjusted =/= 0))
when(input.valid){
val flag = io.port(input.source).completion.flag
flag.NX setWhen(nx)
flag.OF setWhen(of)
flag.UF setWhen(uf)
}
val output = input.swapPayload(RoundOutput())
output.source := input.source
output.lockId := input.lockId
@ -1079,8 +1099,11 @@ case class FpuCore( portCount : Int, p : FpuParameter) extends Component{
if(p.sim) when(port.data.isZero || port.data.isInfinity){
port.data.mantissa.assignDontCare()
}
if(p.sim) when(port.data.special){
port.data.exponent(p.internalExponentSize-1 downto 2).assignDontCare()
if(p.sim) when(input.value.special){
port.data.exponent(p.internalExponentSize-1 downto 3).assignDontCare()
when(!input.value.isNan){
port.data.exponent(2 downto 2).assignDontCare()
}
}
when(port.valid){

View File

@ -27,6 +27,7 @@ object FpuFloat{
val ZERO = 0
val INFINITY = 1
val NAN = 2
val NAN_CANONICAL_BIT = 2
}
case class FpuFloat(exponentSize: Int,
@ -49,12 +50,14 @@ case class FpuFloat(exponentSize: Int,
def isInfinity = special && exponent(1 downto 0) === FpuFloat.INFINITY
def isNan = special && exponent(1 downto 0) === FpuFloat.NAN
def isQuiet = mantissa.msb
def isNanSignaling = special && exponent(1 downto 0) === FpuFloat.NAN && !isQuiet
def isCanonical = exponent(FpuFloat.NAN_CANONICAL_BIT)
def setNormal = { special := False }
def setZero = { special := True; exponent(1 downto 0) := FpuFloat.ZERO }
def setInfinity = { special := True; exponent(1 downto 0) := FpuFloat.INFINITY }
def setNan = { special := True; exponent(1 downto 0) := FpuFloat.NAN }
def setNanQuiet = { special := True; exponent(1 downto 0) := FpuFloat.NAN ; mantissa.msb := True }
def setNan = { special := True; exponent(1 downto 0) := FpuFloat.NAN; exponent(FpuFloat.NAN_CANONICAL_BIT) := False}
def setNanQuiet = { special := True; exponent(1 downto 0) := FpuFloat.NAN; exponent(FpuFloat.NAN_CANONICAL_BIT) := True; mantissa.msb := True; }
def decode() = {
val ret = FpuFloatDecoded()

View File

@ -23,7 +23,7 @@ import scala.util.Random
class FpuTest extends FunSuite{
val b2f = lang.Float.intBitsToFloat(_)
val f2b = lang.Float.floatToIntBits(_)
val f2b = lang.Float.floatToRawIntBits(_)
def clamp(f : Float) = {
f // if(f.abs < b2f(0x00800000)) b2f(f2b(f) & 0x80000000) else f
@ -38,9 +38,11 @@ class FpuTest extends FunSuite{
)
val config = SimConfig
// config.withFstWave
config.allOptimisation
config.withFstWave
config.compile(new FpuCore(portCount, p){
for(i <- 0 until portCount) out(Bits(5 bits)).setName(s"flagAcc$i") := io.port(i).completion.flag.asBits
setDefinitionName("FpuCore")
}).doSim(seed = 42){ dut =>
dut.clockDomain.forkStimulus(10)
dut.clockDomain.forkSimSpeedPrinter(5.0)
@ -48,10 +50,29 @@ class FpuTest extends FunSuite{
class TestCase(op : String){
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -forever -$op"){
def f32_2 ={
def build(arg : String) = new ProcessStream(s"testfloat_gen $arg -tininessafter -forever -$op"){
def f32_f32 ={
val s = new Scanner(next)
(b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), b2f(s.nextLong(16).toInt), s.nextInt(16))
val a,b,c = (s.nextLong(16).toInt)
// if(b2f(a).isNaN || b2f(b).isNaN){
// print("NAN => ")
// if(((a >> 23) & 0xFF) == 0xFF && ((a >> 0) & 0xEFFFFF) != 0){
// print(a.toHexString)
// print(" " + f2b(b2f(a)).toHexString)
// }
// if(((b >> 23) & 0xFF) == 0xFF && ((b >> 0) & 0xEFFFFF) != 0){
// print(b.toHexString)
// print(" " + f2b(b2f(b)).toHexString)
// }
// if(((c >> 23) & 0xFF) == 0xFF && ((c >> 0) & 0xEFFFFF) != 0){
// print(" " + c.toHexString)
// print(" " + f2b(b2f(c)).toHexString)
// }
//
// print(" " + simTime())
// println("")
// }
(b2f(a), b2f(b), b2f(c), s.nextInt(16))
}
def i32_f32 ={
@ -95,18 +116,26 @@ class FpuTest extends FunSuite{
val commitQueue = mutable.Queue[FpuCommit => Unit]()
val rspQueue = mutable.Queue[FpuRsp => Unit]()
var pending = 0
var pendingMiaou = 0
var flagAccumulator = 0
def cmdAdd(body : FpuCmd => Unit): Unit ={
pending += 1
pendingMiaou += 1
cmdQueue += body
}
def softAssert(cond : Boolean, msg : String) = if(!cond)println(msg)
def flagMatch(ref : Int, value : Float, report : String): Unit ={
waitUntil(pendingMiaou == 0)
val patch = if(value.abs == 1.17549435E-38f) ref & ~2 else ref
assert(flagAccumulator == patch, s"Flag missmatch dut=$flagAccumulator ref=$patch $report")
flagAccumulator = 0
}
val flagAggregated = dut.reflectBaseType(s"flagAcc$id").asInstanceOf[Bits]
dut.clockDomain.onSamplings{
val c = dut.io.port(id).completion
pending -= c.count.toInt
pendingMiaou -= c.count.toInt
flagAccumulator |= flagAggregated.toInt
}
@ -152,7 +181,7 @@ class FpuTest extends FunSuite{
}
def load(rd : Int, value : Float): Unit ={
loadRaw(rd, lang.Float.floatToIntBits(value).toLong & 0xFFFFFFFFl)
loadRaw(rd, f2b(value).toLong & 0xFFFFFFFFl)
}
def storeRaw(rs : Int)(body : FpuRsp => Unit): Unit ={
@ -166,7 +195,7 @@ class FpuTest extends FunSuite{
}
rspQueue += body
waitUntil(rspQueue.isEmpty)
// waitUntil(rspQueue.isEmpty)
}
def storeFloat(rs : Int)(body : Float => Unit): Unit ={
@ -385,6 +414,9 @@ class FpuTest extends FunSuite{
storeFloat(rd){v =>
assert(f2b(v) == f2b(ref), f"## ${a} ${opName} $b = $v, $ref $rounding")
}
flagMatch(flag, ref, f"## ${opName} ${a} $b $ref $rounding")
}
def testAddExact(a : Float, b : Float, ref : Float, flag : Int, rounding : FpuRoundMode.E): Unit ={
@ -538,6 +570,8 @@ class FpuTest extends FunSuite{
assert(v == ref2, f" <= f2ui($a) = $v, $ref2, $rounding $flag")
}
}
flagMatch(flag, ref, f" f2${if(signed) "" else "u"}i($a) $ref $flag $rounding")
}
@ -563,6 +597,9 @@ class FpuTest extends FunSuite{
val ref = b
assert(f2b(v) == f2b(ref), f"i2f($aLong) = $v, $ref")
}
flagMatch(f, b, f"i2f() = $b")
}
@ -589,7 +626,7 @@ class FpuTest extends FunSuite{
val rd = Random.nextInt(32)
load(rs1, a)
fmv_x_w(rs1){rsp =>
val ref = lang.Float.floatToIntBits(a).toLong & 0xFFFFFFFFl
val ref = f2b(a).toLong & 0xFFFFFFFFl
val v = rsp.value.toBigInt
println(f"fmv_x_w $a = $v, $ref")
assert(v === ref)
@ -682,48 +719,16 @@ class FpuTest extends FunSuite{
val binaryOps = List[(Int,Int,Int,FpuRoundMode.E) => Unit](add, sub, mul)
testI2f(24, false)
testI2f(17, false)
testLoadStore(2.5f)
testLoadStore(3.67341984632e-40f)
testLoadStore(5.5321021294e-40f)
testF2iExact(-2.14748365E9f, -2147483648, 0, true, FpuRoundMode.RDN)
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.add(rounding).f32_2
testBinaryOp(add,a,b,c,f, rounding,"add")
}
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.sub(rounding).f32_2
testBinaryOp(sub,a,b,c,f, rounding,"sub")
}
println("Add done")
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.i2f(rounding).i32_f32
testI2fExact(a,b,f, true, rounding)
}
for(_ <- 0 until 100000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.ui2f(rounding).i32_f32
testI2fExact(a,b,f, false, rounding)
}
println("i2f done")
for(_ <- 0 until 100000){
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.f2ui(rounding).f32_i32
testF2iExact(a,b, f, false, rounding)
}
for(_ <- 0 until 100000){
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.f2i(rounding).f32_i32
testF2iExact(a,b, f, true, rounding)
@ -731,17 +736,63 @@ class FpuTest extends FunSuite{
println("f2i done")
for(_ <- 0 until 100000){
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_2
val (a,b,f) = f32.i2f(rounding).i32_f32
testI2fExact(a,b,f, true, rounding)
}
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,f) = f32.ui2f(rounding).i32_f32
testI2fExact(a,b,f, false, rounding)
}
println("i2f done")
testBinaryOp(mul,1.469368E-39f, 7.9999995f, 1.17549435E-38f,3, FpuRoundMode.RUP,"mul")
testBinaryOp(mul,1.1753509E-38f, 1.0001221f, 1.17549435E-38f ,1, FpuRoundMode.RUP,"mul")
testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RNE,"mul")
testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RDN,"mul")
testBinaryOp(mul, 1.1754942E-38f, -1.0000001f, -1.17549435E-38f,1, FpuRoundMode.RMM,"mul")
testBinaryOp(mul, 1.1754945E-38f, 0.9999998f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
testBinaryOp(mul, 1.1754945E-38f, -0.9999998f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
testBinaryOp(mul, 1.1754946E-38f, 0.9999997f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
testBinaryOp(mul, 1.1754946E-38f, -0.9999997f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
testBinaryOp(mul, 1.1754949E-38f, 0.99999946f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
testBinaryOp(mul, 1.1754949E-38f, -0.99999946f, -1.17549435E-38f, 3, FpuRoundMode.RDN, "mul")
testBinaryOp(mul, 1.1754955E-38f, 0.999999f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.mul(rounding).f32_f32
testBinaryOp(mul,a,b,c,f, rounding,"mul")
}
println("Mul done")
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.add(rounding).f32_f32
testBinaryOp(add,a,b,c,f, rounding,"add")
}
for(_ <- 0 until 10000){
val rounding = FpuRoundMode.elements.randomPick()
val (a,b,c,f) = f32.sub(rounding).f32_f32
testBinaryOp(sub,a,b,c,f, rounding,"sub")
}
println("Add done")
@ -823,7 +874,7 @@ class FpuTest extends FunSuite{
testLoadStore(1.765f)
testFmv_w_x(lang.Float.floatToIntBits(7.234f))
testFmv_w_x(f2b(7.234f))
testI2f(64, false)
for(i <- iUnsigned) testI2f(i, false)
for(i <- iSigned) testI2f(i, true)
@ -874,7 +925,7 @@ class FpuTest extends FunSuite{
testFmv_x_w(1.246f)
testFmv_w_x(lang.Float.floatToIntBits(7.234f))
testFmv_w_x(f2b(7.234f))
testMin(1.0f, 2.0f)
testMin(1.5f, 2.0f)
@ -989,7 +1040,7 @@ class FpuTest extends FunSuite{
tests += (() =>{testSqrt(randomFloat().abs)})
tests += (() =>{testCmp(randomFloat(), randomFloat())})
tests += (() =>{testFmv_x_w(randomFloat())})
tests += (() =>{testFmv_w_x(lang.Float.floatToIntBits(randomFloat()))})
tests += (() =>{testFmv_w_x(f2b(randomFloat()))})
tests += (() =>{testMin(randomFloat(), randomFloat())})
tests += (() =>{testSgnj(randomFloat(), randomFloat())})
@ -1018,15 +1069,37 @@ object Clib {
DoCmd.doCmd(cmd)
val math = new FpuMath
}
// cd /media/data/open/SaxonSoc/testFloatBuild/berkeley-softfloat-3/build/Linux-x86_64-GCC
// make clean && SPECIALIZE_TYPE=RISCV make -j$(nproc) && cp softfloat.a /media/data/open/SaxonSoc/artyA7SmpUpdate/SaxonSoc/ext/VexRiscv/src/test/cpp/fpu/math
object FpuCompileSo extends App{
val b2f = lang.Float.intBitsToFloat(_)
for(e <- FpuRoundMode.elements) {
println(e)
for (i <- -2 until 50) println(i + " => " + Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000 + i), e.position))
println("")
}
// val b2f = lang.Float.intBitsToFloat(_)
// for(e <- FpuRoundMode.elements) {
// println(e)
// for (i <- -2 until 50) println(i + " => " + Clib.math.addF32(b2f(0x7f000000), b2f(0x7f000000 + i), e.position))
// println("")
// }
//1 did not equal 3 Flag missmatch dut=1 ref=3 ## mul 0.9994812 -1.1754988E-38 -1.174889E-38 RMM
// println(Clib.math.mulF32(0.9994812f, -1.1754988E-38f, FpuRoundMode.RMM.position))
// miaou ffffffff 7fffffe0 7f
// miaou 0 3ffffff0 70 = 0
println(Clib.math.mulF32( 1.1753509E-38f, 1.0001221f, FpuRoundMode.RUP.position))
println(Clib.math.mulF32( 1.1754945E-38f, 0.9999998f, FpuRoundMode.RUP.position))
// testBinaryOp(mul, 1.1753509E-38f, 1.0001221f, 1.17549435E-38f ,1, FpuRoundMode.RUP,"mul")
// testBinaryOp(mul, 1.1754945E-38f, 0.9999998f, 1.17549435E-38f, 3, FpuRoundMode.RUP, "mul")
// miaou ffffffff 7fffffe0 7f
// miaou 0 3ffffff0 70 = 0
// miaou ffffffff 7fffff7e 7f
// miaou 1 3fffffbf 3f = 1
// println(Clib.math.mulF32( 1.1753509E-38f, 1.0001221f, FpuRoundMode.RUP.position))
// println(Clib.math.mulF32( 1.469368E-39f, 7.9999995f, FpuRoundMode.RUP.position))
// println(Clib.math.mulF32( 1.40129846432e-45f, 7.9999995f, FpuRoundMode.RUP.position))
// println(Clib.math.mulF32( 2.93873587706e-39f, 7.9999995f, FpuRoundMode.RUP.position))
// println(Clib.math.mulF32( 1f, 7.9999995f, FpuRoundMode.RUP.position))
// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RNE.position))
// println(Clib.math.addF32(1.00000011921f, 4.0f, FpuRoundMode.RTZ.position))