ppc/svp64: validate SVP64 context
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 19 Jun 2022 16:59:00 +0000 (19:59 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Fri, 23 Sep 2022 17:11:54 +0000 (20:11 +0300)
gas/config/tc-ppc-svp64.c

index 21f6014d0048f3f9f08db5b05a71245d9a2c6101..b867b186df4418f08052b7642a81dd9280e42767 100644 (file)
@@ -756,6 +756,75 @@ svp64_decode (char *str, struct svp64_ctx *svp64)
     svp64_raise (_("unrecognized opcode: `%s'"), str);
 }
 
+static void
+svp64_validate (struct svp64_ctx *svp64)
+{
+  if (svp64->desc->ptype == SVP64_PTYPE_P2)
+    {
+      /*
+       * Since m=xx takes precedence (overrides) sm=xx and dm=xx,
+       * treat them as mutually exclusive.
+       */
+      if (svp64->mask_m_specified)
+        {
+          svp64_raise_if (svp64->has_smask,
+            "cannot have both source-mask and predicate mask");
+          svp64_raise_if (svp64->has_pmask,
+            "cannot have both dest-mask and predicate mask");
+        }
+
+      /*
+       * Since the default is INT predication (ALWAYS), if you
+       * specify one CR mask, you must specify both, to avoid
+       * mixing INT and CR reg types.
+       */
+      if (svp64->has_pmask && (svp64->pmmode == 1))
+        {
+          svp64_raise_if (!svp64->has_smask,
+            "need explicit source-mask in CR twin predication");
+        }
+      if (svp64->has_smask && (svp64->smmode == 1))
+        {
+          svp64_raise_if (!svp64->has_pmask,
+            "need explicit dest-mask in CR twin predication");
+        }
+
+      /* Sanity-check that 2Pred mask is same mode. */
+      if (svp64->has_pmask && svp64->has_smask)
+        {
+          svp64_raise_if (svp64->smmode != svp64->pmmode,
+            "predicate masks mismatch: pmmode=0x%08x, smmode=0x%08x",
+            (unsigned int)svp64->pmmode, (unsigned int)svp64->smmode);
+        }
+      else if (svp64->desc->ptype == SVP64_PTYPE_P1)
+        {
+          svp64_raise_if (svp64->has_smask,
+            "source-mask can only be specified on Twin-predicate ops");
+          svp64_raise_if (svp64->has_pmask,
+            "dest-mask can only be specified on Twin-predicate ops");
+        }
+    }
+
+  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,
+        "src zeroing requires a source predicate");
+    }
+  if (svp64->dst_zero)
+    {
+      svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified,
+        "dest zeroing requires a dest predicate");
+    }
+}
+
 static void
 svp64_assemble (char *str)
 {
@@ -767,6 +836,7 @@ svp64_assemble (char *str)
   memset (&svp64, 0, sizeof (svp64));
 
   svp64_decode (str, &svp64);
+  svp64_validate (&svp64);
 
   as_warn (_("opcode ignored (desc=%p)"), svp64.desc);
   memcpy (str, "nop", sizeof ("nop"));