ppc/svp64: support m/dm/sm modes
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 19 Jun 2022 07:33:44 +0000 (10:33 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Fri, 23 Sep 2022 17:11:53 +0000 (20:11 +0300)
gas/config/tc-ppc-svp64.c

index 0a61752ff2672c5a9c5d23d5c789ec765729113f..b83dbc881f84acd07da3dde73a971f4361f503b7 100644 (file)
 
 struct svp64_ctx {
   const struct svp64_desc *desc;
+  unsigned int pmmode : 1;
+  unsigned int pmask : 3;
+  unsigned int smmode : 1;
+  unsigned int smask : 3;
+  unsigned int mmode : 1;
+  unsigned int has_pmask : 1;
+  unsigned int has_smask : 1;
+  unsigned int mask_m_specified : 1;
+  unsigned int subvl : 2;
 };
 
 static jmp_buf svp64_exception;
@@ -62,10 +71,170 @@ svp64_setup_records (void)
 
 #define SVP64_SEP '/'
 
+struct svp64_predicate_map {
+  const char *str;
+  unsigned int len : 3;
+  unsigned int cr : 1;
+  unsigned int mask : 3;
+};
+#define SVP64_PREDICATE_MAP(STR, MODE, MASK) \
+  { STR, (sizeof (STR) - 1), MODE, MASK }
+
+static char *
+svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
+{
+  size_t i;
+  static const struct svp64_predicate_map table[] = {
+    /* integer */
+    SVP64_PREDICATE_MAP ("1<<r3", 0, 1),
+    SVP64_PREDICATE_MAP ("r3"   , 0, 2),
+    SVP64_PREDICATE_MAP ("~r3"  , 0, 3),
+    SVP64_PREDICATE_MAP ("r10"  , 0, 4),
+    SVP64_PREDICATE_MAP ("~r10" , 0, 5),
+    SVP64_PREDICATE_MAP ("r30"  , 0, 6),
+    SVP64_PREDICATE_MAP ("~r30" , 0, 7),
+    /* CR */
+    SVP64_PREDICATE_MAP ("lt"   , 1, 0),
+    SVP64_PREDICATE_MAP ("nl"   , 1, 1),
+    SVP64_PREDICATE_MAP ("ge"   , 1, 1), /* same value as nl */
+    SVP64_PREDICATE_MAP ("gt"   , 1, 2),
+    SVP64_PREDICATE_MAP ("ng"   , 1, 3),
+    SVP64_PREDICATE_MAP ("le"   , 1, 3), /* same value as ng */
+    SVP64_PREDICATE_MAP ("eq"   , 1, 4),
+    SVP64_PREDICATE_MAP ("ne"   , 1, 5),
+    SVP64_PREDICATE_MAP ("so"   , 1, 6),
+    SVP64_PREDICATE_MAP ("un"   , 1, 6), /* same value as so */
+    SVP64_PREDICATE_MAP ("ns"   , 1, 7),
+    SVP64_PREDICATE_MAP ("nu"   , 1, 7), /* same value as ns */
+  };
+
+  for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
+    {
+      const struct svp64_predicate_map *entry = &table[i];
+
+      if (strncmp (str, entry->str, entry->len) != 0)
+        continue;
+
+      str += entry->len;
+      if (! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0')
+        {
+          str -= entry->len;
+          continue;
+        }
+
+      *mask = entry->mask;
+      *cr = entry->cr;
+
+      *str++ = '\0';
+
+      return str;
+    }
+
+  return NULL;
+}
+
+struct svp64_decoder {
+  char *(*call)(char *str, struct svp64_ctx *svp64);
+  const char *str;
+  size_t len;
+};
+#define SVP64_DECODER(STR, CALL) \
+  { CALL, STR, (sizeof (STR) - 1) }
+
+static char *
+svp64_decode_m (char *str, struct svp64_ctx *svp64)
+{
+  char *iter;
+  bool cr;
+  unsigned int pmmode;
+  unsigned int pmask;
+
+  str += (sizeof ("m=") - 1);
+  iter = svp64_decode_predicate (str, &cr, &pmask);
+  if (!iter)
+    svp64_raise (_("unrecognized mode: `%s'"), str);
+
+  pmmode = (cr ? 1 : 0);
+  svp64->pmmode = pmmode;
+  svp64->pmask = pmask;
+  svp64->smmode = pmmode;
+  svp64->smask = pmask;
+  svp64->mmode = pmmode;
+  svp64->mask_m_specified = 1;
+
+  return iter;
+}
+
+static char *
+svp64_decode_dm (char *str, struct svp64_ctx *svp64)
+{
+  char *iter;
+  bool cr;
+  unsigned int pmmode;
+  unsigned int pmask;
+
+  str += (sizeof ("dm=") - 1);
+  iter = svp64_decode_predicate (str, &cr, &pmask);
+  if (!iter)
+    svp64_raise (_("unrecognized mode: `%s'"), str);
+
+  pmmode = (cr ? 1 : 0);
+  svp64->pmmode = pmmode;
+  svp64->pmask = pmask;
+  svp64->mmode = pmmode;
+  svp64->has_pmask = 1;
+
+  return iter;
+}
+
+static char *
+svp64_decode_sm (char *str, struct svp64_ctx *svp64)
+{
+  char *iter;
+  bool cr;
+  unsigned int smmode;
+  unsigned int smask;
+
+  str += (sizeof ("sm=") - 1);
+  iter = svp64_decode_predicate (str, &cr, &smask);
+  if (!iter)
+    svp64_raise (_("unrecognized mode: `%s'"), str);
+
+  smmode = (cr ? 1 : 0);
+  svp64->smmode = smmode;
+  svp64->smask = smask;
+  svp64->mmode = smmode;
+  svp64->has_smask = 1;
+
+  return iter;
+}
+
+static char *
+svp64_decode_mode (char *str, struct svp64_ctx *svp64)
+{
+  size_t i;
+  static const struct svp64_decoder table[] = {
+    SVP64_DECODER ("m="  , svp64_decode_m),
+    SVP64_DECODER ("dm=" , svp64_decode_dm),
+    SVP64_DECODER ("sm=" , svp64_decode_sm),
+  };
+
+  for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
+    {
+      const struct svp64_decoder *entry = &table[i];
+
+      if (strncmp (str, entry->str, entry->len) == 0)
+        return entry->call (str, svp64);
+    }
+
+  return NULL;
+}
+
 static void
 svp64_decode (char *str, struct svp64_ctx *svp64)
 {
   char *opc;
+  char *iter;
 
   str += (sizeof ("sv.") - 1);
   if (! ISALPHA (*str))
@@ -77,6 +246,9 @@ svp64_decode (char *str, struct svp64_ctx *svp64)
   if (*str != '\0')
     *str++ = '\0';
 
+  for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter)
+    ;
+
   svp64->desc = (const struct svp64_desc *) str_hash_find (svp64_hash, opc);
   if (!svp64->desc)
     svp64_raise (_("unrecognized opcode: `%s'"), str);