mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 15:38:09 +02:00
pvr: Add bitwise instruction support
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/21331>
This commit is contained in:
parent
93fa2f6265
commit
888e06b8cc
10 changed files with 499 additions and 9 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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!", },
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue