diff --git a/src/imagination/rogue/passes/rogue_dce.c b/src/imagination/rogue/passes/rogue_dce.c index ad7fd19ccc3..7f1e3898e3f 100644 --- a/src/imagination/rogue/passes/rogue_dce.c +++ b/src/imagination/rogue/passes/rogue_dce.c @@ -76,6 +76,9 @@ static bool rogue_dce_instrs(rogue_shader *shader) case ROGUE_INSTR_TYPE_CTRL: break; + case ROGUE_INSTR_TYPE_BITWISE: + break; + default: unreachable("Unsupported instruction type."); return false; diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index b8df932cf01..26cccebe892 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -198,6 +198,37 @@ static void rogue_lower_ctrl_io(rogue_ctrl_instr *ctrl, /* TODO: Support control instructions with I/O. */ } +static void rogue_lower_bitwise_io(rogue_bitwise_instr *bitwise, + rogue_instr_group *group) +{ + const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op]; + enum rogue_instr_phase phase = bitwise->instr.index; + + 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, + group->header.alu, + info->phase_io[phase].dst[u], + &bitwise->dst[u].ref, + true); + bitwise->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) + continue; + + rogue_set_io_sel(&group->io_sel, + group->header.alu, + info->phase_io[phase].src[u], + &bitwise->src[u].ref, + false); + bitwise->src[u].ref = rogue_ref_io(info->phase_io[phase].src[u]); + } +} + static void rogue_lower_instr_group_io(rogue_instr *instr, rogue_instr_group *group) { @@ -214,6 +245,10 @@ static void rogue_lower_instr_group_io(rogue_instr *instr, rogue_lower_ctrl_io(rogue_instr_as_ctrl(instr), group); break; + case ROGUE_INSTR_TYPE_BITWISE: + rogue_lower_bitwise_io(rogue_instr_as_bitwise(instr), group); + break; + default: unreachable("Unsupported instruction group type."); } @@ -577,6 +612,28 @@ static void rogue_calc_ctrl_instrs_size(rogue_instr_group *group, } } +static void rogue_calc_bitwise_instrs_size(rogue_instr_group *group, + rogue_bitwise_instr *bitwise, + enum rogue_instr_phase phase) +{ + switch (bitwise->op) { + case ROGUE_BITWISE_OP_BYP0: + group->size.instrs[phase] = 1; + + if (rogue_ref_is_val(&bitwise->src[1].ref)) { + group->size.instrs[phase] = 3; + + /* If upper 16 bits aren't zero. */ + if (rogue_ref_get_val(&bitwise->src[1].ref) & 0xffff0000) + group->size.instrs[phase] = 5; + } + break; + + default: + unreachable("Invalid bitwise op."); + } +} + static void rogue_calc_instrs_size(rogue_instr_group *group) { rogue_foreach_phase_in_set (p, group->header.phases) { @@ -597,6 +654,12 @@ static void rogue_calc_instrs_size(rogue_instr_group *group) rogue_calc_ctrl_instrs_size(group, rogue_instr_as_ctrl(instr), p); break; + case ROGUE_INSTR_TYPE_BITWISE: + rogue_calc_bitwise_instrs_size(group, + rogue_instr_as_bitwise(instr), + p); + break; + default: unreachable("Unsupported instruction type."); } @@ -707,6 +770,10 @@ bool rogue_schedule_instr_groups(rogue_shader *shader, bool multi_instr_groups) group_alu = ROGUE_ALU_CONTROL; break; + case ROGUE_INSTR_TYPE_BITWISE: + group_alu = ROGUE_ALU_BITWISE; + break; + default: unreachable("Unsupported instruction type."); } diff --git a/src/imagination/rogue/rogue.c b/src/imagination/rogue/rogue.c index ddb8f88040f..246b0e76a3a 100644 --- a/src/imagination/rogue/rogue.c +++ b/src/imagination/rogue/rogue.c @@ -708,6 +708,27 @@ void rogue_link_instr_write(rogue_instr *instr) break; } + case ROGUE_INSTR_TYPE_BITWISE: { + rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr); + const unsigned num_dsts = rogue_bitwise_op_infos[bitwise->op].num_dsts; + + for (unsigned i = 0; i < num_dsts; ++i) { + if (rogue_ref_is_reg(&bitwise->dst[i].ref)) { + rogue_reg_write *write = &bitwise->dst_write[i].reg; + rogue_reg *reg = bitwise->dst[i].ref.reg; + rogue_link_instr_write_reg(instr, write, reg, i); + } else if (rogue_ref_is_regarray(&bitwise->dst[i].ref)) { + rogue_regarray_write *writearray = &bitwise->dst_write[i].regarray; + rogue_regarray *regarray = bitwise->dst[i].ref.regarray; + rogue_link_instr_write_regarray(instr, writearray, regarray, i); + } else { + unreachable("Unsupported destination reference type."); + } + } + + break; + } + default: unreachable("Unsupported instruction type."); } @@ -740,6 +761,8 @@ void rogue_link_instr_use(rogue_instr *instr) instr, i, rogue_ref_get_imm(&alu->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); } } @@ -763,6 +786,8 @@ void rogue_link_instr_use(rogue_instr *instr) rogue_link_drc_trxn(instr->block->shader, instr, rogue_ref_get_drc(&backend->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); } } @@ -796,6 +821,33 @@ void rogue_link_instr_use(rogue_instr *instr) rogue_link_drc_trxn(instr->block->shader, instr, rogue_ref_get_drc(&ctrl->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); + } + } + + break; + } + + case ROGUE_INSTR_TYPE_BITWISE: { + rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr); + const unsigned num_srcs = rogue_bitwise_op_infos[bitwise->op].num_srcs; + + for (unsigned i = 0; i < num_srcs; ++i) { + if (rogue_ref_is_reg(&bitwise->src[i].ref)) { + rogue_reg_use *use = &bitwise->src_use[i].reg; + rogue_reg *reg = bitwise->src[i].ref.reg; + rogue_link_instr_use_reg(instr, use, reg, i); + } else if (rogue_ref_is_regarray(&bitwise->src[i].ref)) { + rogue_regarray_use *usearray = &bitwise->src_use[i].regarray; + rogue_regarray *regarray = bitwise->src[i].ref.regarray; + rogue_link_instr_use_regarray(instr, usearray, regarray, i); + } else if (rogue_ref_is_drc(&bitwise->src[i].ref)) { + rogue_link_drc_trxn(instr->block->shader, + instr, + rogue_ref_get_drc(&bitwise->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); } } @@ -874,6 +926,25 @@ void rogue_unlink_instr_write(rogue_instr *instr) break; } + case ROGUE_INSTR_TYPE_BITWISE: { + rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr); + const unsigned num_dsts = rogue_bitwise_op_infos[bitwise->op].num_dsts; + + for (unsigned i = 0; i < num_dsts; ++i) { + if (rogue_ref_is_reg(&bitwise->dst[i].ref)) { + rogue_reg_write *write = &bitwise->dst_write[i].reg; + rogue_unlink_instr_write_reg(instr, write); + } else if (rogue_ref_is_regarray(&bitwise->dst[i].ref)) { + rogue_regarray_write *writearray = &bitwise->dst_write[i].regarray; + rogue_unlink_instr_write_regarray(instr, writearray); + } else { + unreachable("Invalid destination reference type."); + } + } + + break; + } + default: unreachable("Unsupported instruction type."); } @@ -902,6 +973,8 @@ void rogue_unlink_instr_use(rogue_instr *instr) } else if (rogue_ref_is_imm(&alu->src[i].ref)) { rogue_unlink_imm_use(instr, &rogue_ref_get_imm(&alu->src[i].ref)->use); + } else { + unreachable("Unsupported source reference type."); } } @@ -923,6 +996,8 @@ void rogue_unlink_instr_use(rogue_instr *instr) rogue_unlink_drc_trxn(instr->block->shader, instr, rogue_ref_get_drc(&backend->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); } } @@ -952,6 +1027,31 @@ void rogue_unlink_instr_use(rogue_instr *instr) rogue_unlink_drc_trxn(instr->block->shader, instr, rogue_ref_get_drc(&ctrl->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); + } + } + + break; + } + + case ROGUE_INSTR_TYPE_BITWISE: { + rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr); + const unsigned num_srcs = rogue_bitwise_op_infos[bitwise->op].num_srcs; + + for (unsigned i = 0; i < num_srcs; ++i) { + if (rogue_ref_is_reg(&bitwise->src[i].ref)) { + rogue_reg_use *use = &bitwise->src_use[i].reg; + rogue_unlink_instr_use_reg(instr, use); + } else if (rogue_ref_is_regarray(&bitwise->src[i].ref)) { + rogue_regarray_use *usearray = &bitwise->src_use[i].regarray; + rogue_unlink_instr_use_regarray(instr, usearray); + } else if (rogue_ref_is_drc(&bitwise->src[i].ref)) { + rogue_unlink_drc_trxn(instr->block->shader, + instr, + rogue_ref_get_drc(&bitwise->src[i].ref)); + } else { + unreachable("Unsupported source reference type."); } } diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index a4737ce0149..8bb3530c0f4 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -717,6 +717,11 @@ static inline bool rogue_ref_is_regarray(const rogue_ref *ref) return ref->type == ROGUE_REF_TYPE_REGARRAY; } +static inline bool rogue_ref_is_reg_or_regarray(const rogue_ref *ref) +{ + return rogue_ref_is_reg(ref) || rogue_ref_is_regarray(ref); +} + static inline bool rogue_ref_is_io(const rogue_ref *ref) { return ref->type == ROGUE_REF_TYPE_IO; @@ -1404,11 +1409,11 @@ enum rogue_bitwise_op { ROGUE_BITWISE_OP_INVALID = 0, /* Real instructions. */ - ROGUE_BITWISE_OP_BYP, + ROGUE_BITWISE_OP_BYP0, /* Pseudo-instructions. */ ROGUE_BITWISE_OP_PSEUDO, - ROGUE_BITWISE_OP_MOV2 = ROGUE_BITWISE_OP_PSEUDO, + ROGUE_BITWISE_OP_ = ROGUE_BITWISE_OP_PSEUDO, ROGUE_BITWISE_OP_COUNT, }; @@ -1422,6 +1427,9 @@ typedef struct rogue_bitwise_op_info { 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[ROGUE_BITWISE_OP_MAX_DSTS]; uint64_t supported_src_mods[ROGUE_BITWISE_OP_MAX_SRCS]; @@ -1454,8 +1462,7 @@ typedef struct rogue_bitwise_instr { enum rogue_bitwise_op op; - /* TODO: op mods */ - /* uint64_t mod; */ + uint64_t mod; /* TODO NEXT: source/dest modifiers */ @@ -2108,6 +2115,10 @@ static inline bool rogue_dst_reg_replace(rogue_reg_write *write, ref = &rogue_instr_as_ctrl(instr)->dst[dst_index].ref; break; + case ROGUE_INSTR_TYPE_BITWISE: + ref = &rogue_instr_as_bitwise(instr)->dst[dst_index].ref; + break; + default: unreachable("Unsupported instruction type."); return false; @@ -2267,6 +2278,16 @@ static inline unsigned rogue_instr_supported_phases(const rogue_instr *instr) break; } + case ROGUE_INSTR_TYPE_BITWISE: { + rogue_bitwise_instr *bitwise = rogue_instr_as_bitwise(instr); + if (bitwise->op >= ROGUE_BITWISE_OP_PSEUDO) + return 0; + + const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op]; + supported_phases = info->supported_phases; + break; + } + default: unreachable("Unsupported instruction type."); } diff --git a/src/imagination/rogue/rogue_bitwise_instrs.def b/src/imagination/rogue/rogue_bitwise_instrs.def index e667a82ad6d..0782830ff32 100644 --- a/src/imagination/rogue/rogue_bitwise_instrs.def +++ b/src/imagination/rogue/rogue_bitwise_instrs.def @@ -37,7 +37,6 @@ #define ROGUE_BUILDER_DEFINE_BITWISE22(...) #endif /* ROGUE_BUILDER_DEFINE_BITWISE22 */ -ROGUE_BUILDER_DEFINE_BITWISE22(MOV2) -ROGUE_BUILDER_DEFINE_BITWISE22(BYP) +ROGUE_BUILDER_DEFINE_BITWISE22(BYP0) #undef ROGUE_BUILDER_DEFINE_BITWISE22 diff --git a/src/imagination/rogue/rogue_encode.c b/src/imagination/rogue/rogue_encode.c index 21e136bc639..eeb9791ebfc 100644 --- a/src/imagination/rogue/rogue_encode.c +++ b/src/imagination/rogue/rogue_encode.c @@ -181,6 +181,7 @@ typedef union rogue_instr_encoding { rogue_alu_instr_encoding alu; rogue_backend_instr_encoding backend; rogue_ctrl_instr_encoding ctrl; + rogue_bitwise_instr_encoding bitwise; } PACKED rogue_instr_encoding; #define SM(src_mod) ROGUE_ALU_SRC_MOD_##src_mod @@ -394,7 +395,40 @@ static void rogue_encode_ctrl_instr(const rogue_ctrl_instr *ctrl, } } -/* TODO: Add p2end where required. */ +static void rogue_encode_bitwise_instr(const rogue_bitwise_instr *bitwise, + unsigned instr_size, + rogue_instr_encoding *instr_encoding) +{ + switch (bitwise->op) { + case ROGUE_BITWISE_OP_BYP0: { + instr_encoding->bitwise.phase0 = 1; + instr_encoding->bitwise.ph0.shft = SHFT1_BYP; + instr_encoding->bitwise.ph0.cnt_byp = 1; + + rogue_imm32 imm32; + if (rogue_ref_is_val(&bitwise->src[1].ref)) + imm32._ = rogue_ref_get_val(&bitwise->src[1].ref); + + if (instr_size > 1) { + instr_encoding->bitwise.ph0.ext = 1; + instr_encoding->bitwise.ph0.imm_7_0 = imm32._7_0; + instr_encoding->bitwise.ph0.imm_15_8 = imm32._15_8; + } + + if (instr_size > 3) { + instr_encoding->bitwise.ph0.bm = 1; + instr_encoding->bitwise.ph0.imm_23_16 = imm32._23_16; + instr_encoding->bitwise.ph0.imm_31_24 = imm32._31_24; + } + + break; + } + + default: + unreachable("Invalid bitwise op."); + } +} + static void rogue_encode_instr_group_instrs(rogue_instr_group *group, struct util_dynarray *binary) { @@ -427,6 +461,12 @@ static void rogue_encode_instr_group_instrs(rogue_instr_group *group, &instr_encoding); break; + case ROGUE_INSTR_TYPE_BITWISE: + rogue_encode_bitwise_instr(rogue_instr_as_bitwise(instr), + group->size.instrs[p], + &instr_encoding); + break; + default: unreachable("Unsupported instruction type."); } diff --git a/src/imagination/rogue/rogue_info.c b/src/imagination/rogue/rogue_info.c index 65dd5677d50..cf5b3c3d08c 100644 --- a/src/imagination/rogue/rogue_info.c +++ b/src/imagination/rogue/rogue_info.c @@ -297,11 +297,29 @@ const rogue_backend_op_mod_info rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_ [ROGUE_BACKEND_OP_MOD_SAT] = { .str = "sat", }, }; +#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type) +#define PH(type) ROGUE_INSTR_PHASE_##type +#define IO(io) ROGUE_IO_##io +#define T(type) BITFIELD64_BIT(ROGUE_REF_TYPE_##type - 1) const rogue_bitwise_op_info rogue_bitwise_op_infos[ROGUE_BITWISE_OP_COUNT] = { [ROGUE_BITWISE_OP_INVALID] = { .str = "", }, - [ROGUE_BITWISE_OP_BYP] = { .str = "byp", .num_dsts = 2, .num_srcs = 2, }, - [ROGUE_BITWISE_OP_MOV2] = { .str = "mov2", .num_dsts = 2, .num_srcs = 2, }, + [ROGUE_BITWISE_OP_BYP0] = { .str = "byp", .num_dsts = 2, .num_srcs = 2, + .supported_phases = P(0_BITMASK), + .phase_io[PH(0_BITMASK)] = { .dst[1] = IO(FT1), }, + .supported_dst_types = { + [0] = T(REG) | T(REGARRAY) | T(IO), + [1] = T(REG) | T(REGARRAY) | T(IO), + }, + .supported_src_types = { + [0] = T(REG) | T(REGARRAY) | T(IO), + [1] = T(REG) | T(REGARRAY) | T(IO) | T(VAL), + }, + }, }; +#undef T +#undef IO +#undef PH +#undef P const rogue_io_info rogue_io_infos[ROGUE_IO_COUNT] = { [ROGUE_IO_INVALID] = { .str = "!INVALID!", }, diff --git a/src/imagination/rogue/rogue_isa.h b/src/imagination/rogue/rogue_isa.h index 220ac830f2c..d0d3ab6bebe 100644 --- a/src/imagination/rogue/rogue_isa.h +++ b/src/imagination/rogue/rogue_isa.h @@ -993,6 +993,161 @@ enum ctrlop { CTRLOP_SBO = 0b1011, }; +/* Bitwise phase 0: logical */ +typedef struct rogue_bitwise_ph0_encoding { + /* Byte 0 */ + struct { + unsigned bm : 1; + unsigned cnt_byp : 1; + unsigned shft : 2; + unsigned ext : 1; + unsigned cnt : 1; + unsigned csrc : 1; + unsigned : 1; + } PACKED; + + /* Byte 1 */ + struct { + unsigned imm_7_0 : 8; + } PACKED; + + /* Byte 2 */ + struct { + unsigned imm_15_8 : 8; + } PACKED; + + /* Byte 3 */ + struct { + unsigned imm_23_16 : 8; + } PACKED; + + /* Byte 4 */ + struct { + unsigned imm_31_24 : 8; + } PACKED; +} PACKED rogue_bitwise_ph0_encoding; +static_assert(sizeof(rogue_bitwise_ph0_encoding) == 5, + "sizeof(rogue_bitwise_ph0_encoding) != 5"); + +enum shft1 { + SHFT1_BYP = 0b00, + SHFT1_SHFL = 0b01, + SHFT1_REV = 0b10, + SHFT1_LSL = 0b11, +}; + +enum cnt { + CNT_CBS = 0b0, + CNT_FTB = 0b1, +}; + +enum csrc { + CNT_S2 = 0b0, + CNT_FT2 = 0b1, +}; + +typedef struct rogue_imm32 { + union { + struct { + struct { + unsigned _7_0 : 8; + } PACKED; + + struct { + unsigned _15_8 : 8; + } PACKED; + + struct { + unsigned _23_16 : 8; + } PACKED; + + struct { + unsigned _31_24 : 8; + } PACKED; + } PACKED; + + uint32_t _; + } PACKED; +} PACKED rogue_imm32; +static_assert(sizeof(rogue_imm32) == 4, "sizeof(rogue_imm32) != 4"); + +/* Bitwise phase 1: logical */ +typedef struct rogue_bitwise_ph1_encoding { + /* Byte 0 */ + struct { + unsigned op : 3; + unsigned mska : 1; + unsigned : 1; + unsigned mskb : 1; + unsigned : 2; + } PACKED; +} PACKED rogue_bitwise_ph1_encoding; +static_assert(sizeof(rogue_bitwise_ph1_encoding) == 1, + "sizeof(rogue_bitwise_ph1_encoding) != 1"); + +enum ph1op { + PH1OP_OR = 0b000, + PH1OP_AND = 0b001, + PH1OP_XOR = 0b010, + PH1OP_NOR = 0b100, + PH1OP_NAND = 0b101, + PH1OP_XNOR = 0b110, + PH1OP_BYP = 0b111, +}; + +/* Bitwise phase 2: shift2/test */ +typedef struct rogue_bitwise_ph2_encoding { + /* Byte 0 */ + struct { + unsigned shft : 3; + unsigned top : 1; + unsigned tsrc : 1; + unsigned pwen : 1; + unsigned : 2; + } PACKED; +} PACKED rogue_bitwise_ph2_encoding; +static_assert(sizeof(rogue_bitwise_ph2_encoding) == 1, + "sizeof(rogue_bitwise_ph2_encoding) != 1"); + +enum shft2 { + SHFT2_LSL = 0b000, + SHFT2_SHR = 0b001, + SHFT2_ROL = 0b010, + SHFT2_CPS = 0b011, + SHFT2_ASR_TWB = 0b100, + SHFT2_ASR_PWB = 0b101, + SHFT2_ASR_MTB = 0b110, + SHFT2_ASR_FTB = 0b111, +}; + +enum top { + TOP_TZ = 0b0, + TOP_TNZ = 0b1, +}; + +enum tsrc { + TSRC_FT5 = 0b0, + TSRC_FT3 = 0b1, +}; + +/* Common for all bitwise instructions. */ +typedef struct rogue_bitwise_instr_encoding { + union { + /* Bytes 0+ */ + struct { + unsigned : 6; + unsigned phase1 : 1; + unsigned phase0 : 1; + } PACKED; + + rogue_bitwise_ph0_encoding ph0; + rogue_bitwise_ph1_encoding ph1; + rogue_bitwise_ph2_encoding ph2; + } PACKED; +} PACKED rogue_bitwise_instr_encoding; +static_assert(sizeof(rogue_bitwise_instr_encoding) == 5, + "sizeof(rogue_bitwise_instr_encoding) != 5"); + typedef struct rogue_instr_group_header_encoding { /* Byte 0 */ struct { diff --git a/src/imagination/rogue/rogue_print.c b/src/imagination/rogue/rogue_print.c index 975e99cd9e4..ccc920096de 100644 --- a/src/imagination/rogue/rogue_print.c +++ b/src/imagination/rogue/rogue_print.c @@ -378,6 +378,44 @@ static inline void rogue_print_ctrl_instr(FILE *fp, } } +static inline void rogue_print_bitwise_dst(FILE *fp, const rogue_instr_dst *dst) +{ + rogue_print_ref(fp, &dst->ref); +} + +static inline void rogue_print_bitwise_src(FILE *fp, const rogue_instr_src *src) +{ + rogue_print_ref(fp, &src->ref); +} + +static inline void rogue_print_bitwise_instr(FILE *fp, + const rogue_bitwise_instr *bitwise) +{ + const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op]; + + fprintf(fp, "%s", info->str); + + /* rogue_print_bitwise_mods(fp, bitwise); */ + + for (unsigned i = 0; i < info->num_dsts; ++i) { + if (i > 0) + fputs(",", fp); + + fputs(" ", fp); + + rogue_print_bitwise_dst(fp, &bitwise->dst[i]); + } + + for (unsigned i = 0; i < info->num_srcs; ++i) { + if (i == 0 && !info->num_dsts) + fputs(" ", fp); + else + fputs(", ", fp); + + rogue_print_bitwise_src(fp, &bitwise->src[i]); + } +} + PUBLIC void rogue_print_instr(FILE *fp, const rogue_instr *instr) { @@ -398,6 +436,10 @@ void rogue_print_instr(FILE *fp, const rogue_instr *instr) rogue_print_ctrl_instr(fp, rogue_instr_as_ctrl(instr)); break; + case ROGUE_INSTR_TYPE_BITWISE: + rogue_print_bitwise_instr(fp, rogue_instr_as_bitwise(instr)); + break; + default: unreachable("Unsupported instruction type."); } diff --git a/src/imagination/rogue/rogue_validate.c b/src/imagination/rogue/rogue_validate.c index 2e98120d2da..a0c351b9e60 100644 --- a/src/imagination/rogue/rogue_validate.c +++ b/src/imagination/rogue/rogue_validate.c @@ -369,6 +369,47 @@ static bool validate_ctrl_instr(rogue_validation_state *state, return info->ends_block; } +static void validate_bitwise_instr(rogue_validation_state *state, + const rogue_bitwise_instr *bitwise) +{ + if (bitwise->op == ROGUE_BITWISE_OP_INVALID || + bitwise->op >= ROGUE_BITWISE_OP_COUNT) + validate_log(state, "Unknown bitwise op 0x%x encountered.", bitwise->op); + + const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op]; + + /* Initial check if instruction modifiers are valid. */ + if (!rogue_mods_supported(bitwise->mod, info->supported_op_mods)) + validate_log(state, "Unsupported bitwise op modifiers."); + + /* Instruction repeat checks. */ + if (bitwise->instr.repeat > 1 && !info->dst_repeat_mask && + !info->src_repeat_mask) { + validate_log(state, "Repeat set for bitwise op without repeat support."); + } + + /* Validate destinations and sources. */ + for (unsigned i = 0; i < info->num_dsts; ++i) { + validate_dst(state, + &bitwise->dst[i], + info->supported_dst_types[i], + i, + info->dst_stride[i], + bitwise->instr.repeat, + info->dst_repeat_mask); + } + + for (unsigned i = 0; i < info->num_srcs; ++i) { + validate_src(state, + &bitwise->src[i], + info->supported_src_types[i], + i, + info->src_stride[i], + bitwise->instr.repeat, + info->src_repeat_mask); + } +} + /* Returns true if instruction can end block. */ static bool validate_instr(rogue_validation_state *state, const rogue_instr *instr) @@ -390,6 +431,10 @@ static bool validate_instr(rogue_validation_state *state, ends_block = validate_ctrl_instr(state, rogue_instr_as_ctrl(instr)); break; + case ROGUE_INSTR_TYPE_BITWISE: + validate_bitwise_instr(state, rogue_instr_as_bitwise(instr)); + break; + default: validate_log(state, "Unknown instruction type 0x%x encountered.",