pvr: Add ADD64 support

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>
This commit is contained in:
Simon Perretta
2023-02-07 10:53:13 +00:00
committed by Marge Bot
parent 7386342a19
commit 81f86a559c
8 changed files with 258 additions and 29 deletions

View File

@@ -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;
/* 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;
}
/* 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;
}
/* 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;
}
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;
}
*(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.");
}

View 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];

View File

@@ -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

View 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,

View 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. */

View 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.");
}

View 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

View 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,