pvr: Support dual-destination ALU instructions
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com> Acked-by: Frank Binns <frank.binns@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20430>
This commit is contained in:
committed by
Marge Bot
parent
6187f1fd8c
commit
e74aaa347b
@@ -37,7 +37,8 @@ static bool can_back_prop(rogue_alu_instr *mov)
|
||||
{
|
||||
/* TODO: Check for src/dst modifiers when support is added for them. */
|
||||
|
||||
if (!rogue_ref_is_reg(&mov->src[0].ref) || !rogue_ref_is_reg(&mov->dst.ref))
|
||||
if (!rogue_ref_is_reg(&mov->src[0].ref) ||
|
||||
!rogue_ref_is_reg(&mov->dst[0].ref))
|
||||
return false;
|
||||
|
||||
if (mov->src[0].ref.reg->regarray)
|
||||
@@ -45,7 +46,7 @@ static bool can_back_prop(rogue_alu_instr *mov)
|
||||
|
||||
/* Vertex outputs require uvsw.write; only back-propagate if the parent
|
||||
* instruction is also a mov. */
|
||||
if (mov->dst.ref.reg->class == ROGUE_REG_CLASS_VTXOUT) {
|
||||
if (mov->dst[0].ref.reg->class == ROGUE_REG_CLASS_VTXOUT) {
|
||||
rogue_reg_write *write =
|
||||
list_first_entry(&mov->src[0].ref.reg->writes, rogue_reg_write, link);
|
||||
|
||||
@@ -62,7 +63,7 @@ static bool can_back_prop(rogue_alu_instr *mov)
|
||||
return false;
|
||||
|
||||
/* Is this the only instruction that writes to this register? */
|
||||
if (!list_is_singular(&mov->dst.ref.reg->writes))
|
||||
if (!list_is_singular(&mov->dst[0].ref.reg->writes))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -72,13 +73,14 @@ static bool can_forward_prop(rogue_alu_instr *mov)
|
||||
{
|
||||
/* TODO: Check for src/dst modifiers when support is added for them. */
|
||||
|
||||
if (!rogue_ref_is_reg(&mov->src[0].ref) || !rogue_ref_is_reg(&mov->dst.ref))
|
||||
if (!rogue_ref_is_reg(&mov->src[0].ref) ||
|
||||
!rogue_ref_is_reg(&mov->dst[0].ref))
|
||||
return false;
|
||||
|
||||
if (mov->dst.ref.reg->regarray)
|
||||
if (mov->dst[0].ref.reg->regarray)
|
||||
return false;
|
||||
|
||||
if (mov->dst.ref.reg->class != ROGUE_REG_CLASS_SSA)
|
||||
if (mov->dst[0].ref.reg->class != ROGUE_REG_CLASS_SSA)
|
||||
return false;
|
||||
|
||||
/* Is the source register written to more than once (driver-supplied regs can
|
||||
@@ -87,7 +89,7 @@ static bool can_forward_prop(rogue_alu_instr *mov)
|
||||
return false;
|
||||
|
||||
/* Is this the only instruction that writes to this register? */
|
||||
if (!list_is_singular(&mov->dst.ref.reg->writes))
|
||||
if (!list_is_singular(&mov->dst[0].ref.reg->writes))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -96,7 +98,7 @@ static bool can_forward_prop(rogue_alu_instr *mov)
|
||||
static bool rogue_back_prop(rogue_alu_instr *mov)
|
||||
{
|
||||
rogue_reg *mov_src = mov->src[0].ref.reg;
|
||||
rogue_reg *mov_dst = mov->dst.ref.reg;
|
||||
rogue_reg *mov_dst = mov->dst[0].ref.reg;
|
||||
|
||||
rogue_reg_write *write =
|
||||
list_first_entry(&mov_src->writes, rogue_reg_write, link);
|
||||
@@ -114,7 +116,7 @@ static bool rogue_forward_prop(rogue_alu_instr *mov)
|
||||
bool success = true;
|
||||
|
||||
rogue_reg *mov_src = mov->src[0].ref.reg;
|
||||
rogue_reg *mov_dst = mov->dst.ref.reg;
|
||||
rogue_reg *mov_dst = mov->dst[0].ref.reg;
|
||||
|
||||
rogue_foreach_reg_use_safe (use, mov_dst)
|
||||
if (rogue_can_replace_reg_use(use, mov_src))
|
||||
|
||||
@@ -47,7 +47,7 @@ static bool rogue_dce_alu_instr(rogue_alu_instr *alu)
|
||||
switch (alu->op) {
|
||||
case ROGUE_ALU_OP_MOV:
|
||||
case ROGUE_ALU_OP_MBYP:
|
||||
if (!alu->mod && rogue_alu_dst_src_equal(&alu->dst, &alu->src[0])) {
|
||||
if (!alu->mod && rogue_alu_dst_src_equal(&alu->dst[0], &alu->src[0])) {
|
||||
rogue_instr_delete(&alu->instr);
|
||||
progress = true;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
static inline bool rogue_lower_FABS(rogue_builder *b, rogue_alu_instr *fabs)
|
||||
{
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fabs->dst.ref, fabs->src[0].ref);
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fabs->dst[0].ref, fabs->src[0].ref);
|
||||
rogue_merge_instr_comment(&mbyp->instr, &fabs->instr, "fabs");
|
||||
rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_ABS);
|
||||
rogue_instr_delete(&fabs->instr);
|
||||
@@ -45,7 +45,7 @@ static inline bool rogue_lower_FABS(rogue_builder *b, rogue_alu_instr *fabs)
|
||||
|
||||
static inline bool rogue_lower_FNEG(rogue_builder *b, rogue_alu_instr *fneg)
|
||||
{
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fneg->dst.ref, fneg->src[0].ref);
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fneg->dst[0].ref, fneg->src[0].ref);
|
||||
rogue_merge_instr_comment(&mbyp->instr, &fneg->instr, "fneg");
|
||||
rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_NEG);
|
||||
rogue_instr_delete(&fneg->instr);
|
||||
@@ -55,7 +55,7 @@ static inline bool rogue_lower_FNEG(rogue_builder *b, rogue_alu_instr *fneg)
|
||||
|
||||
static inline bool rogue_lower_FNABS(rogue_builder *b, rogue_alu_instr *fnabs)
|
||||
{
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fnabs->dst.ref, fnabs->src[0].ref);
|
||||
rogue_alu_instr *mbyp = rogue_MBYP(b, fnabs->dst[0].ref, fnabs->src[0].ref);
|
||||
rogue_merge_instr_comment(&mbyp->instr, &fnabs->instr, "fnabs");
|
||||
rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_ABS);
|
||||
rogue_set_alu_src_mod(mbyp, 0, ROGUE_ALU_SRC_MOD_NEG);
|
||||
@@ -70,11 +70,11 @@ static inline bool rogue_lower_MOV(rogue_builder *b, rogue_alu_instr *mov)
|
||||
|
||||
/* If we're writing to a vertex output register, we need to use uvsw.write.
|
||||
*/
|
||||
if (rogue_ref_is_reg(&mov->dst.ref) &&
|
||||
mov->dst.ref.reg->class == ROGUE_REG_CLASS_VTXOUT) {
|
||||
instr = &rogue_UVSW_WRITE(b, mov->dst.ref, mov->src[0].ref)->instr;
|
||||
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 {
|
||||
instr = &rogue_MBYP(b, mov->dst.ref, mov->src[0].ref)->instr;
|
||||
instr = &rogue_MBYP(b, mov->dst[0].ref, mov->src[0].ref)->instr;
|
||||
}
|
||||
|
||||
rogue_merge_instr_comment(instr, &mov->instr, "mov");
|
||||
|
||||
@@ -72,11 +72,16 @@ static void rogue_lower_alu_io(rogue_alu_instr *alu, rogue_instr_group *group)
|
||||
const rogue_alu_op_info *info = &rogue_alu_op_infos[alu->op];
|
||||
enum rogue_instr_phase phase = alu->instr.index;
|
||||
|
||||
rogue_set_io_sel(&group->io_sel,
|
||||
info->phase_io[phase].dst,
|
||||
&alu->dst.ref,
|
||||
true);
|
||||
alu->dst.ref = rogue_ref_io(info->phase_io[phase].dst);
|
||||
for (unsigned u = 0; u < info->num_dsts; ++u) {
|
||||
if (info->phase_io[phase].dst[u] == ROGUE_IO_INVALID)
|
||||
continue;
|
||||
|
||||
rogue_set_io_sel(&group->io_sel,
|
||||
info->phase_io[phase].dst[u],
|
||||
&alu->dst[u].ref,
|
||||
true);
|
||||
alu->dst[u].ref = rogue_ref_io(info->phase_io[phase].dst[u]);
|
||||
}
|
||||
|
||||
for (unsigned u = 0; u < info->num_srcs; ++u) {
|
||||
if (info->phase_io[phase].src[u] == ROGUE_IO_INVALID)
|
||||
|
||||
@@ -646,17 +646,20 @@ void rogue_link_instr_write(rogue_instr *instr)
|
||||
switch (instr->type) {
|
||||
case ROGUE_INSTR_TYPE_ALU: {
|
||||
rogue_alu_instr *alu = rogue_instr_as_alu(instr);
|
||||
const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts;
|
||||
|
||||
if (rogue_ref_is_reg(&alu->dst.ref)) {
|
||||
rogue_reg_write *write = &alu->dst_write.reg;
|
||||
rogue_reg *reg = alu->dst.ref.reg;
|
||||
rogue_link_instr_write_reg(instr, write, reg, 0);
|
||||
} else if (rogue_ref_is_regarray(&alu->dst.ref)) {
|
||||
struct util_dynarray **writearray = &alu->dst_write.regarray;
|
||||
rogue_regarray *regarray = alu->dst.ref.regarray;
|
||||
rogue_link_instr_write_regarray(instr, writearray, regarray, 0);
|
||||
} else {
|
||||
unreachable("Invalid destination reference type.");
|
||||
for (unsigned i = 0; i < num_dsts; ++i) {
|
||||
if (rogue_ref_is_reg(&alu->dst[i].ref)) {
|
||||
rogue_reg_write *write = &alu->dst_write[i].reg;
|
||||
rogue_reg *reg = alu->dst[i].ref.reg;
|
||||
rogue_link_instr_write_reg(instr, write, reg, 0);
|
||||
} else if (rogue_ref_is_regarray(&alu->dst[i].ref)) {
|
||||
struct util_dynarray **writearray = &alu->dst_write[i].regarray;
|
||||
rogue_regarray *regarray = alu->dst[i].ref.regarray;
|
||||
rogue_link_instr_write_regarray(instr, writearray, regarray, 0);
|
||||
} else {
|
||||
unreachable("Invalid destination reference type.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -815,15 +818,18 @@ void rogue_unlink_instr_write(rogue_instr *instr)
|
||||
switch (instr->type) {
|
||||
case ROGUE_INSTR_TYPE_ALU: {
|
||||
rogue_alu_instr *alu = rogue_instr_as_alu(instr);
|
||||
const unsigned num_dsts = rogue_alu_op_infos[alu->op].num_dsts;
|
||||
|
||||
if (rogue_ref_is_reg(&alu->dst.ref)) {
|
||||
rogue_reg_write *write = &alu->dst_write.reg;
|
||||
rogue_unlink_instr_write_reg(instr, write);
|
||||
} else if (rogue_ref_is_regarray(&alu->dst.ref)) {
|
||||
struct util_dynarray **writearray = &alu->dst_write.regarray;
|
||||
rogue_unlink_instr_write_regarray(instr, writearray);
|
||||
} else {
|
||||
unreachable("Invalid destination reference type.");
|
||||
for (unsigned i = 0; i < num_dsts; ++i) {
|
||||
if (rogue_ref_is_reg(&alu->dst[i].ref)) {
|
||||
rogue_reg_write *write = &alu->dst_write[i].reg;
|
||||
rogue_unlink_instr_write_reg(instr, write);
|
||||
} else if (rogue_ref_is_regarray(&alu->dst[i].ref)) {
|
||||
struct util_dynarray **writearray = &alu->dst_write[i].regarray;
|
||||
rogue_unlink_instr_write_regarray(instr, writearray);
|
||||
} else {
|
||||
unreachable("Invalid destination reference type.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -864,6 +864,7 @@ static inline bool rogue_refs_equal(rogue_ref *a, rogue_ref *b)
|
||||
typedef struct rogue_alu_dst {
|
||||
rogue_ref ref;
|
||||
uint64_t mod;
|
||||
unsigned index;
|
||||
} rogue_alu_dst;
|
||||
|
||||
typedef struct rogue_alu_src {
|
||||
@@ -1066,9 +1067,10 @@ static inline bool rogue_ctrl_op_has_dsts(enum rogue_ctrl_op op)
|
||||
|
||||
/* ALU instructions have at most 3 sources. */
|
||||
#define ROGUE_ALU_OP_MAX_SRCS 3
|
||||
#define ROGUE_ALU_OP_MAX_DSTS 2
|
||||
|
||||
typedef struct rogue_alu_io_info {
|
||||
enum rogue_io dst;
|
||||
enum rogue_io dst[ROGUE_ALU_OP_MAX_DSTS];
|
||||
enum rogue_io src[ROGUE_ALU_OP_MAX_SRCS];
|
||||
} rogue_alu_io_info;
|
||||
|
||||
@@ -1076,17 +1078,18 @@ typedef struct rogue_alu_io_info {
|
||||
typedef struct rogue_alu_op_info {
|
||||
const char *str;
|
||||
|
||||
unsigned num_dsts;
|
||||
unsigned num_srcs;
|
||||
|
||||
uint64_t supported_phases;
|
||||
rogue_alu_io_info phase_io[ROGUE_INSTR_PHASE_COUNT];
|
||||
|
||||
uint64_t supported_op_mods;
|
||||
uint64_t supported_dst_mods;
|
||||
uint64_t supported_dst_mods[ROGUE_ALU_OP_MAX_DSTS];
|
||||
uint64_t supported_src_mods[ROGUE_ALU_OP_MAX_SRCS];
|
||||
|
||||
/* TODO NEXT: Do the same for other instruction types. */
|
||||
uint64_t supported_dst_types;
|
||||
uint64_t supported_dst_types[ROGUE_ALU_OP_MAX_DSTS];
|
||||
uint64_t supported_src_types[ROGUE_ALU_OP_MAX_SRCS];
|
||||
} rogue_alu_op_info;
|
||||
|
||||
@@ -1143,12 +1146,12 @@ typedef struct rogue_alu_instr {
|
||||
|
||||
uint64_t mod;
|
||||
|
||||
rogue_alu_dst dst;
|
||||
rogue_alu_dst dst[ROGUE_ALU_OP_MAX_DSTS];
|
||||
|
||||
union {
|
||||
rogue_reg_write reg;
|
||||
struct util_dynarray *regarray;
|
||||
} dst_write;
|
||||
} dst_write[ROGUE_ALU_OP_MAX_DSTS];
|
||||
|
||||
rogue_alu_src src[ROGUE_ALU_OP_MAX_SRCS];
|
||||
|
||||
@@ -1171,9 +1174,17 @@ static inline bool rogue_alu_op_mod_is_set(const rogue_alu_instr *alu,
|
||||
}
|
||||
|
||||
static inline void rogue_set_alu_dst_mod(rogue_alu_instr *alu,
|
||||
unsigned dst_index,
|
||||
enum rogue_alu_dst_mod mod)
|
||||
{
|
||||
alu->dst.mod |= BITFIELD64_BIT(mod);
|
||||
alu->dst[dst_index].mod |= BITFIELD64_BIT(mod);
|
||||
}
|
||||
|
||||
static inline bool rogue_alu_dst_mod_is_set(const rogue_alu_instr *alu,
|
||||
unsigned dst_index,
|
||||
enum rogue_alu_dst_mod mod)
|
||||
{
|
||||
return !!(alu->dst[dst_index].mod & BITFIELD64_BIT(mod));
|
||||
}
|
||||
|
||||
static inline void rogue_set_alu_src_mod(rogue_alu_instr *alu,
|
||||
@@ -2082,7 +2093,7 @@ static inline bool rogue_dst_reg_replace(rogue_reg_write *write,
|
||||
|
||||
switch (instr->type) {
|
||||
case ROGUE_INSTR_TYPE_ALU:
|
||||
ref = &rogue_instr_as_alu(instr)->dst.ref;
|
||||
ref = &rogue_instr_as_alu(instr)->dst[dst_index].ref;
|
||||
break;
|
||||
|
||||
case ROGUE_INSTR_TYPE_BACKEND:
|
||||
|
||||
@@ -28,40 +28,48 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* ROGUE_BUILDER_DEFINE_ALUs
|
||||
* ROGUE_BUILDER_DEFINE_ALUds
|
||||
* d: Number of destinations.
|
||||
* s: Number of sources.
|
||||
*/
|
||||
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU1
|
||||
#define ROGUE_BUILDER_DEFINE_ALU1(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU1 */
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU11
|
||||
#define ROGUE_BUILDER_DEFINE_ALU11(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU11 */
|
||||
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU2
|
||||
#define ROGUE_BUILDER_DEFINE_ALU2(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU2 */
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU12
|
||||
#define ROGUE_BUILDER_DEFINE_ALU12(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU12 */
|
||||
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU3
|
||||
#define ROGUE_BUILDER_DEFINE_ALU3(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU3 */
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU13
|
||||
#define ROGUE_BUILDER_DEFINE_ALU13(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU13 */
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU1(MOV)
|
||||
ROGUE_BUILDER_DEFINE_ALU1(MBYP)
|
||||
#ifndef ROGUE_BUILDER_DEFINE_ALU22
|
||||
#define ROGUE_BUILDER_DEFINE_ALU22(...)
|
||||
#endif /* ROGUE_BUILDER_DEFINE_ALU22 */
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU1(FABS)
|
||||
ROGUE_BUILDER_DEFINE_ALU1(FNEG)
|
||||
ROGUE_BUILDER_DEFINE_ALU1(FNABS)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(MOV)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(MBYP)
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU1(PCK_U8888)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(FABS)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(FNEG)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(FNABS)
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU2(FADD)
|
||||
ROGUE_BUILDER_DEFINE_ALU2(FMUL)
|
||||
ROGUE_BUILDER_DEFINE_ALU11(PCK_U8888)
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU2(FMAX)
|
||||
ROGUE_BUILDER_DEFINE_ALU2(FMIN)
|
||||
ROGUE_BUILDER_DEFINE_ALU12(FADD)
|
||||
ROGUE_BUILDER_DEFINE_ALU12(FMUL)
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU3(SEL)
|
||||
ROGUE_BUILDER_DEFINE_ALU3(FMAD)
|
||||
ROGUE_BUILDER_DEFINE_ALU12(FMAX)
|
||||
ROGUE_BUILDER_DEFINE_ALU12(FMIN)
|
||||
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU3
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU2
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU1
|
||||
ROGUE_BUILDER_DEFINE_ALU13(FMAD)
|
||||
ROGUE_BUILDER_DEFINE_ALU13(SEL)
|
||||
|
||||
ROGUE_BUILDER_DEFINE_ALU22(TST)
|
||||
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU22
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU13
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU12
|
||||
#undef ROGUE_BUILDER_DEFINE_ALU11
|
||||
|
||||
@@ -48,14 +48,19 @@ static inline void rogue_builder_insert_instr(rogue_builder *b,
|
||||
|
||||
static inline rogue_alu_instr *rogue_build_alu(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst,
|
||||
unsigned num_dsts,
|
||||
rogue_ref dsts[num_dsts],
|
||||
unsigned num_srcs,
|
||||
rogue_ref srcs[num_srcs])
|
||||
{
|
||||
rogue_alu_instr *alu =
|
||||
rogue_alu_instr_create(rogue_cursor_block(b->cursor), op);
|
||||
|
||||
alu->dst.ref = dst;
|
||||
for (unsigned i = 0; i < num_dsts; ++i) {
|
||||
alu->dst[i].ref = dsts[i];
|
||||
alu->dst[i].index = i;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < num_srcs; ++i) {
|
||||
alu->src[i].ref = srcs[i];
|
||||
alu->src[i].index = i;
|
||||
@@ -65,68 +70,99 @@ static inline rogue_alu_instr *rogue_build_alu(rogue_builder *b,
|
||||
return alu;
|
||||
}
|
||||
|
||||
static inline rogue_alu_instr *rogue_build_alu1(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst,
|
||||
rogue_ref src0)
|
||||
static inline rogue_alu_instr *rogue_build_alu11(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst0,
|
||||
rogue_ref src0)
|
||||
{
|
||||
rogue_ref dsts[] = { dst0 };
|
||||
rogue_ref srcs[] = { src0 };
|
||||
return rogue_build_alu(b, op, dst, 1, srcs);
|
||||
return rogue_build_alu(b, op, 1, dsts, 1, srcs);
|
||||
}
|
||||
|
||||
static inline rogue_alu_instr *rogue_build_alu2(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst,
|
||||
rogue_ref src0,
|
||||
rogue_ref src1)
|
||||
static inline rogue_alu_instr *rogue_build_alu12(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst0,
|
||||
rogue_ref src0,
|
||||
rogue_ref src1)
|
||||
{
|
||||
rogue_ref dsts[] = { dst0 };
|
||||
rogue_ref srcs[] = { src0, src1 };
|
||||
return rogue_build_alu(b, op, dst, 2, srcs);
|
||||
return rogue_build_alu(b, op, 1, dsts, 2, srcs);
|
||||
}
|
||||
|
||||
static inline rogue_alu_instr *rogue_build_alu3(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst,
|
||||
rogue_ref src0,
|
||||
rogue_ref src1,
|
||||
rogue_ref src2)
|
||||
static inline rogue_alu_instr *rogue_build_alu13(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst0,
|
||||
rogue_ref src0,
|
||||
rogue_ref src1,
|
||||
rogue_ref src2)
|
||||
{
|
||||
rogue_ref dsts[] = { dst0 };
|
||||
rogue_ref srcs[] = { src0, src1, src2 };
|
||||
return rogue_build_alu(b, op, dst, 3, srcs);
|
||||
return rogue_build_alu(b, op, 1, dsts, 3, srcs);
|
||||
}
|
||||
|
||||
static inline rogue_alu_instr *rogue_build_alu22(rogue_builder *b,
|
||||
enum rogue_alu_op op,
|
||||
rogue_ref dst0,
|
||||
rogue_ref dst1,
|
||||
rogue_ref src0,
|
||||
rogue_ref src1)
|
||||
{
|
||||
rogue_ref dsts[] = { dst0, dst1 };
|
||||
rogue_ref srcs[] = { src0, src1 };
|
||||
return rogue_build_alu(b, op, 2, dsts, 2, srcs);
|
||||
}
|
||||
|
||||
/* TODO: Static inline in rogue.h? */
|
||||
#define ROGUE_BUILDER_DEFINE_ALU1(op) \
|
||||
#define ROGUE_BUILDER_DEFINE_ALU11(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 1); \
|
||||
return rogue_build_alu1(b, ROGUE_ALU_OP_##op, dst, src0); \
|
||||
return rogue_build_alu11(b, ROGUE_ALU_OP_##op, dst0, src0); \
|
||||
}
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU2(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \
|
||||
return rogue_build_alu2(b, ROGUE_ALU_OP_##op, dst, src0, src1); \
|
||||
#define ROGUE_BUILDER_DEFINE_ALU12(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \
|
||||
return rogue_build_alu12(b, ROGUE_ALU_OP_##op, dst0, src0, src1); \
|
||||
}
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU3(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1, \
|
||||
rogue_ref src2) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \
|
||||
return rogue_build_alu3(b, ROGUE_ALU_OP_##op, dst, src0, src1, src2); \
|
||||
#define ROGUE_BUILDER_DEFINE_ALU13(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1, \
|
||||
rogue_ref src2) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 1); \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 3); \
|
||||
return rogue_build_alu13(b, ROGUE_ALU_OP_##op, dst0, src0, src1, src2); \
|
||||
}
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU22(op) \
|
||||
PUBLIC \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref dst1, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1) \
|
||||
{ \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_dsts == 2); \
|
||||
assert(rogue_alu_op_infos[ROGUE_ALU_OP_##op].num_srcs == 2); \
|
||||
return rogue_build_alu22(b, ROGUE_ALU_OP_##op, dst0, dst1, src0, src1); \
|
||||
}
|
||||
|
||||
#include "rogue_alu_instrs.def"
|
||||
|
||||
@@ -91,22 +91,31 @@ static inline rogue_block *rogue_push_block(rogue_builder *b)
|
||||
}
|
||||
|
||||
/* ALU instructions. */
|
||||
#define ROGUE_BUILDER_DEFINE_ALU1(op) \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, rogue_ref dst, rogue_ref src0);
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU2(op) \
|
||||
#define ROGUE_BUILDER_DEFINE_ALU11(op) \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0);
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU12(op) \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1);
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU3(op) \
|
||||
#define ROGUE_BUILDER_DEFINE_ALU13(op) \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1, \
|
||||
rogue_ref src2);
|
||||
|
||||
#define ROGUE_BUILDER_DEFINE_ALU22(op) \
|
||||
rogue_alu_instr *rogue_##op(rogue_builder *b, \
|
||||
rogue_ref dst0, \
|
||||
rogue_ref dst1, \
|
||||
rogue_ref src0, \
|
||||
rogue_ref src1);
|
||||
|
||||
#include "rogue_alu_instrs.def"
|
||||
|
||||
/* Backend instructions. */
|
||||
|
||||
@@ -300,50 +300,50 @@ const rogue_io_info rogue_io_infos[ROGUE_IO_COUNT] = {
|
||||
#define T(type) BITFIELD64_BIT(ROGUE_REF_TYPE_##type - 1)
|
||||
const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
|
||||
[ROGUE_ALU_OP_INVALID] = { .str = "!INVALID!", },
|
||||
[ROGUE_ALU_OP_MBYP] = { .str = "mbyp", .num_srcs = 1,
|
||||
[ROGUE_ALU_OP_MBYP] = { .str = "mbyp", .num_dsts = 1, .num_srcs = 1,
|
||||
.supported_phases = P(0),
|
||||
.phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), },
|
||||
.phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), },
|
||||
.supported_src_mods = {
|
||||
[0] = SM(ABS) | SM(NEG),
|
||||
},
|
||||
.supported_dst_types = T(REG),
|
||||
.supported_dst_types = { [0] = T(REG), },
|
||||
.supported_src_types = {
|
||||
[0] = T(REG),
|
||||
},
|
||||
},
|
||||
[ROGUE_ALU_OP_FADD] = { .str = "fadd", .num_srcs = 2,
|
||||
[ROGUE_ALU_OP_FADD] = { .str = "fadd", .num_dsts = 1, .num_srcs = 2,
|
||||
.supported_phases = P(0),
|
||||
.phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), },
|
||||
.phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), },
|
||||
.supported_op_mods = OM(LP) | OM(SAT),
|
||||
.supported_src_mods = {
|
||||
[0] = SM(FLR) | SM(ABS) | SM(NEG),
|
||||
[1] = SM(ABS),
|
||||
},
|
||||
},
|
||||
[ROGUE_ALU_OP_FMUL] = { .str = "fmul", .num_srcs = 2,
|
||||
[ROGUE_ALU_OP_FMUL] = { .str = "fmul", .num_dsts = 1, .num_srcs = 2,
|
||||
.supported_phases = P(0),
|
||||
.phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), },
|
||||
.phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), },
|
||||
.supported_op_mods = OM(LP) | OM(SAT),
|
||||
.supported_src_mods = {
|
||||
[0] = SM(FLR) | SM(ABS) | SM(NEG),
|
||||
[1] = SM(ABS),
|
||||
},
|
||||
.supported_dst_types = T(REG),
|
||||
.supported_dst_types = { [0] = T(REG), },
|
||||
.supported_src_types = {
|
||||
[0] = T(REG),
|
||||
[1] = T(REG),
|
||||
},
|
||||
},
|
||||
[ROGUE_ALU_OP_FMAD] = { .str = "fmad", .num_srcs = 3,
|
||||
[ROGUE_ALU_OP_FMAD] = { .str = "fmad", .num_dsts = 1, .num_srcs = 3,
|
||||
.supported_phases = P(0),
|
||||
.phase_io[PH(0)] = { .dst = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), .src[2] = IO(S2), },
|
||||
.phase_io[PH(0)] = { .dst[0] = IO(FT0), .src[0] = IO(S0), .src[1] = IO(S1), .src[2] = IO(S2), },
|
||||
.supported_op_mods = OM(LP) | OM(SAT),
|
||||
.supported_src_mods = {
|
||||
[0] = SM(ABS) | SM(NEG),
|
||||
[1] = SM(ABS) | SM(NEG),
|
||||
[2] = SM(FLR) | SM(ABS) | SM(NEG),
|
||||
},
|
||||
.supported_dst_types = T(REG),
|
||||
.supported_dst_types = { [0] = T(REG), },
|
||||
.supported_src_types = {
|
||||
[0] = T(REG),
|
||||
[1] = T(REG),
|
||||
@@ -351,30 +351,30 @@ const rogue_alu_op_info rogue_alu_op_infos[ROGUE_ALU_OP_COUNT] = {
|
||||
},
|
||||
},
|
||||
/* TODO: Implement */
|
||||
[ROGUE_ALU_OP_TST] = { .str = "tst", .num_srcs = 2, },
|
||||
[ROGUE_ALU_OP_PCK_U8888] = { .str = "pck.u8888", .num_srcs = 1,
|
||||
[ROGUE_ALU_OP_TST] = { .str = "tst", .num_dsts = 2, .num_srcs = 2, },
|
||||
[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 = IO(FT2), .src[0] = IO(IS3), },
|
||||
.phase_io[PH(2_PCK)] = { .dst[0] = IO(FT2), .src[0] = IO(IS3), },
|
||||
.supported_op_mods = OM(SCALE) | OM(ROUNDZERO),
|
||||
.supported_dst_types = T(REG),
|
||||
.supported_dst_types = { [0] = T(REG), },
|
||||
.supported_src_types = {
|
||||
[0] = T(REGARRAY),
|
||||
},
|
||||
},
|
||||
/* 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_srcs = 1,
|
||||
.supported_dst_types = T(REG),
|
||||
[ROGUE_ALU_OP_MOV] = { .str = "mov", .num_dsts = 1, .num_srcs = 1,
|
||||
.supported_dst_types = { [0] = T(REG), },
|
||||
.supported_src_types = {
|
||||
[0] = T(REG) | T(IMM),
|
||||
},
|
||||
},
|
||||
[ROGUE_ALU_OP_FABS] = { .str = "fabs", .num_srcs = 1, },
|
||||
[ROGUE_ALU_OP_FNEG] = { .str = "fneg", .num_srcs = 1, },
|
||||
[ROGUE_ALU_OP_FNABS] = { .str = "fnabs", .num_srcs = 1, },
|
||||
[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, },
|
||||
|
||||
[ROGUE_ALU_OP_FMAX] = { .str = "fmax", .num_srcs = 2, }, /* TODO */
|
||||
[ROGUE_ALU_OP_FMIN] = { .str = "fmin", .num_srcs = 2, }, /* TODO */
|
||||
[ROGUE_ALU_OP_SEL] = { .str = "sel", .num_srcs = 3, }, /* TODO */
|
||||
[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 T
|
||||
#undef IO
|
||||
|
||||
@@ -256,12 +256,21 @@ static inline void rogue_print_alu_instr(FILE *fp, const rogue_alu_instr *alu)
|
||||
|
||||
rogue_print_alu_mods(fp, alu);
|
||||
|
||||
fputs(" ", fp);
|
||||
for (unsigned i = 0; i < info->num_dsts; ++i) {
|
||||
if (i > 0)
|
||||
fputs(",", fp);
|
||||
|
||||
rogue_print_alu_dst(fp, &alu->dst);
|
||||
fputs(" ", fp);
|
||||
|
||||
rogue_print_alu_dst(fp, &alu->dst[i]);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < info->num_srcs; ++i) {
|
||||
fputs(", ", fp);
|
||||
if (i == 0 && !info->num_dsts)
|
||||
fputs(" ", fp);
|
||||
else
|
||||
fputs(", ", fp);
|
||||
|
||||
rogue_print_alu_src(fp, &alu->src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +194,9 @@ static void validate_alu_instr(rogue_validation_state *state,
|
||||
if (!rogue_mods_supported(alu->mod, info->supported_op_mods))
|
||||
validate_log(state, "Unsupported ALU op modifiers.");
|
||||
|
||||
/* Validate destination and sources. */
|
||||
validate_alu_dst(state, &alu->dst, info->supported_dst_types);
|
||||
/* Validate destinations and sources. */
|
||||
for (unsigned i = 0; i < info->num_dsts; ++i)
|
||||
validate_alu_dst(state, &alu->dst[i], info->supported_dst_types[i]);
|
||||
|
||||
for (unsigned i = 0; i < info->num_srcs; ++i)
|
||||
validate_alu_src(state, &alu->src[i], info->supported_src_types[i]);
|
||||
|
||||
Reference in New Issue
Block a user