Module: Mesa
Branch: main
Commit: 8719f7cb8d4b6bfb9c55985840520c219aa68d76
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=8719f7cb8d4b6bfb9c55985840520c219aa68d76

Author: Simon Perretta <[email protected]>
Date:   Fri Feb 17 16:29:22 2023 +0000

pvr: Add support for MOVC

Signed-off-by: Simon Perretta <[email protected]>
Acked-by: Frank Binns <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21474>

---

 .../rogue/passes/rogue_schedule_instr_groups.c     | 19 ++++++
 src/imagination/rogue/rogue.h                      |  7 +++
 src/imagination/rogue/rogue_alu_instrs.def         |  8 +++
 src/imagination/rogue/rogue_builder.c              | 33 +++++++++++
 src/imagination/rogue/rogue_builder.h              |  8 +++
 src/imagination/rogue/rogue_encode.c               | 68 ++++++++++++++++++++++
 src/imagination/rogue/rogue_info.c                 | 22 ++++++-
 src/imagination/rogue/rogue_isa.h                  | 27 +++++++--
 8 files changed, 185 insertions(+), 7 deletions(-)

diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c 
b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
index 1587ec777f7..77719c77f52 100644
--- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
+++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c
@@ -552,6 +552,25 @@ static void rogue_calc_alu_instrs_size(rogue_instr_group 
*group,
       }
       break;
 
+   case ROGUE_ALU_OP_MOVC: {
+      group->size.instrs[phase] = 1;
+
+      bool e0 = rogue_alu_dst_mod_is_set(alu, 0, DM(E0));
+      bool e1 = rogue_alu_dst_mod_is_set(alu, 0, DM(E1));
+      bool e2 = rogue_alu_dst_mod_is_set(alu, 0, DM(E2));
+      bool e3 = rogue_alu_dst_mod_is_set(alu, 0, DM(E3));
+      bool eq = (e0 == e1) && (e0 == e2) && (e0 == e3);
+
+      if ((!rogue_phase_occupied(ROGUE_INSTR_PHASE_2_TST,
+                                 group->header.phases) &&
+           !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_PCK,
+                                 group->header.phases)) ||
+          !rogue_ref_is_io_ftt(&alu->src[0].ref) || !eq) {
+         group->size.instrs[phase] = 2;
+      }
+      break;
+   }
+
    case ROGUE_ALU_OP_PCK_U8888:
       group->size.instrs[phase] = 2;
       break;
diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h
index b4b611c2243..d66be6cee0b 100644
--- a/src/imagination/rogue/rogue.h
+++ b/src/imagination/rogue/rogue.h
@@ -887,6 +887,11 @@ 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_ftt(const rogue_ref *ref)
+{
+   return rogue_ref_get_io(ref) == ROGUE_IO_FTT;
+}
+
 static inline bool rogue_ref_is_io_none(const rogue_ref *ref)
 {
    /* Special case - never assert. */
@@ -1038,12 +1043,14 @@ enum rogue_alu_op {
    ROGUE_ALU_OP_ADD64,
 
    ROGUE_ALU_OP_TST,
+   ROGUE_ALU_OP_MOVC,
 
    ROGUE_ALU_OP_PCK_U8888,
 
    /* Pseudo-instructions. */
    ROGUE_ALU_OP_PSEUDO,
    ROGUE_ALU_OP_MOV = ROGUE_ALU_OP_PSEUDO,
+   ROGUE_ALU_OP_CMOV, /** Conditional move. */
 
    ROGUE_ALU_OP_FABS,
    ROGUE_ALU_OP_FNEG,
diff --git a/src/imagination/rogue/rogue_alu_instrs.def 
b/src/imagination/rogue/rogue_alu_instrs.def
index bebbfc98963..9895d567794 100644
--- a/src/imagination/rogue/rogue_alu_instrs.def
+++ b/src/imagination/rogue/rogue_alu_instrs.def
@@ -49,6 +49,10 @@
 #define ROGUE_BUILDER_DEFINE_ALU22(...)
 #endif /* ROGUE_BUILDER_DEFINE_ALU22 */
 
+#ifndef ROGUE_BUILDER_DEFINE_ALU23
+#define ROGUE_BUILDER_DEFINE_ALU23(...)
+#endif /* ROGUE_BUILDER_DEFINE_ALU23 */
+
 #ifndef ROGUE_BUILDER_DEFINE_ALU35
 #define ROGUE_BUILDER_DEFINE_ALU35(...)
 #endif /* ROGUE_BUILDER_DEFINE_ALU35 */
@@ -69,12 +73,16 @@ ROGUE_BUILDER_DEFINE_ALU12(FMAX)
 ROGUE_BUILDER_DEFINE_ALU12(FMIN)
 
 ROGUE_BUILDER_DEFINE_ALU13(FMAD)
+ROGUE_BUILDER_DEFINE_ALU13(CMOV)
 
 ROGUE_BUILDER_DEFINE_ALU22(TST)
 
+ROGUE_BUILDER_DEFINE_ALU23(MOVC)
+
 ROGUE_BUILDER_DEFINE_ALU35(ADD64)
 
 #undef ROGUE_BUILDER_DEFINE_ALU35
+#undef ROGUE_BUILDER_DEFINE_ALU23
 #undef ROGUE_BUILDER_DEFINE_ALU22
 #undef ROGUE_BUILDER_DEFINE_ALU13
 #undef ROGUE_BUILDER_DEFINE_ALU12
diff --git a/src/imagination/rogue/rogue_builder.c 
b/src/imagination/rogue/rogue_builder.c
index 8947b6b4f42..63f1ba1a4d5 100644
--- a/src/imagination/rogue/rogue_builder.c
+++ b/src/imagination/rogue/rogue_builder.c
@@ -115,6 +115,19 @@ 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_alu23(rogue_builder *b,
+                                                 enum rogue_alu_op op,
+                                                 rogue_ref dst0,
+                                                 rogue_ref dst1,
+                                                 rogue_ref src0,
+                                                 rogue_ref src1,
+                                                 rogue_ref src2)
+{
+   rogue_ref dsts[] = { dst0, dst1 };
+   rogue_ref srcs[] = { src0, src1, src2 };
+   return rogue_build_alu(b, op, 2, dsts, 3, srcs);
+}
+
 static inline rogue_alu_instr *rogue_build_alu35(rogue_builder *b,
                                                  enum rogue_alu_op op,
                                                  rogue_ref dst0,
@@ -181,6 +194,26 @@ static inline rogue_alu_instr 
*rogue_build_alu35(rogue_builder *b,
       return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \
    }
 
+#define ROGUE_BUILDER_DEFINE_ALU23(op)                             \
+   PUBLIC                                                          \
+   rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
+                               rogue_ref dst0,                     \
+                               rogue_ref dst1,                     \
+                               rogue_ref src0,                     \
+                               rogue_ref src1,                     \
+                               rogue_ref src2)                     \
+   {                                                               \
+      assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \
+      assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \
+      return rogue_build_alu23(b,                                  \
+                               ROGUE_ALU_OP_##op,                  \
+                               dst0,                               \
+                               dst1,                               \
+                               src0,                               \
+                               src1,                               \
+                               src2);                              \
+   }
+
 #define ROGUE_BUILDER_DEFINE_ALU35(op)                             \
    PUBLIC                                                          \
    rogue_alu_instr *rogue_##op(rogue_builder *b,                   \
diff --git a/src/imagination/rogue/rogue_builder.h 
b/src/imagination/rogue/rogue_builder.h
index 5161df86601..eb8b0425a77 100644
--- a/src/imagination/rogue/rogue_builder.h
+++ b/src/imagination/rogue/rogue_builder.h
@@ -116,6 +116,14 @@ static inline rogue_block *rogue_push_block(rogue_builder 
*b)
                                rogue_ref src0,   \
                                rogue_ref src1);
 
+#define ROGUE_BUILDER_DEFINE_ALU23(op)           \
+   rogue_alu_instr *rogue_##op(rogue_builder *b, \
+                               rogue_ref dst0,   \
+                               rogue_ref dst1,   \
+                               rogue_ref src0,   \
+                               rogue_ref src1,   \
+                               rogue_ref src2);
+
 #define ROGUE_BUILDER_DEFINE_ALU35(op)           \
    rogue_alu_instr *rogue_##op(rogue_builder *b, \
                                rogue_ref dst0,   \
diff --git a/src/imagination/rogue/rogue_encode.c 
b/src/imagination/rogue/rogue_encode.c
index cd8100d6e7b..d610e0fefb9 100644
--- a/src/imagination/rogue/rogue_encode.c
+++ b/src/imagination/rogue/rogue_encode.c
@@ -348,6 +348,74 @@ static void rogue_encode_alu_instr(const rogue_alu_instr 
*alu,
       break;
    }
 
+   case ROGUE_ALU_OP_MOVC: {
+      instr_encoding->alu.op = ALUOP_MOVC;
+
+      bool e0 = rogue_alu_dst_mod_is_set(alu, 0, DM(E0));
+      bool e1 = rogue_alu_dst_mod_is_set(alu, 0, DM(E1));
+      bool e2 = rogue_alu_dst_mod_is_set(alu, 0, DM(E2));
+      bool e3 = rogue_alu_dst_mod_is_set(alu, 0, DM(E3));
+      bool e_none = !e0 && !e1 && !e2 && !e3;
+
+      switch (rogue_ref_get_io(&alu->src[1].ref)) {
+      case ROGUE_IO_FT0:
+         instr_encoding->alu.movc.movw0 = MOVW_FT0;
+         break;
+      case ROGUE_IO_FT1:
+         instr_encoding->alu.movc.movw0 = MOVW_FT1;
+         break;
+      case ROGUE_IO_FT2:
+         instr_encoding->alu.movc.movw0 = MOVW_FT2;
+         break;
+      case ROGUE_IO_FTE:
+         instr_encoding->alu.movc.movw0 = MOVW_FTE;
+         break;
+      default:
+         unreachable("Invalid source.");
+      }
+
+      switch (rogue_ref_get_io(&alu->src[2].ref)) {
+      case ROGUE_IO_FT0:
+         instr_encoding->alu.movc.movw1 = MOVW_FT0;
+         break;
+      case ROGUE_IO_FT1:
+         instr_encoding->alu.movc.movw1 = MOVW_FT1;
+         break;
+      case ROGUE_IO_FT2:
+         instr_encoding->alu.movc.movw1 = MOVW_FT2;
+         break;
+      case ROGUE_IO_FTE:
+         instr_encoding->alu.movc.movw1 = MOVW_FTE;
+         break;
+      default:
+         unreachable("Invalid source.");
+      }
+
+      if (instr_size == 2) {
+         instr_encoding->alu.movc.ext = 1;
+         instr_encoding->alu.movc.p2end =
+            !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_TST,
+                                  alu->instr.group->header.phases) &&
+            !rogue_phase_occupied(ROGUE_INSTR_PHASE_2_PCK,
+                                  alu->instr.group->header.phases);
+         instr_encoding->alu.movc.aw = !rogue_ref_is_io_ftt(&alu->src[0].ref);
+
+         if (e_none) {
+            instr_encoding->alu.movc.maskw0 = MASKW0_EALL;
+         } else {
+            if (e0)
+               instr_encoding->alu.movc.maskw0 |= MASKW0_E0;
+            if (e1)
+               instr_encoding->alu.movc.maskw0 |= MASKW0_E1;
+            if (e2)
+               instr_encoding->alu.movc.maskw0 |= MASKW0_E2;
+            if (e3)
+               instr_encoding->alu.movc.maskw0 |= MASKW0_E3;
+         }
+      }
+      break;
+   }
+
    case ROGUE_ALU_OP_PCK_U8888:
       instr_encoding->alu.op = ALUOP_SNGL;
       instr_encoding->alu.sngl.snglop = SNGLOP_PCK;
diff --git a/src/imagination/rogue/rogue_info.c 
b/src/imagination/rogue/rogue_info.c
index 0e1eb5b1a7c..23853fa59df 100644
--- a/src/imagination/rogue/rogue_info.c
+++ b/src/imagination/rogue/rogue_info.c
@@ -635,6 +635,19 @@ const rogue_alu_op_info 
rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
          [1] = T(REG) | T(IO),
       },
    },
+   [ROGUE_ALU_OP_MOVC] = { .str = "movc", .num_dsts = 2, .num_srcs = 3,
+      .supported_phases = P(2_MOV),
+      .phase_io[PH(2_MOV)] = { .dst[0] = IO(W0), .dst[1] = IO(W1), .src[1] = 
IO(FT0), .src[2] = IO(FTE), }, /* TODO: SRC ONES ARE TEMPORARY, SHOULD BE MADE 
TO MATCH THE TST ONES INSTEAD? */
+      .supported_dst_mods = {
+         [0] = DM(E0) | DM(E1) | DM(E2) | DM(E3),
+      },
+      .supported_dst_types = { [0] = T(REG), [1] = T(REG) | T(IO), },
+      .supported_src_types = {
+         [0] = T(IO),
+         [1] = T(REG) | T(IO),
+         [2] = T(REG) | T(IO),
+      },
+   },
    [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), },
@@ -663,13 +676,20 @@ const rogue_alu_op_info 
rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
       },
       .src_repeat_mask = B(0),
    },
-   /* This mov is "fake" since it can be lowered to a MBYP, make a new 
instruction for real mov (call it MOVD?). */
    [ROGUE_ALU_OP_MOV] = { .str = "mov", .num_dsts = 1, .num_srcs = 1,
       .supported_dst_types = { [0] = T(REG) | T(REGARRAY), },
       .supported_src_types = {
          [0] = T(REG) | T(IMM),
       },
    },
+   [ROGUE_ALU_OP_CMOV] = { .str = "cmov", .num_dsts = 1, .num_srcs = 3,
+      .supported_dst_types = { [0] = T(REG), },
+      .supported_src_types = {
+         [0] = T(IO),
+         [1] = T(REG),
+         [2] = T(REG),
+      },
+   },
    [ROGUE_ALU_OP_FABS] = { .str = "fabs", .num_dsts = 1, .num_srcs = 1, },
    [ROGUE_ALU_OP_FNEG] = { .str = "fneg", .num_dsts = 1, .num_srcs = 1, },
    [ROGUE_ALU_OP_FNABS] = { .str = "fnabs", .num_dsts = 1, .num_srcs = 1, },
diff --git a/src/imagination/rogue/rogue_isa.h 
b/src/imagination/rogue/rogue_isa.h
index 32c25e64289..3315fbfba4f 100644
--- a/src/imagination/rogue/rogue_isa.h
+++ b/src/imagination/rogue/rogue_isa.h
@@ -633,7 +633,7 @@ enum tstelem {
    TST_E3 = 0b11,
 };
 
-typedef struct rogue_alu_mov_encoding {
+typedef struct rogue_alu_movc_encoding {
    /* Byte 0 */
    struct {
       unsigned movw0 : 2;
@@ -649,9 +649,24 @@ typedef struct rogue_alu_mov_encoding {
       unsigned maskw0 : 4;
       unsigned : 2;
    } PACKED;
-} PACKED rogue_alu_mov_encoding;
-static_assert(sizeof(rogue_alu_mov_encoding) == 2,
-              "sizeof(rogue_alu_mov_encoding) != 2");
+} PACKED rogue_alu_movc_encoding;
+static_assert(sizeof(rogue_alu_movc_encoding) == 2,
+              "sizeof(rogue_alu_movc_encoding) != 2");
+
+enum movw {
+   MOVW_FT0 = 0b00,
+   MOVW_FT1 = 0b01,
+   MOVW_FT2 = 0b10,
+   MOVW_FTE = 0b11,
+};
+
+enum maskw0 {
+   MASKW0_E0 = 0b0001,
+   MASKW0_E1 = 0b0010,
+   MASKW0_E2 = 0b0100,
+   MASKW0_E3 = 0b1000,
+   MASKW0_EALL = 0b1111,
+};
 
 typedef struct rogue_alu_int32_64_encoding {
    /* Byte 0 */
@@ -699,7 +714,7 @@ typedef struct rogue_alu_instr_encoding {
       rogue_alu_fdual_encoding fmul;
       rogue_alu_fmad_encoding fmad;
       rogue_alu_tst_encoding tst;
-      rogue_alu_mov_encoding mov;
+      rogue_alu_movc_encoding movc;
       rogue_alu_int32_64_encoding int32_64;
    } PACKED;
 } PACKED rogue_alu_instr_encoding;
@@ -712,7 +727,7 @@ enum aluop {
    ALUOP_SNGL = 0b100, /** Phase 0, 1, 2. */
    ALUOP_INT8_16 = 0b101, /** Phase 0. */
    ALUOP_FMAD = 0b110, /** Phase 0, 1. */
-   ALUOP_MOV = 0b110, /** Phase 2. */
+   ALUOP_MOVC = 0b110, /** Phase 2. */
    ALUOP_INT32_64 = 0b111, /** Phase 0. */
    ALUOP_TST = 0b111, /** Phase 2. */
 };

Reply via email to