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. */ };
