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;
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)
{
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)
}
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)
{
}
}
- 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,
svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified,
"dest zeroing requires a dest predicate");
}
+
+ svp64_validate_and_fix_mode (svp64);
}
static void
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"));