glsl: Add "built-in" functions to do fp32_to_fp64(fp32)
authorElie Tournier <tournier.elie@gmail.com>
Wed, 9 Aug 2017 22:11:08 +0000 (23:11 +0100)
committerMatt Turner <mattst88@gmail.com>
Thu, 10 Jan 2019 00:42:40 +0000 (16:42 -0800)
Signed-off-by: Elie Tournier <elie.tournier@collabora.com>
src/compiler/glsl/float64.glsl

index 8cc0a27..05e07d3 100644 (file)
@@ -1045,3 +1045,41 @@ __fp64_to_fp32(uint64_t __a)
    zFrac = mix(zFrac, zFrac | 0x40000000u, aExp != 0);
    return __roundAndPackFloat32(aSign, aExp - 0x381, zFrac);
 }
+
+/* Returns the result of converting the single-precision floating-point value
+ * `a' to the double-precision floating-point format.
+ */
+uint64_t
+__fp32_to_fp64(float f)
+{
+   uint a = floatBitsToUint(f);
+   uint aFrac = a & 0x007FFFFFu;
+   int aExp = int((a>>23) & 0xFFu);
+   uint aSign = a>>31;
+   uint zFrac0 = 0u;
+   uint zFrac1 = 0u;
+
+   if (aExp == 0xFF) {
+      if (aFrac != 0u) {
+         uint nanLo = 0u;
+         uint nanHi = a<<9;
+         __shift64Right(nanHi, nanLo, 12, nanHi, nanLo);
+         nanHi |= ((aSign<<31) | 0x7FF80000u);
+         return packUint2x32(uvec2(nanLo, nanHi));
+      }
+      return __packFloat64(aSign, 0x7FF, 0u, 0u);
+    }
+
+   if (aExp == 0) {
+      if (aFrac == 0u)
+         return __packFloat64(aSign, 0, 0u, 0u);
+      /* Normalize subnormal */
+      int shiftCount = __countLeadingZeros32(aFrac) - 8;
+      aFrac <<= shiftCount;
+      aExp = 1 - shiftCount;
+      --aExp;
+   }
+
+   __shift64Right(aFrac, 0u, 3, zFrac0, zFrac1);
+   return __packFloat64(aSign, aExp + 0x380, zFrac0, zFrac1);
+}