ppc/svp64: validate SVP64 context
authorDmitry Selyutin <ghostmansd@gmail.com>
Tue, 11 Apr 2023 18:27:25 +0000 (21:27 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Wed, 26 Apr 2023 16:42:45 +0000 (19:42 +0300)
gas/config/tc-ppc-svp64.c

index 819d64573918bf589a610da4ed34e027f1143f59..cbaaaf5fbd9a457819604a8c9504ee9eaf832219 100644 (file)
@@ -608,6 +608,67 @@ svp64_decode (char *str, struct svp64_ctx *svp64)
     ;
 }
 
+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->dz)
+    {
+      svp64_raise_if (!svp64->has_pmask && !svp64->mask_m_specified,
+        "dest zeroing requires a dest predicate");
+    }
+  if (svp64->sz)
+    {
+      svp64_raise_if (!svp64->has_smask && !svp64->mask_m_specified,
+        "src zeroing requires a source predicate");
+    }
+}
+
 static void
 svp64_assemble (char *str)
 {
@@ -619,6 +680,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"));