pan/bit: Add BI_CONVERT interpretation
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 13 Apr 2020 20:38:40 +0000 (16:38 -0400)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Apr 2020 22:32:40 +0000 (22:32 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4539>

src/panfrost/bifrost/test/bi_interpret.c

index f0068398df49d4e0a4d3d5b9f651ab0269aca774..2f3295772d92ed986966953dd7bbd8949be1c75f 100644 (file)
@@ -264,6 +264,82 @@ biti_special(float Q, enum bi_special_op op)
         }
 }
 
+/* For BI_CONVERT. */
+
+#define _AS_ROUNDMODE(mode) \
+        ((mode == BIFROST_RTZ) ? FP_INT_TOWARDZERO : \
+        (mode == BIFROST_RTE) ? FP_INT_TONEAREST : \
+        (mode == BIFROST_RTN) ? FP_INT_DOWNWARD : \
+        FP_INT_UPWARD)
+
+static float
+bit_as_float32(nir_alu_type T, bit_t src, unsigned C)
+{
+        switch (T) {
+        case nir_type_int32:   return src.i32;
+        case nir_type_uint32:  return src.u32;
+        case nir_type_float16: return bf(src.u16[C]);
+        default: unreachable("Invalid");
+        }
+}
+
+static uint32_t
+bit_as_uint32(nir_alu_type T, bit_t src, unsigned C, enum bifrost_roundmode rm)
+{
+        switch (T) {
+        case nir_type_float16: return bf(src.u16[C]);
+        case nir_type_float32: return ufromfpf(src.f32, _AS_ROUNDMODE(rm), 32);
+        default: unreachable("Invalid");
+        }
+}
+
+static int32_t
+bit_as_int32(nir_alu_type T, bit_t src, unsigned C, enum bifrost_roundmode rm)
+{
+        switch (T) {
+        case nir_type_float16: return bf(src.u16[C]);
+        case nir_type_float32: return fromfpf(src.f32, _AS_ROUNDMODE(rm), 32);
+        default: unreachable("Invalid");
+        }
+}
+
+static uint16_t
+bit_as_float16(nir_alu_type T, bit_t src, unsigned C)
+{
+        switch (T) {
+        case nir_type_int32:   return bh(src.i32);
+        case nir_type_uint32:  return bh(src.u32);
+        case nir_type_float32: return bh(src.f32);
+        case nir_type_int16:   return bh(src.i16[C]);
+        case nir_type_uint16:  return bh(src.u16[C]);
+        default: unreachable("Invalid");
+        }
+}
+
+static uint16_t
+bit_as_uint16(nir_alu_type T, bit_t src, unsigned C, enum bifrost_roundmode rm)
+{
+        switch (T) {
+        case nir_type_int32:   return src.i32;
+        case nir_type_uint32:  return src.u32;
+        case nir_type_float16: return ufromfpf(bf(src.u16[C]), _AS_ROUNDMODE(rm), 16);
+        case nir_type_float32: return src.f32;
+        default: unreachable("Invalid");
+        }
+}
+
+static int16_t
+bit_as_int16(nir_alu_type T, bit_t src, unsigned C, enum bifrost_roundmode rm)
+{
+        switch (T) {
+        case nir_type_int32:   return src.i32;
+        case nir_type_uint32:  return src.u32;
+        case nir_type_float16: return fromfpf(bf(src.u16[C]), _AS_ROUNDMODE(rm), 16);
+        case nir_type_float32: return src.f32;
+        default: unreachable("Invalid");
+        }
+}
+
 void
 bit_step(struct bit_state *s, bi_instruction *ins, bool FMA)
 {
@@ -300,9 +376,40 @@ bit_step(struct bit_state *s, bi_instruction *ins, bool FMA)
         case BI_BRANCH:
         case BI_CMP:
         case BI_BITWISE:
-        case BI_CONVERT:
                 unreachable("Unsupported op");
 
+        case BI_CONVERT: {
+                /* If it exists */
+                unsigned comp = ins->swizzle[0][1];
+
+                if (ins->dest_type == nir_type_float32)
+                        dest.f32 = bit_as_float32(ins->src_types[0], srcs[0], comp);
+                else if (ins->dest_type == nir_type_uint32)
+                        dest.u32 = bit_as_uint32(ins->src_types[0], srcs[0], comp, ins->roundmode);
+                else if (ins->dest_type == nir_type_int32)
+                        dest.i32 = bit_as_int32(ins->src_types[0], srcs[0], comp, ins->roundmode);
+                else if (ins->dest_type == nir_type_float16) {
+                        dest.u16[0] = bit_as_float16(ins->src_types[0], srcs[0], ins->swizzle[0][0]);
+
+                        if (ins->src_types[0] == nir_type_float32) {
+                                /* TODO: Second argument */
+                                dest.u16[1] = 0;
+                        } else {
+                                dest.u16[1] = bit_as_float16(ins->src_types[0], srcs[0], ins->swizzle[0][1]);
+                        }
+                } else if (ins->dest_type == nir_type_uint16) {
+                        dest.u16[0] = bit_as_uint16(ins->src_types[0], srcs[0], ins->swizzle[0][0], ins->roundmode);
+                        dest.u16[1] = bit_as_uint16(ins->src_types[0], srcs[0], ins->swizzle[0][1], ins->roundmode);
+                } else if (ins->dest_type == nir_type_int16) {
+                        dest.i16[0] = bit_as_int16(ins->src_types[0], srcs[0], ins->swizzle[0][0], ins->roundmode);
+                        dest.i16[1] = bit_as_int16(ins->src_types[0], srcs[0], ins->swizzle[0][1], ins->roundmode);
+                } else {
+                        unreachable("Unknown convert type");
+                }
+
+                break;
+        }
+
         case BI_CSEL: {
                 bool direct = ins->csel_cond == BI_COND_ALWAYS;
                 bool cond = direct ? srcs[0].u32 :