nir_alu_type to_base = nir_alu_type_get_base_type(ins->dest_type);
unsigned to_size = nir_alu_type_get_type_size(ins->dest_type);
bool to_unsigned = to_base == nir_type_uint;
+ bool to_float = to_base == nir_type_float;
/* Sanity check */
assert((from_base != to_base) || (from_size != to_size));
assert((MAX2(from_size, to_size) / MIN2(from_size, to_size)) <= 2);
- if (from_size == 16 && to_size == 16) {
- /* f2i_i2f16 */
- unreachable("i16 not yet implemented");
- } else if (from_size == 32 && to_size == 32) {
- unsigned op = 0;
+ /* f32 to f16 is special */
+ if (from_size == 32 && to_size == 16 && from_base == nir_type_float && to_base == from_base) {
+ /* TODO: second vectorized source? */
+ struct bifrost_fma_2src pack = {
+ .src0 = bi_get_src(ins, regs, 0, true),
+ .src1 = BIFROST_SRC_STAGE, /* 0 */
+ .op = BIFROST_FMA_FLOAT32_TO_16
+ };
- if (from_base == nir_type_float) {
- op = BIFROST_FMA_FLOAT32_TO_INT(to_unsigned);
- } else {
- op = BIFROST_FMA_INT_TO_FLOAT32(from_unsigned);
- }
+ RETURN_PACKED(pack);
+ }
- return bi_pack_fma_1src(ins, regs, op);
- } else if (from_size == 16 && to_size == 32) {
- bool from_y = ins->swizzle[0][0];
+ /* Otherwise, figure out the mode */
+ unsigned op = 0;
+
+ if (from_size == 16 && to_size == 32) {
+ unsigned component = ins->swizzle[0][0];
+ assert(component <= 1);
+
+ if (from_base == nir_type_float)
+ op = BIFROST_CONVERT_5(component);
+ else
+ op = BIFROST_CONVERT_4(from_unsigned, component, to_float);
+ } else {
+ unsigned mode = 0;
+ unsigned swizzle = (from_size == 16) ? bi_swiz16(ins, 0) : 0;
+ bool is_unsigned = from_unsigned;
if (from_base == nir_type_float) {
- return bi_pack_fma_1src(ins, regs,
- BIFROST_FMA_FLOAT16_TO_32(from_y));
- } else {
- unreachable("i16 not yet implemented");
- }
- } else if (from_size == 32 && to_size == 16) {
- if (from_base == nir_type_float) {
- /* TODO: second vectorized source? */
- struct bifrost_fma_2src pack = {
- .src0 = bi_get_src(ins, regs, 0, true),
- .src1 = BIFROST_SRC_STAGE, /* 0 */
- .op = BIFROST_FMA_FLOAT32_TO_16
- };
-
- RETURN_PACKED(pack);
+ assert(to_base != nir_type_float);
+ is_unsigned = to_unsigned;
+
+ if (from_size == 32 && to_size == 32)
+ mode = BIFROST_CONV_F32_TO_I32;
+ else if (from_size == 16 && to_size == 16)
+ mode = BIFROST_CONV_F16_TO_I16;
+ else
+ unreachable("Invalid float conversion");
} else {
- unreachable("i16 not yet implemented");
+ assert(to_base == nir_type_float);
+ assert(from_size == to_size);
+
+ if (to_size == 32)
+ mode = BIFROST_CONV_I32_TO_F32;
+ else if (to_size == 16)
+ mode = BIFROST_CONV_I16_TO_F16;
+ else
+ unreachable("Invalid int conversion");
}
+
+ /* Fixup swizzle for 32-bit only modes */
+
+ if (mode == BIFROST_CONV_I32_TO_F32)
+ swizzle = 0b11;
+ else if (mode == BIFROST_CONV_F32_TO_I32)
+ swizzle = 0b10;
+
+ op = BIFROST_CONVERT(is_unsigned, ins->roundmode, swizzle, mode);
+
+ /* Unclear what the top bit is for... maybe 16-bit related */
+ bool mode2 = mode == BIFROST_CONV_F16_TO_I16;
+ bool mode6 = mode == BIFROST_CONV_I16_TO_F16;
+
+ if (!(mode2 || mode6))
+ op |= 0x100;
}
- unreachable("Unknown convert");
+ return bi_pack_fma_1src(ins, regs, BIFROST_FMA_CONVERT | op);
}
static unsigned
unsigned op : 7;
} __attribute__((packed));
-#define BIFROST_FMA_INT16_TO_32 (0xe0198 >> 3)
-
-struct bifrost_fma_int16_to_32 {
- unsigned src0 : 3;
- unsigned is_unsigned : 1;
- unsigned swizzle : 1;
- unsigned to_float : 1;
- unsigned op : 17;
-} __attribute__((packed));
-
-/* We could combine but it's easier to just use FMA_ONE_SRC */
-#define BIFROST_FMA_FLOAT16_TO_32(y) (0xe01a2 | ((y) ? 1 : 0))
-
/* Two sources for vectorization */
#define BIFROST_FMA_FLOAT32_TO_16 (0xdd000 >> 3)
-/* Again we could combine but easier to just ONE_SRC with an
- * argumnt for unsignedness */
-#define BIFROST_FMA_FLOAT32_TO_INT(u) (0xe0136 | ((u) ? 1 : 0))
-#define BIFROST_FMA_INT_TO_FLOAT32(u) (0xe0178 | ((u) ? 1 : 0))
+enum bifrost_convert_mode {
+ BIFROST_CONV_UNK0 = 0,
+ BIFROST_CONV_F32_TO_I32 = 1,
+ BIFROST_CONV_F16_TO_I16 = 2,
+ BIFROST_CONV_I32_TO_F32 = 3,
+ BIFROST_CONV_I16_TO_X32 = 4,
+ BIFROST_CONV_F16_TO_F32 = 5,
+ BIFROST_CONV_I16_TO_F16 = 6,
+ BIFROST_CONV_UNK7 = 7
+};
-/* Used for f2i16 and i2f16 */
-#define BIFROST_FMA_F2I16 (0xe00)
+/* i16 to x32 */
+#define BIFROST_CONVERT_4(is_unsigned, component, to_float) \
+ ((is_unsigned & 1) | ((component & 1) << 1) | ((to_float & 1) << 2) | \
+ ((0x3) << 3) | ((4) << 5) | 0x100)
-struct bifrost_fma_f2i_i2f16 {
- unsigned src0 : 3;
- unsigned is_unsigned : 1;
- unsigned direction : 2; /* 00 for i2f, 11 for f2i */
- unsigned swizzle : 2;
- unsigned unk : 2; /* always 10 */
- unsigned direction_2 : 1; /* 0 for f2i, 1 for i2f */
- unsigned op : 12;
-} __attribute__((packed));
+/* f16 to f32 */
+#define BIFROST_CONVERT_5(component) \
+ ((component & 1) | ((1) << 1) | ((5) << 5) | 0x100)
+
+/* Other conversions */
+#define BIFROST_CONVERT(is_unsigned, roundmode, swizzle, mode) \
+ ((is_unsigned & 1) | ((roundmode & 3) << 1) | ((swizzle & 3) << 3) | ((mode & 7) << 5))
+
+#define BIFROST_FMA_CONVERT (0xe0000)
enum bifrost_ldst_type {
BIFROST_LDST_F16 = 0,