ppc/svp64: determine instruction type
authorDmitry Selyutin <ghostmansd@gmail.com>
Mon, 25 Jul 2022 19:21:38 +0000 (22:21 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Fri, 23 Sep 2022 17:11:54 +0000 (20:11 +0300)
gas/config/tc-ppc-svp64.c

index f0427976c24e40b24e42e79c7df87ee76df69c5e..7b43a37c1383484df47c8ad11a47ea82b003cfb0 100644 (file)
@@ -46,11 +46,19 @@ struct svp64_ctx {
   unsigned int rg : 1;
   unsigned int crm : 1;
   unsigned int svm : 1;
+  unsigned int type : 2;
 };
 
 #define SVP64_RC1_ACTIVE (1U << 3U)
 #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U))
 
+enum svp64_type {
+  SVP64_TYPE_NONE,
+  SVP64_TYPE_LD,
+  SVP64_TYPE_ST,
+  SVP64_TYPE_BC,
+};
+
 static jmp_buf svp64_exception;
 
 #define svp64_raise(...)                \
@@ -565,10 +573,151 @@ svp64_decode_mode (char *str, struct svp64_ctx *svp64)
   return NULL;
 }
 
+struct svp64_str_map {
+  const char *str;
+  size_t len;
+};
+#define SVP64_STR_MAP(STR) \
+  { STR, (sizeof (STR) - 1) }
+
+static bool
+svp64_str_map_cmp(const char *str, size_t len,
+    const struct svp64_str_map *map, size_t cnt)
+{
+  size_t i;
+
+  for (i = 0; i < cnt; ++i) {
+    const struct svp64_str_map *entry = &map[i];
+
+    if ((entry->len == len) && (memcmp(entry->str, str, len) == 0))
+      return true;
+  }
+
+  return false;
+}
+#define SVP64_STR_MAP_CMP(STR, LEN, MAP) \
+  svp64_str_map_cmp(STR, LEN, MAP, (sizeof (MAP) / sizeof (*MAP)))
+
+static bool
+svp64_is_ld(const char *str, size_t len)
+{
+  static const struct svp64_str_map table[] = {
+    /* load byte */
+    SVP64_STR_MAP ("lbarx"),
+    SVP64_STR_MAP ("lbz"),
+    SVP64_STR_MAP ("lbzu"),
+    SVP64_STR_MAP ("lbzux"),
+    SVP64_STR_MAP ("lbzx"),
+    /* load double */
+    SVP64_STR_MAP ("ld"),
+    SVP64_STR_MAP ("ldarx"),
+    SVP64_STR_MAP ("ldbrx"),
+    SVP64_STR_MAP ("ldu"),
+    SVP64_STR_MAP ("ldux"),
+    SVP64_STR_MAP ("ldx"),
+    /* FP load single */
+    SVP64_STR_MAP ("lfs"),
+    SVP64_STR_MAP ("lfsx"),
+    SVP64_STR_MAP ("lfsu"),
+    SVP64_STR_MAP ("lfsux"),
+    /* FP load double */
+    SVP64_STR_MAP ("lfd"),
+    SVP64_STR_MAP ("lfdx"),
+    SVP64_STR_MAP ("lfdu"),
+    SVP64_STR_MAP ("lfdux"),
+    SVP64_STR_MAP ("lfiwzx"),
+    SVP64_STR_MAP ("lfiwax"),
+    /* load half */
+    SVP64_STR_MAP ("lha"),
+    SVP64_STR_MAP ("lharx"),
+    SVP64_STR_MAP ("lhau"),
+    SVP64_STR_MAP ("lhaux"),
+    SVP64_STR_MAP ("lhax"),
+    SVP64_STR_MAP ("lhbrx"),
+    SVP64_STR_MAP ("lhz"),
+    SVP64_STR_MAP ("lhzu"),
+    SVP64_STR_MAP ("lhzux"),
+    SVP64_STR_MAP ("lhzx"),
+    /* load word */
+    SVP64_STR_MAP ("lwa"),
+    SVP64_STR_MAP ("lwarx"),
+    SVP64_STR_MAP ("lwaux"),
+    SVP64_STR_MAP ("lwax"),
+    SVP64_STR_MAP ("lwbrx"),
+    SVP64_STR_MAP ("lwz"),
+    SVP64_STR_MAP ("lwzcix"),
+    SVP64_STR_MAP ("lwzu"),
+    SVP64_STR_MAP ("lwzux"),
+    SVP64_STR_MAP ("lwzx"),
+  };
+
+  return SVP64_STR_MAP_CMP(str, len, table);
+}
+
+static bool
+svp64_is_st(const char *str, size_t len)
+{
+  static const struct svp64_str_map table[] = {
+    /* store byte */
+    SVP64_STR_MAP ("stb"),
+    SVP64_STR_MAP ("stbcix"),
+    SVP64_STR_MAP ("stbcx"),
+    SVP64_STR_MAP ("stbu"),
+    SVP64_STR_MAP ("stbux"),
+    SVP64_STR_MAP ("stbx"),
+    /* store double */
+    SVP64_STR_MAP ("std"),
+    SVP64_STR_MAP ("stdbrx"),
+    SVP64_STR_MAP ("stdcx"),
+    SVP64_STR_MAP ("stdu"),
+    SVP64_STR_MAP ("stdux"),
+    SVP64_STR_MAP ("stdx"),
+    /* FP store single */
+    SVP64_STR_MAP ("stfs"),
+    SVP64_STR_MAP ("stfsx"),
+    SVP64_STR_MAP ("stfsu"),
+    SVP64_STR_MAP ("stfux"),
+    /* FP store double */
+    SVP64_STR_MAP ("stfd"),
+    SVP64_STR_MAP ("stfdx"),
+    SVP64_STR_MAP ("stfdu"),
+    SVP64_STR_MAP ("stfdux"),
+    SVP64_STR_MAP ("stfiwx"),
+    /* store half */
+    SVP64_STR_MAP ("sth"),
+    SVP64_STR_MAP ("sthbrx"),
+    SVP64_STR_MAP ("sthcx"),
+    SVP64_STR_MAP ("sthu"),
+    SVP64_STR_MAP ("sthux"),
+    SVP64_STR_MAP ("sthx"),
+    /* store word */
+    SVP64_STR_MAP ("stw"),
+    SVP64_STR_MAP ("stwbrx"),
+    SVP64_STR_MAP ("stwcx"),
+    SVP64_STR_MAP ("stwu"),
+    SVP64_STR_MAP ("stwux"),
+    SVP64_STR_MAP ("stwx"),
+  };
+
+  return SVP64_STR_MAP_CMP(str, len, table);
+}
+
+static bool
+svp64_is_bc(const char *str, size_t len)
+{
+  static const struct svp64_str_map table[] = {
+    SVP64_STR_MAP ("bc"),
+    SVP64_STR_MAP ("bclr"),
+  };
+
+  return SVP64_STR_MAP_CMP(str, len, table);
+}
+
 static void
 svp64_decode (char *str, struct svp64_ctx *svp64)
 {
   char *opc;
+  size_t opclen;
   char *iter;
 
   str += (sizeof ("sv.") - 1);
@@ -578,9 +727,17 @@ svp64_decode (char *str, struct svp64_ctx *svp64)
   opc = str;
   for (; ! ISSPACE (*str) && *str != SVP64_SEP && *str != '\0'; ++str)
     ;
+  opclen = (str - opc);
   if (*str != '\0')
     *str++ = '\0';
 
+  if (svp64_is_ld (opc, opclen))
+    svp64->type = SVP64_TYPE_LD;
+  else if (svp64_is_st (opc, opclen))
+    svp64->type = SVP64_TYPE_ST;
+  else if (svp64_is_bc (opc, opclen))
+    svp64->type = SVP64_TYPE_BC;
+
   for (; (iter = svp64_decode_mode (str, svp64)) != NULL; str = iter)
     ;