From d2f3a4eea248d47d548a87d958d55d0d24405c62 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Sun, 19 Jun 2022 20:59:19 +0300 Subject: [PATCH] ppc/svp64: validate and fix modes --- gas/config/tc-ppc-svp64.c | 212 +++++++++++++++++++++++++++++++++----- 1 file changed, 186 insertions(+), 26 deletions(-) diff --git a/gas/config/tc-ppc-svp64.c b/gas/config/tc-ppc-svp64.c index 0f7db8c474a..b9a07c2f594 100644 --- a/gas/config/tc-ppc-svp64.c +++ b/gas/config/tc-ppc-svp64.c @@ -45,7 +45,6 @@ struct svp64_ctx { unsigned int mr : 1; unsigned int rg : 1; unsigned int crm : 1; - unsigned int svm : 1; unsigned int type : 2; unsigned int rc : 1; unsigned int mode : 5; @@ -533,20 +532,6 @@ svp64_decode_crm (char *str, struct svp64_ctx *svp64) return str; } -static char * -svp64_decode_svm (char *str, struct svp64_ctx *svp64) -{ - str += (sizeof ("svm") - 1); - if ( ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0') - return NULL; - - svp64->svm = 1; - - *str++ = '\0'; - - return str; -} - static char * svp64_decode_mode (char *str, struct svp64_ctx *svp64) { @@ -571,7 +556,6 @@ svp64_decode_mode (char *str, struct svp64_ctx *svp64) SVP64_DECODER ("mr" , svp64_decode_mr), SVP64_DECODER ("mrr" , svp64_decode_mrr), SVP64_DECODER ("crm" , svp64_decode_crm), - SVP64_DECODER ("svm" , svp64_decode_svm), }; for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i) @@ -768,7 +752,189 @@ svp64_decode (char *str, struct svp64_ctx *svp64) } static void -svp64_validate (struct svp64_ctx *svp64) +svp64_validate_and_fix_mode_bc (struct svp64_ctx *svp64) +{ + /* + * Create mode and (overridden) src/dst widths. + * TODO: sanity-check BC modes. + */ + svp64->sv_mode = ((svp64->bc_svstep << SVP64_MODE_MOD2_MSB) | + (svp64->bc_vlset << SVP64_MODE_MOD2_LSB) | + (svp64->bc_snz << SVP64_MODE_BC_SNZ)); + svp64->srcwid = ((svp64->bc_vsb << 1) | svp64->bc_lru); + svp64->destwid = ((svp64->bc_lru << 1) | svp64->bc_all); +} + +static void +svp64_validate_and_fix_mode_mr (struct svp64_ctx *svp64) +{ + svp64->mode |= (1U << SVP64_MODE_REDUCE); + svp64_raise_if (svp64->dst_zero, + "dest-zero not allowed in mr mode"); + + if (svp64->rg) + svp64->mode |= (1U << SVP64_MODE_RG); + + if (svp64->crm) + { + svp64->mode |= (1U << SVP64_MODE_CRM); + svp64_raise_if (!svp64->rc, "CRM only allowed when Rc=1"); + } + + /* + * Bit of weird encoding to jam zero-pred or SVM mode in. + * SVM mode can be enabled only when SUBVL=2/3/4 (vec2/3/4) + */ + if (svp64->subvl == 0) + svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ); +} + +static void +svp64_validate_and_fix_mode_ff(struct svp64_ctx *svp64) +{ + svp64_raise_if (svp64->src_zero, + "dest-zero not allowed in ff mode"); + + if (svp64->ff & SVP64_RC1_ACTIVE) + { + svp64->mode |= (1U << SVP64_MODE_RC1); + svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ); + svp64_raise_if (svp64->rc, + "ffirst RC1/~RC1 only possible when Rc=0"); + if (svp64->ff & SVP64_RC1_INVERT) + svp64->mode |= (1U << SVP64_MODE_INV); + } + else + { + svp64_raise_if (svp64->dst_zero, + "dst-zero not allowed in ffirst BO"); + svp64_raise_if (!svp64->rc, + "ffirst BO only possible when Rc=1"); + svp64->mode |= (svp64->ff << SVP64_MODE_BO_LSB); + } +} + +static void +svp64_validate_and_fix_mode_sat(struct svp64_ctx *svp64) +{ + svp64->mode |= (svp64->src_zero << SVP64_MODE_SZ); + svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ); + svp64->mode |= (svp64->sat << SVP64_MODE_N); +} + +static void +svp64_validate_and_fix_mode_pr(struct svp64_ctx *svp64) +{ + svp64_raise_if (svp64->src_zero, + "dest-zero not allowed in pr mode"); + + if (svp64->pr & SVP64_RC1_ACTIVE) + { + svp64->mode |= (1U << SVP64_MODE_RC1); + svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ); + svp64_raise_if (svp64->rc, + "pr-mode RC1/~RC1 only possible when Rc=0"); + if (svp64->pr & SVP64_RC1_INVERT) + svp64->mode |= (1U << SVP64_MODE_INV); + } + else + { + svp64_raise_if (svp64->dst_zero, + "dst-zero not allowed in pr-mode BO"); + svp64_raise_if (!svp64->rc, + "pr-mode BO only possible when Rc=1"); + svp64->mode |= (svp64->pr << SVP64_MODE_BO_LSB); + } +} + +static void +svp64_validate_and_fix_mode_explicit(struct svp64_ctx *svp64) +{ + static void (*const table[])(struct svp64_ctx *svp64) = { + svp64_validate_and_fix_mode_mr, + svp64_validate_and_fix_mode_ff, + svp64_validate_and_fix_mode_sat, + svp64_validate_and_fix_mode_pr, + }; + + return table[svp64->sv_mode] (svp64); +} + +static void +svp64_validate_and_fix_mode_normal (struct svp64_ctx *svp64) +{ + svp64->mode |= (svp64->src_zero << SVP64_MODE_SZ); + svp64->mode |= (svp64->dst_zero << SVP64_MODE_DZ); + if ((svp64->type == SVP64_TYPE_LD) || + (svp64->type == SVP64_TYPE_ST)) + { + /* TODO: for now, LD/ST-indexed is ignored. */ + svp64->mode |= (svp64->ldst_elstride << SVP64_MODE_ELS_NORMAL); + } + else + { + /* + * TODO: reduce and subvector mode. + * 00 1 dz CRM reduce mode (mr), SUBVL=1 + * 00 1 SVM CRM subvector reduce mode, SUBVL>1 + */ + } + svp64->sv_mode = 0; +} + +/* + * There are 4 different modes, here, which will be partly-merged-in: + * is_ldst is merged in with "normal", but is_bc is so different it's + * done separately. Likewise is_cr (when it is done). + * + * "normal" arithmetic: https://libre-soc.org/openpower/sv/normal + * | 0-1 | 2 | 3 4 | description | + * | --- | --- |---------|------------------------------------------ | + * | 00 | 0 | dz sz | normal mode | + * | 00 | 1 | 0 RG | scalar reduce mode (mr), SUBVL=1 | + * | 00 | 1 | 1 / | parallel reduce mode (mr), SUBVL=1 | + * | 00 | 1 | SVM RG | subvector reduce mode, SUBVL>1 | + * | 01 | inv | CR-bit | Rc=1: ffirst CR sel | + * | 01 | inv | VLi RC1 | Rc=0: ffirst z/nonz | + * | 10 | N | dz sz | sat mode: N=0/1 u/s | + * | 11 | inv | CR-bit | Rc=1: pred-result CR sel | + * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz | + * + * LD/ST-immediate: https://libre-soc.org/openpower/sv/ldst + * | 0-1 | 2 | 3 4 | description | + * | --- | --- |---------|------------------------------------------ | + * | 00 | 0 | dz els | normal mode | + * | 00 | 1 | dz shf | shift mode | + * | 01 | inv | CR-bit | Rc=1: ffirst CR sel | + * | 01 | inv | els RC1 | Rc=0: ffirst z/nonz | + * | 10 | N | dz els | sat mode: N=0/1 u/s | + * | 11 | inv | CR-bit | Rc=1: pred-result CR sel | + * | 11 | inv | els RC1 | Rc=0: pred-result z/nonz | + * + * LD/ST-indexed (RA+RB): https://libre-soc.org/openpower/sv/ldst + * | 0-1 | 2 | 3 4 | description | + * | --- | --- |---------|------------------------------------------ | + * | 00 | SEA | dz sz | normal mode | + * | 01 | SEA | dz sz | Strided (scalar only source) | + * | 10 | N | dz sz | sat mode: N=0/1 u/s | + * | 11 | inv | CR-bit | Rc=1: pred-result CR sel | + * | 11 | inv | dz RC1 | Rc=0: pred-result z/nonz | + * + * ...and branches/cr_ops are still in development. + */ +static void +svp64_validate_and_fix_mode (struct svp64_ctx *svp64) +{ + if (svp64->type == SVP64_TYPE_BC) + svp64_validate_and_fix_mode_bc (svp64); + else if (svp64->sv_mode_explicit) + svp64_validate_and_fix_mode_explicit (svp64); + else + svp64_validate_and_fix_mode_normal (svp64); +} + +static void +svp64_validate_and_fix (struct svp64_ctx *svp64) { if (svp64->desc->ptype == SVP64_PTYPE_P2) { @@ -816,14 +982,6 @@ svp64_validate (struct svp64_ctx *svp64) } } - if (svp64->svm) - { - svp64_raise_if (svp64->sv_mode != 0, - "sub-vector mode in mapreduce only"); - svp64_raise_if (svp64->subvl == 0, - "sub-vector mode not possible on SUBVL!=0"); - } - if (svp64->src_zero) { svp64_raise_if (!svp64->has_smask && !svp64->mask_m_specified, @@ -834,6 +992,8 @@ svp64_validate (struct svp64_ctx *svp64) svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified, "dest zeroing requires a dest predicate"); } + + svp64_validate_and_fix_mode (svp64); } static void @@ -847,7 +1007,7 @@ svp64_assemble (char *str) memset (&svp64, 0, sizeof (svp64)); svp64_decode (str, &svp64); - svp64_validate (&svp64); + svp64_validate_and_fix (&svp64); as_warn (_("opcode ignored (desc=%p)"), svp64.desc); memcpy (str, "nop", sizeof ("nop")); -- 2.30.2