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:
Simon Perretta
2023-01-18 15:41:23 +00:00
committed by Marge Bot
parent 6187f1fd8c
commit e74aaa347b
12 changed files with 236 additions and 149 deletions
+11 -9
View File
@@ -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))
+1 -1
View File
@@ -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)
+24 -18
View File
@@ -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;
+18 -7
View File
@@ -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:
+33 -25
View File
@@ -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
+78 -42
View File
@@ -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"
+16 -7
View File
@@ -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. */
+23 -23
View File
@@ -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
+12 -3
View File
@@ -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]);
}
}
+3 -2
View File
@@ -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]);