diff --git a/src/imagination/pco/pco_map.py b/src/imagination/pco/pco_map.py index 88ca75491ed..ddfef93fc23 100644 --- a/src/imagination/pco/pco_map.py +++ b/src/imagination/pco/pco_map.py @@ -192,6 +192,15 @@ enum_map(OM_TST_TYPE_MAIN.t, F_TST_TYPE, [ ('s32', 's32'), ]) +enum_map(OM_LOGIOP.t, F_LOGICAL_OP, [ + ('or', 'or'), + ('and', 'and'), + ('xor', 'xor'), + ('nor', 'nor'), + ('nand', 'nand'), + ('xnor', 'xnor'), +]) + enum_map(RM_ELEM.t, F_UPCK_ELEM, [ ('e0', 'e0'), ('e1', 'e1'), @@ -794,6 +803,27 @@ encode_map(O_BBYP0BM_IMM32, ] ) +encode_map(O_BBYP0S1, + encodings=[ + (I_PHASE0_SRC, [ + ('count_src', 's2'), + ('count_op', 'byp'), + ('bitmask_src_op', 'byp'), + ('shift1_op', 'byp') + ]) + ] +) + +encode_map(O_LOGICAL, + encodings=[ + (I_PHASE1, [ + ('mskb', False), + ('mska', False), + ('logical_op', OM_LOGIOP), + ]) + ] +) + encode_map(O_WOP, encodings=[(I_WOP, [])]) encode_map(O_WDF, encodings=[(I_WDF, [])]) encode_map(O_NOP, encodings=[(I_NOP, [])]) @@ -1189,6 +1219,28 @@ group_map(O_MOVI32, dests=[('w[0]', ('0', 'dest[1]'), 'ft1')] ) +group_map(O_LOGICAL, + hdr=(I_IGRP_HDR_BITWISE, [ + ('opcnt', ['p0', 'p1']), + ('olchk', OM_OLCHK), + ('w1p', False), + ('w0p', True), + ('cc', OM_EXEC_CND), + ('end', OM_END), + ('atom', OM_ATOM), + ('rpt', OM_RPT) + ]), + enc_ops=[ + ('0', O_BBYP0S1, ['ft2'], ['src[0]']), + ('1', O_LOGICAL, ['dest[0]'], ['ft2', 'src[1]'], [(OM_LOGIOP, OM_LOGIOP)]) + ], + srcs=[ + ('s[2]', ('0', 'src[0]'), 's2'), + ('s[3]', ('1', 'src[1]'), 's3') + ], + dests=[('w[0]', ('1', 'dest[0]'), 'ft4')] +) + group_map(O_WOP, hdr=(I_IGRP_HDR_CONTROL, [ ('olchk', False), diff --git a/src/imagination/pco/pco_ops.py b/src/imagination/pco/pco_ops.py index bdf8dc21115..60ad90b29da 100644 --- a/src/imagination/pco/pco_ops.py +++ b/src/imagination/pco/pco_ops.py @@ -277,6 +277,14 @@ OM_ATOM = op_mod('atom', BaseType.bool, unset=True) OM_OLCHK = op_mod('olchk', BaseType.bool, unset=True) OM_END = op_mod('end', BaseType.bool, unset=True) +OM_LOGIOP = op_mod_enum('logiop', [ + 'or', + 'and', + 'xor', + 'nor', + 'nand', + 'xnor', +]) # Ops. OM_ALU = [OM_OLCHK, OM_EXEC_CND, OM_END, OM_ATOM, OM_RPT] @@ -313,7 +321,10 @@ O_LD = hw_op('ld', OM_ALU_RPT1 + [OM_MCU_CACHE_MODE_LD], 1, 3) ## Bitwise. O_MOVI32 = hw_op('movi32', OM_ALU, 1, 1) +O_LOGICAL = hw_op('logical', OM_ALU + [OM_LOGIOP], 1, 2) + O_BBYP0BM_IMM32 = hw_direct_op('bbyp0bm', [], 2, 2) +O_BBYP0S1 = hw_direct_op('bbyp0s1', [], 1, 1) ## Control. O_WOP = hw_op('wop') diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 5a3c65275a4..560d09c9296 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -641,6 +641,54 @@ trans_scmp(trans_ctx *tctx, nir_op op, pco_ref dest, pco_ref src0, pco_ref src1) return pco_scmp(&tctx->b, dest, src0, src1, .tst_op_main = tst_op_main); } +/** + * \brief Translates a NIR bitwise logical op into PCO. + * + * \param[in,out] tctx Translation context. + * \param[in] op The NIR op. + * \param[in] dest Instruction destination. + * \param[in] src0 First logical operand. + * \param[in] src1 Second logical operand. + * \return The translated PCO instruction. + */ +static pco_instr *trans_logical(trans_ctx *tctx, + nir_op op, + pco_ref dest, + pco_ref src0, + pco_ref src1) +{ + ASSERTED unsigned bits = pco_ref_get_bits(dest); + + /* TODO: bool support. */ + /* TODO: 8/16-bit support via masking. */ + assert(bits == 32); + + enum pco_logiop logiop; + switch (op) { + case nir_op_iand: + logiop = PCO_LOGIOP_AND; + break; + + case nir_op_ior: + logiop = PCO_LOGIOP_OR; + break; + + case nir_op_ixor: + logiop = PCO_LOGIOP_XOR; + break; + + case nir_op_inot: + logiop = PCO_LOGIOP_XNOR; + src1 = pco_zero; + break; + + default: + unreachable(); + } + + return pco_logical(&tctx->b, dest, src0, src1, .logiop = logiop); +} + /** * \brief Translates a NIR alu instruction into PCO. * @@ -696,6 +744,13 @@ static pco_instr *trans_alu(trans_ctx *tctx, nir_alu_instr *alu) instr = trans_scmp(tctx, alu->op, dest, src[0], src[1]); break; + case nir_op_iand: + case nir_op_ior: + case nir_op_ixor: + case nir_op_inot: + instr = trans_logical(tctx, alu->op, dest, src[0], src[1]); + break; + case nir_op_f2i32: instr = pco_pck(&tctx->b, dest,