From 81f86a559c87f2da414a9adc4b1055deef863e9b Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Tue, 7 Feb 2023 10:53:13 +0000 Subject: [PATCH] pvr: Add ADD64 support Signed-off-by: Simon Perretta Acked-by Frank Binns Part-of: --- .../rogue/passes/rogue_schedule_instr_groups.c | 121 +++++++++++++++++---- src/imagination/rogue/rogue.h | 24 +++- src/imagination/rogue/rogue_alu_instrs.def | 8 +- src/imagination/rogue/rogue_builder.c | 42 +++++++ src/imagination/rogue/rogue_builder.h | 11 ++ src/imagination/rogue/rogue_encode.c | 25 +++++ src/imagination/rogue/rogue_info.c | 19 +++- src/imagination/rogue/rogue_isa.h | 33 ++++++ 8 files changed, 256 insertions(+), 27 deletions(-) diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index fe06b5b..8e18835 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -34,34 +34,99 @@ */ 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."); } diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index 5ca2042..dd95bf5 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -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]; diff --git a/src/imagination/rogue/rogue_alu_instrs.def b/src/imagination/rogue/rogue_alu_instrs.def index 6f90386..bebbfc9 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_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 diff --git a/src/imagination/rogue/rogue_builder.c b/src/imagination/rogue/rogue_builder.c index 8454c78..e9b2658 100644 --- a/src/imagination/rogue/rogue_builder.c +++ b/src/imagination/rogue/rogue_builder.c @@ -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, diff --git a/src/imagination/rogue/rogue_builder.h b/src/imagination/rogue/rogue_builder.h index 02540be..6a2ae33 100644 --- a/src/imagination/rogue/rogue_builder.h +++ b/src/imagination/rogue/rogue_builder.h @@ -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. */ diff --git a/src/imagination/rogue/rogue_encode.c b/src/imagination/rogue/rogue_encode.c index 383d091..6778a3d 100644 --- a/src/imagination/rogue/rogue_encode.c +++ b/src/imagination/rogue/rogue_encode.c @@ -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."); } diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index 2b7ee1e..c2a2358 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -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 diff --git a/src/imagination/rogue/rogue_isa.h b/src/imagination/rogue/rogue_isa.h index c32bc16..c57de60 100644 --- a/src/imagination/rogue/rogue_isa.h +++ b/src/imagination/rogue/rogue_isa.h @@ -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, -- 2.7.4