From eeac8336ef7835b16871651ef3a321ea7060102b Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Fri, 24 Feb 2023 17:52:09 +0000 Subject: [PATCH] pvr: Use movc for reading special registers Signed-off-by: Simon Perretta Acked-by: Karmjit Mahil Part-of: --- .../rogue/passes/rogue_lower_pseudo_ops.c | 14 +++++ .../rogue/passes/rogue_schedule_instr_groups.c | 15 +++-- src/imagination/rogue/rogue.c | 1 - src/imagination/rogue/rogue.h | 5 ++ src/imagination/rogue/rogue_encode.c | 70 +++++++++------------- src/imagination/rogue/rogue_info.c | 9 +-- 6 files changed, 63 insertions(+), 51 deletions(-) diff --git a/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c b/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c index 9ddd27d..398b2af 100644 --- a/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c +++ b/src/imagination/rogue/passes/rogue_lower_pseudo_ops.c @@ -73,6 +73,20 @@ static inline bool rogue_lower_MOV(rogue_builder *b, rogue_alu_instr *mov) if (rogue_ref_is_reg(&mov->dst[0].ref) && mov->dst[0].ref.reg->class == ROGUE_REG_CLASS_VTXOUT) { instr = &rogue_UVSW_WRITE(b, mov->dst[0].ref, mov->src[0].ref)->instr; + } else if (rogue_ref_is_special_reg(&mov->src[0].ref)) { + /* If we're loading a special register, use a movc. */ + rogue_alu_instr *alu = rogue_MOVC(b, + mov->dst[0].ref, + rogue_ref_io(ROGUE_IO_NONE), + rogue_ref_io(ROGUE_IO_NONE), + mov->src[0].ref, + rogue_ref_io(ROGUE_IO_NONE)); + rogue_set_alu_dst_mod(alu, 0, ROGUE_ALU_DST_MOD_E0); + rogue_set_alu_dst_mod(alu, 0, ROGUE_ALU_DST_MOD_E1); + rogue_set_alu_dst_mod(alu, 0, ROGUE_ALU_DST_MOD_E2); + rogue_set_alu_dst_mod(alu, 0, ROGUE_ALU_DST_MOD_E3); + + instr = &alu->instr; } else { /* If we're moving an immediate value not in special constants, * we need to do a bitwise bypass. diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index 2d7ead5..ed432ac 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -47,10 +47,6 @@ static inline void rogue_set_io_sel(rogue_instr_group_io_sel *map, 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)) { @@ -65,6 +61,15 @@ static inline void rogue_set_io_sel(rogue_instr_group_io_sel *map, } } + /* Movc source. */ + /* TODO: hardcoded to use fte and s1 for now. */ + if (!is_dst && io == ROGUE_IO_FTE) { + enum rogue_io src = ROGUE_IO_S1; + *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS0)) = rogue_ref_io(src); + *(rogue_instr_group_io_sel_ref(map, ROGUE_IO_IS4)) = rogue_ref_io(io); + io = src; + } + /* Pack source */ if (!is_dst && io == ROGUE_IO_IS3) { enum rogue_io src = ROGUE_IO_S0; @@ -74,7 +79,7 @@ static inline void rogue_set_io_sel(rogue_instr_group_io_sel *map, io = src; } - /* Movc sources. */ + /* w0/w1 used as sources. */ if (!is_dst && rogue_io_is_dst(io)) { enum rogue_io dst_ft = (io == ROGUE_IO_W0 ? ROGUE_IO_IS4 : ROGUE_IO_IS5); diff --git a/src/imagination/rogue/rogue.c b/src/imagination/rogue/rogue.c index 9e5c54d..e4ad5e0 100644 --- a/src/imagination/rogue/rogue.c +++ b/src/imagination/rogue/rogue.c @@ -144,7 +144,6 @@ bool rogue_regarray_set(rogue_shader *shader, *regarray_cached = regarray; regarray->cached = regarray_cached; - assert(updated); return updated; } diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index e9b22c1..e4c02fe 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -796,6 +796,11 @@ static inline bool rogue_ref_is_reg(const rogue_ref *ref) return ref->type == ROGUE_REF_TYPE_REG; } +static inline bool rogue_ref_is_special_reg(const rogue_ref *ref) +{ + return rogue_ref_is_reg(ref) && ref->reg->class == ROGUE_REG_CLASS_SPECIAL; +} + static inline bool rogue_ref_is_regarray(const rogue_ref *ref) { return ref->type == ROGUE_REF_TYPE_REGARRAY; diff --git a/src/imagination/rogue/rogue_encode.c b/src/imagination/rogue/rogue_encode.c index b56f330..0ab4ff5 100644 --- a/src/imagination/rogue/rogue_encode.c +++ b/src/imagination/rogue/rogue_encode.c @@ -222,6 +222,29 @@ typedef union rogue_instr_encoding { rogue_bitwise_instr_encoding bitwise; } PACKED rogue_instr_encoding; +static unsigned rogue_alu_movc_ft(const rogue_ref *ref) +{ + switch (rogue_ref_get_io(ref)) { + case ROGUE_IO_NONE: + case ROGUE_IO_FT0: + return MOVW_FT0; + + case ROGUE_IO_FT1: + return MOVW_FT1; + + case ROGUE_IO_FT2: + return MOVW_FT2; + + case ROGUE_IO_FTE: + return MOVW_FTE; + + default: + break; + } + + unreachable("Invalid source."); +} + #define SM(src_mod) ROGUE_ALU_SRC_MOD_##src_mod #define DM(dst_mod) ROGUE_ALU_DST_MOD_##dst_mod #define OM(op_mod) ROGUE_ALU_OP_MOD_##op_mod @@ -357,39 +380,8 @@ static void rogue_encode_alu_instr(const rogue_alu_instr *alu, 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."); - } + instr_encoding->alu.movc.movw0 = rogue_alu_movc_ft(&alu->src[1].ref); + instr_encoding->alu.movc.movw1 = rogue_alu_movc_ft(&alu->src[2].ref); if (instr_size == 2) { instr_encoding->alu.movc.ext = 1; @@ -403,14 +395,10 @@ static void rogue_encode_alu_instr(const rogue_alu_instr *alu, 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; + instr_encoding->alu.movc.maskw0 |= e0 ? MASKW0_E0 : 0; + instr_encoding->alu.movc.maskw0 |= e1 ? MASKW0_E1 : 0; + instr_encoding->alu.movc.maskw0 |= e2 ? MASKW0_E2 : 0; + instr_encoding->alu.movc.maskw0 |= e3 ? MASKW0_E3 : 0; } } break; diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index ee7fab7..3c0bebd 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -640,17 +640,18 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = { [1] = T(REG) | T(IO), }, }, + /* TODO: Support fully. */ [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? */ + .phase_io[PH(2_MOV)] = { .dst[0] = IO(W0), .src[1] = IO(FTE), }, .supported_dst_mods = { [0] = DM(E0) | DM(E1) | DM(E2) | DM(E3), }, - .supported_dst_types = { [0] = T(REG), [1] = T(REG) | T(IO), }, + .supported_dst_types = { [0] = T(REG) | T(REGARRAY), [1] = T(REG) | T(REGARRAY) | T(IO), }, .supported_src_types = { [0] = T(IO), - [1] = T(REG) | T(IO), - [2] = T(REG) | T(IO), + [1] = T(REG) | T(REGARRAY) | T(IO), + [2] = T(REG) | T(REGARRAY) | T(IO), }, }, [ROGUE_ALU_OP_ADD64] = { .str = "add64", .num_dsts = 3, .num_srcs = 5, -- 2.7.4