pvr: Add ADD64 support
authorSimon Perretta <simon.perretta@imgtec.com>
Tue, 7 Feb 2023 10:53:13 +0000 (10:53 +0000)
committerMarge Bot <emma+marge@anholt.net>
Mon, 20 Feb 2023 13:34:02 +0000 (13:34 +0000)
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by Frank Binns <frank.binns@imgtec.comr>

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21331>

src/imagination/rogue/passes/rogue_schedule_instr_groups.c
src/imagination/rogue/rogue.h
src/imagination/rogue/rogue_alu_instrs.def
src/imagination/rogue/rogue_builder.c
src/imagination/rogue/rogue_builder.h
src/imagination/rogue/rogue_encode.c
src/imagination/rogue/rogue_info.c
src/imagination/rogue/rogue_isa.h

index fe06b5b..8e18835 100644 (file)
  */
 
 static inline void rogue_set_io_sel(rogue_instr_group_io_sel *map,
+                                    enum rogue_alu alu,
                                     enum rogue_io io,
                                     rogue_ref *ref,
                                     bool is_dst)
 {
-   /* Hookup feedthrough outputs to W0 using IS4. */
-   if (is_dst && rogue_io_is_ft(io)) {
-      *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS4)) = rogue_ref_io(io);
-      io = ROGUE_IO_W0;
-   }
+   /* Skip unassigned I/Os. */
+   if (rogue_ref_is_io_none(ref))
+      return;
 
-   /* Pack source */
-   if (!is_dst && io == ROGUE_IO_IS3) {
-      enum rogue_io src = ROGUE_IO_S0;
-      *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) = rogue_ref_io(src);
-      *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS3)) =
-         rogue_ref_io(ROGUE_IO_FTE);
-      io = src;
-   }
+   /* Early skip I/Os that have already been assigned (e.g. for grouping). */
+   if (rogue_ref_is_io(ref) && rogue_ref_get_io(ref) == io)
+      return;
+
+   /* Leave source feedthroughs in place. */
+   if (!is_dst && rogue_io_is_ft(io))
+      return;
+
+   if (alu == ROGUE_ALU_MAIN) {
+      /* Hookup feedthrough outputs to W0 using IS4. */
+      if (is_dst && rogue_io_is_ft(io)) {
+         if (io == ROGUE_IO_FTE) {
+            *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS5)) =
+               rogue_ref_io(io);
+            io = ROGUE_IO_W1;
+         } else {
+            *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS4)) =
+               rogue_ref_io(io);
+            io = ROGUE_IO_W0;
+         }
+      }
+
+      /* Pack source */
+      if (!is_dst && io == ROGUE_IO_IS3) {
+         enum rogue_io src = ROGUE_IO_S0;
+         *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) = rogue_ref_io(src);
+         *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS3)) =
+            rogue_ref_io(ROGUE_IO_FTE);
+         io = src;
+      }
+
+      /* Movc sources. */
+      if (!is_dst && rogue_io_is_dst(io)) {
+         enum rogue_io dst_ft =
+            (io == ROGUE_IO_W0 ? ROGUE_IO_IS4 : ROGUE_IO_IS5);
+         enum rogue_io src = ROGUE_IO_S0;
+         *(rogue_instr_group_io_sel_ref(map, dst_ft)) =
+            rogue_ref_io(ROGUE_IO_FTE);
+         *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) = rogue_ref_io(src);
+         io = src;
+      }
+
+      /* ADD64 fourth source */
+      if (!is_dst && io == ROGUE_IO_IS0) {
+         enum rogue_io src = ROGUE_IO_S3;
+         *(rogue_instr_group_io_sel_ref(map, io)) = rogue_ref_io(src);
+         io = src;
+      }
 
-   if (!is_dst && rogue_io_is_dst(io)) {
-      enum rogue_io dst_ft = (io == ROGUE_IO_W0 ? ROGUE_IO_IS4 : ROGUE_IO_IS5);
-      enum rogue_io src = ROGUE_IO_S0;
-      *(rogue_instr_group_io_sel_ref(map, dst_ft)) = rogue_ref_io(ROGUE_IO_FTE);
-      *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) = rogue_ref_io(src);
-      io = src;
+      /* Test source(s). */
+      /* TODO: tidy up. */
+      if (!is_dst && io == ROGUE_IO_IS1) {
+         enum rogue_io src = ROGUE_IO_S0;
+         enum rogue_io ft = ROGUE_IO_FT0;
+
+         /* Already set up. */
+         if (io != ft)
+            *(rogue_instr_group_io_sel_ref(map, io)) = rogue_ref_io(ft);
+
+         io = src;
+      }
+
+      if (!is_dst && io == ROGUE_IO_IS2) {
+         enum rogue_io src = ROGUE_IO_S3;
+         enum rogue_io ft = ROGUE_IO_FTE;
+
+         *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) =
+            rogue_ref_io(ROGUE_IO_S3);
+
+         /* Already set up. */
+         if (io != ft)
+            *(rogue_instr_group_io_sel_ref(map, io)) = rogue_ref_io(ft);
+
+         io = src;
+      }
+   } else if (alu == ROGUE_ALU_BITWISE) {
+      /* TODO: This is temporary because we just have BYP0, do it properly. */
+      if (is_dst)
+         io = ROGUE_IO_W0;
    }
 
-   *(rogue_instr_group_io_sel_ref(map, io)) = *ref;
+   /* Set if not already set. */
+   if (rogue_ref_is_null(rogue_instr_group_io_sel_ref(map, io)))
+      *(rogue_instr_group_io_sel_ref(map, io)) = *ref;
 }
 
 /* TODO NEXT: Abort if anything in sel map is already set. */
@@ -77,6 +142,7 @@ static void rogue_lower_alu_io(rogue_alu_instr *alu, rogue_instr_group *group)
          continue;
 
       rogue_set_io_sel(&group->io_sel,
+                       group->header.alu,
                        info->phase_io[phase].dst[u],
                        &alu->dst[u].ref,
                        true);
@@ -88,6 +154,7 @@ static void rogue_lower_alu_io(rogue_alu_instr *alu, rogue_instr_group *group)
          continue;
 
       rogue_set_io_sel(&group->io_sel,
+                       group->header.alu,
                        info->phase_io[phase].src[u],
                        &alu->src[u].ref,
                        false);
@@ -105,6 +172,7 @@ static void rogue_lower_backend_io(rogue_backend_instr *backend,
          continue;
 
       rogue_set_io_sel(&group->io_sel,
+                       group->header.alu,
                        info->phase_io.dst[u],
                        &backend->dst[u].ref,
                        true);
@@ -116,6 +184,7 @@ static void rogue_lower_backend_io(rogue_backend_instr *backend,
          continue;
 
       rogue_set_io_sel(&group->io_sel,
+                       group->header.alu,
                        info->phase_io.src[u],
                        &backend->src[u].ref,
                        false);
@@ -437,6 +506,18 @@ static void rogue_calc_alu_instrs_size(rogue_instr_group *group,
       group->size.instrs[phase] = 2;
       break;
 
+   case ROGUE_ALU_OP_ADD64:
+      group->size.instrs[phase] = 1;
+
+      if (rogue_ref_is_io_p0(&alu->src[4].ref) ||
+          rogue_alu_src_mod_is_set(alu, 0, SM(ABS)) ||
+          rogue_alu_src_mod_is_set(alu, 0, SM(NEG)) ||
+          rogue_alu_src_mod_is_set(alu, 1, SM(ABS)) ||
+          rogue_alu_src_mod_is_set(alu, 1, SM(NEG)) ||
+          rogue_alu_src_mod_is_set(alu, 2, SM(ABS)))
+         group->size.instrs[phase] = 2;
+      break;
+
    default:
       unreachable("Unsupported alu op.");
    }
index 5ca2042..dd95bf5 100644 (file)
@@ -793,6 +793,20 @@ static inline enum rogue_io rogue_ref_get_io(const rogue_ref *ref)
    return ref->io;
 }
 
+static inline bool rogue_ref_is_io_p0(const rogue_ref *ref)
+{
+   return rogue_ref_get_io(ref) == ROGUE_IO_P0;
+}
+
+static inline bool rogue_ref_is_io_none(const rogue_ref *ref)
+{
+   /* Special case - never assert. */
+   if (!rogue_ref_is_io(ref))
+      return false;
+
+   return rogue_ref_get_io(ref) == ROGUE_IO_NONE;
+}
+
 static inline unsigned rogue_ref_get_drc_index(const rogue_ref *ref)
 {
    assert(rogue_ref_is_drc(ref));
@@ -927,6 +941,8 @@ enum rogue_alu_op {
    ROGUE_ALU_OP_FMUL,
    ROGUE_ALU_OP_FMAD,
 
+   ROGUE_ALU_OP_ADD64,
+
    ROGUE_ALU_OP_TST,
 
    ROGUE_ALU_OP_PCK_U8888,
@@ -942,8 +958,6 @@ enum rogue_alu_op {
    ROGUE_ALU_OP_FMAX,
    ROGUE_ALU_OP_FMIN,
 
-   ROGUE_ALU_OP_SEL,
-
    ROGUE_ALU_OP_COUNT,
 };
 
@@ -1075,9 +1089,9 @@ static inline bool rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)
    return info->has_dsts;
 }
 
-/* ALU instructions have at most 3 sources. */
-#define ROGUE_ALU_OP_MAX_SRCS 3
-#define ROGUE_ALU_OP_MAX_DSTS 2
+/* ALU instructions have at most 5 sources. */
+#define ROGUE_ALU_OP_MAX_SRCS 5
+#define ROGUE_ALU_OP_MAX_DSTS 3
 
 typedef struct rogue_alu_io_info {
    enum rogue_io dst[ROGUE_ALU_OP_MAX_DSTS];
index 6f90386..bebbfc9 100644 (file)
 #define ROGUE_BUILDER_DEFINE_ALU22(...)
 #endif /* ROGUE_BUILDER_DEFINE_ALU22 */
 
+#ifndef ROGUE_BUILDER_DEFINE_ALU35
+#define ROGUE_BUILDER_DEFINE_ALU35(...)
+#endif /* ROGUE_BUILDER_DEFINE_ALU35 */
+
 ROGUE_BUILDER_DEFINE_ALU11(MOV)
 ROGUE_BUILDER_DEFINE_ALU11(MBYP)
 
@@ -65,10 +69,12 @@ ROGUE_BUILDER_DEFINE_ALU12(FMAX)
 ROGUE_BUILDER_DEFINE_ALU12(FMIN)
 
 ROGUE_BUILDER_DEFINE_ALU13(FMAD)
-ROGUE_BUILDER_DEFINE_ALU13(SEL)
 
 ROGUE_BUILDER_DEFINE_ALU22(TST)
 
+ROGUE_BUILDER_DEFINE_ALU35(ADD64)
+
+#undef ROGUE_BUILDER_DEFINE_ALU35
 #undef ROGUE_BUILDER_DEFINE_ALU22
 #undef ROGUE_BUILDER_DEFINE_ALU13
 #undef ROGUE_BUILDER_DEFINE_ALU12
index 8454c78..e9b2658 100644 (file)
@@ -115,6 +115,22 @@ static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b,
    return rogue_build_alu(b, op, 2, dsts, 2, srcs);
 }
 
+static inline rogue_alu_instr *rogue_build_alu35(rogue_builder *b,
+                                                 enum rogue_alu_op op,
+                                                 rogue_ref dst0,
+                                                 rogue_ref dst1,
+                                                 rogue_ref dst2,
+                                                 rogue_ref src0,
+                                                 rogue_ref src1,
+                                                 rogue_ref src2,
+                                                 rogue_ref src3,
+                                                 rogue_ref src4)
+{
+   rogue_ref dsts[] = { dst0, dst1, dst2 };
+   rogue_ref srcs[] = { src0, src1, src2, src3, src4 };
+   return rogue_build_alu(b, op, 3, dsts, 5, srcs);
+}
+
 /* TODO: Static inline in rogue.h? */
 #define ROGUE_BUILDER_DEFINE_ALU11(op)                             \
    PUBLIC                                                          \
@@ -165,6 +181,32 @@ static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b,
       return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \
    }
 
+#define ROGUE_BUILDER_DEFINE_ALU35(op)                             \
+   PUBLIC                                                          \
+   rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
+                               rogue_ref dst0,                     \
+                               rogue_ref dst1,                     \
+                               rogue_ref dst2,                     \
+                               rogue_ref src0,                     \
+                               rogue_ref src1,                     \
+                               rogue_ref src2,                     \
+                               rogue_ref src3,                     \
+                               rogue_ref src4)                     \
+   {                                                               \
+      assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 3); \
+      assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 5); \
+      return rogue_build_alu35(b,                                  \
+                               ROGUE_ALU_OP_##op,                  \
+                               dst0,                               \
+                               dst1,                               \
+                               dst2,                               \
+                               src0,                               \
+                               src1,                               \
+                               src2,                               \
+                               src3,                               \
+                               src4);                              \
+   }
+
 #include "rogue_alu_instrs.def"
 
 static inline rogue_backend_instr *rogue_build_backend(rogue_builder *b,
index 02540be..6a2ae33 100644 (file)
@@ -116,6 +116,17 @@ static inline rogue_block *rogue_push_block(rogue_builder *b)
                                rogue_ref src0,   \
                                rogue_ref src1);
 
+#define ROGUE_BUILDER_DEFINE_ALU35(op)           \
+   rogue_alu_instr *rogue_##op(rogue_builder *b, \
+                               rogue_ref dst0,   \
+                               rogue_ref dst1,   \
+                               rogue_ref dst2,   \
+                               rogue_ref src0,   \
+                               rogue_ref src1,   \
+                               rogue_ref src2,   \
+                               rogue_ref src3,   \
+                               rogue_ref src4);
+
 #include "rogue_alu_instrs.def"
 
 /* Backend instructions. */
index 383d091..6778a3d 100644 (file)
@@ -255,6 +255,31 @@ static void rogue_encode_alu_instr(const rogue_alu_instr *alu,
       instr_encoding->alu.sngl.pck.pck.format = PCK_FMT_U8888;
       break;
 
+   case ROGUE_ALU_OP_ADD64:
+      instr_encoding->alu.op = ALUOP_INT32_64;
+
+      instr_encoding->alu.int32_64.int32_64_op = INT32_64_OP_ADD64_NMX;
+      instr_encoding->alu.int32_64.s2neg =
+         rogue_alu_src_mod_is_set(alu, 2, SM(NEG));
+      instr_encoding->alu.int32_64.s = 0;
+
+      if (instr_size == 2) {
+         instr_encoding->alu.int32_64.ext = 1;
+         instr_encoding->alu.int32_64.s2abs =
+            rogue_alu_src_mod_is_set(alu, 2, SM(ABS));
+         instr_encoding->alu.int32_64.s1abs =
+            rogue_alu_src_mod_is_set(alu, 1, SM(ABS));
+         instr_encoding->alu.int32_64.s0abs =
+            rogue_alu_src_mod_is_set(alu, 0, SM(ABS));
+         instr_encoding->alu.int32_64.s0neg =
+            rogue_alu_src_mod_is_set(alu, 0, SM(NEG));
+         instr_encoding->alu.int32_64.s1neg =
+            rogue_alu_src_mod_is_set(alu, 1, SM(NEG));
+         instr_encoding->alu.int32_64.cin =
+            rogue_ref_is_io_p0(&alu->src[4].ref);
+      }
+      break;
+
    default:
       unreachable("Unsupported alu op.");
    }
index 2b7ee1e..c2a2358 100644 (file)
@@ -376,6 +376,24 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
    },
    /* TODO: Implement */
    [ROGUE_ALU_OP_TST] = { .str = "tst", .num_dsts = 2, .num_srcs = 2, },
+   [ROGUE_ALU_OP_ADD64] = { .str = "add64", .num_dsts = 3, .num_srcs = 5,
+      .supported_phases = P(0),
+      .phase_io[PH(0)] = { .dst[0] = IO(FT0), .dst[1] = IO(FTE), .src[0] = IO(S0), .src[1] = IO(S1), .src[2] = IO(S2), .src[3] = IO(IS0), },
+      .supported_src_mods = {
+         [0] = SM(ABS) | SM(NEG),
+         [1] = SM(ABS) | SM(NEG),
+         [2] = SM(ABS) | SM(NEG),
+         [3] = SM(ABS) | SM(NEG),
+      },
+      .supported_dst_types = { [0] = T(REG) | T(REGARRAY), [1] = T(REG) | T(REGARRAY) | T(IO), [2] = T(IO) },
+      .supported_src_types = {
+         [0] = T(REG) | T(REGARRAY),
+         [1] = T(REG) | T(REGARRAY),
+         [2] = T(REG) | T(REGARRAY),
+         [3] = T(REG) | T(REGARRAY)| T(IO),
+         [4] = T(IO),
+      },
+   },
    [ROGUE_ALU_OP_PCK_U8888] = { .str = "pck.u8888", .num_dsts = 1, .num_srcs = 1,
       .supported_phases = P(2_PCK),
       .phase_io[PH(2_PCK)] = { .dst[0] = IO(FT2), .src[0] = IO(IS3), },
@@ -399,7 +417,6 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
 
    [ROGUE_ALU_OP_FMAX] = { .str = "fmax", .num_dsts = 1, .num_srcs = 2, }, /* TODO */
    [ROGUE_ALU_OP_FMIN] = { .str = "fmin", .num_dsts = 1, .num_srcs = 2, }, /* TODO */
-   [ROGUE_ALU_OP_SEL] = { .str = "sel", .num_dsts = 1, .num_srcs = 3, }, /* TODO */
 };
 #undef B
 #undef T
index c32bc16..c57de60 100644 (file)
@@ -636,6 +636,38 @@ typedef struct rogue_alu_mov_encoding {
 static_assert(sizeof(rogue_alu_mov_encoding) == 2,
               "sizeof(rogue_alu_mov_encoding) != 2");
 
+typedef struct rogue_alu_int32_64_encoding {
+   /* Byte 0 */
+   struct {
+      unsigned int32_64_op : 2;
+      unsigned s2neg : 1;
+      unsigned s : 1;
+      unsigned ext : 1;
+      unsigned : 3;
+   } PACKED;
+
+   /* Byte 1 */
+   struct {
+      unsigned s2abs : 1;
+      unsigned s1abs : 1;
+      unsigned s0abs : 1;
+      unsigned : 1;
+      unsigned s0neg : 1;
+      unsigned s1neg : 1;
+      unsigned cin : 1;
+      unsigned : 1;
+   } PACKED;
+} PACKED rogue_alu_int32_64_encoding;
+static_assert(sizeof(rogue_alu_int32_64_encoding) == 2,
+              "sizeof(rogue_alu_int32_64_encoding) != 2");
+
+enum int32_64_op {
+   INT32_64_OP_ADD6432 = 0b00,
+   /* No multiply or extension, only valid when s=0. */
+   INT32_64_OP_ADD64_NMX = 0b01,
+   INT32_64_OP_MADD32 = 0b10,
+   INT32_64_OP_MADD64 = 0b11,
+};
 typedef struct rogue_alu_instr_encoding {
    union {
       /* Byte 0 */
@@ -651,6 +683,7 @@ typedef struct rogue_alu_instr_encoding {
       rogue_alu_fmad_encoding fmad;
       rogue_alu_tst_encoding tst;
       rogue_alu_mov_encoding mov;
+      rogue_alu_int32_64_encoding int32_64;
    } PACKED;
 } PACKED rogue_alu_instr_encoding;
 static_assert(sizeof(rogue_alu_instr_encoding) == 2,