ppc/svp64: allow predicate macro expansion
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:47:42 +0000 (19:47 +0300)
gas/config/tc-ppc-svp64.c
gas/config/tc-ppc.c
gas/config/tc-ppc.h

index 8e7bd09a39bb523a9cab95b7482cfbc1d33cd64d..4e3a12918cb6eb64f5e85e5d5893dd66feaa58be 100644 (file)
@@ -61,6 +61,33 @@ struct svp64_ctx {
 #define SVP64_RC1_ACTIVE (1U << 3U)
 #define SVP64_RC1_INVERT (SVP64_RC1_ACTIVE | (1U << 4U))
 
+enum svp64_predicate {
+  /* Integer */
+  SVP64_PREDICATE_1BIT_R3,
+  SVP64_PREDICATE_R3,
+  SVP64_PREDICATE_R3_INV,
+  SVP64_PREDICATE_R10,
+  SVP64_PREDICATE_R10_INV,
+  SVP64_PREDICATE_R30,
+  SVP64_PREDICATE_R30_INV,
+  /* CR */
+  SVP64_PREDICATE_LT,
+  SVP64_PREDICATE_NL,
+  SVP64_PREDICATE_GE = SVP64_PREDICATE_NL,
+  SVP64_PREDICATE_GT,
+  SVP64_PREDICATE_NG,
+  SVP64_PREDICATE_LE = SVP64_PREDICATE_NG,
+  SVP64_PREDICATE_EQ,
+  SVP64_PREDICATE_NE,
+  SVP64_PREDICATE_SO,
+  SVP64_PREDICATE_UN = SVP64_PREDICATE_SO,
+  SVP64_PREDICATE_NS,
+  SVP64_PREDICATE_NU = SVP64_PREDICATE_NS,
+  /* RC1 */
+  SVP64_PREDICATE_RC1,
+  SVP64_PREDICATE_RC1_INV,
+};
+
 static void
 svp64_operand (expressionS *exp)
 {
@@ -99,16 +126,10 @@ svp64_operand (expressionS *exp)
     *origin = '*';
 }
 
-static void
-svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode)
-{
-  ppc_parse_name_common (name, exp, mode, svp64_regs, svp64_num_regs);
-}
-
 static bool
 svp64_special_expr (expressionS *exp)
 {
-  return (exp->X_op == O_vector);
+  return ((exp->X_op == O_vector) || (exp->X_op == O_predicate));
 }
 
 static jmp_buf svp64_exception;
@@ -164,7 +185,6 @@ svp64_expression (char *str, expressionS *exp)
     *str++ = '\0';
   str_tail = str;
   old_sep = *str;
-  *str = '\0';
   str = str_head;
   input_line_pointer = str;
 
@@ -176,49 +196,37 @@ svp64_expression (char *str, expressionS *exp)
   return ((exp->X_op == O_absent) ? str_head : str_tail);
 }
 
-struct svp64_predicate_map {
+struct svp64_predicate_cr_map {
   const char *str;
   unsigned int len : 3;
-  unsigned int cr : 1;
-  unsigned int mask : 3 + 2; /* 3-bit plus RC1 */
+  unsigned int id : 5;
 };
-#define SVP64_PREDICATE_MAP(STR, MODE, MASK) \
-  { STR, (sizeof (STR) - 1), MODE, MASK }
+#define SVP64_PREDICATE_CR_MAP(STR, ID) \
+  { STR, (sizeof (STR) - 1), ID }
 
-static char *
-svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
+static bool
+svp64_parse_predicate_cr (const char *name, expressionS *exp)
 {
   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 */
-    /* RC1 */
-    SVP64_PREDICATE_MAP ("RC1"  , 0, SVP64_RC1_ACTIVE),
-    SVP64_PREDICATE_MAP ("~RC1" , 0, SVP64_RC1_INVERT),
+  const char *str = name;
+  static const struct svp64_predicate_cr_map table[] = {
+    SVP64_PREDICATE_CR_MAP ("lt", SVP64_PREDICATE_LT),
+    SVP64_PREDICATE_CR_MAP ("nl", SVP64_PREDICATE_NL),
+    SVP64_PREDICATE_CR_MAP ("ge", SVP64_PREDICATE_GE),
+    SVP64_PREDICATE_CR_MAP ("gt", SVP64_PREDICATE_GT),
+    SVP64_PREDICATE_CR_MAP ("ng", SVP64_PREDICATE_NG),
+    SVP64_PREDICATE_CR_MAP ("le", SVP64_PREDICATE_LE),
+    SVP64_PREDICATE_CR_MAP ("eq", SVP64_PREDICATE_EQ),
+    SVP64_PREDICATE_CR_MAP ("ne", SVP64_PREDICATE_NE),
+    SVP64_PREDICATE_CR_MAP ("so", SVP64_PREDICATE_SO),
+    SVP64_PREDICATE_CR_MAP ("un", SVP64_PREDICATE_UN),
+    SVP64_PREDICATE_CR_MAP ("ns", SVP64_PREDICATE_NS),
+    SVP64_PREDICATE_CR_MAP ("nu", SVP64_PREDICATE_NU),
   };
 
   for (i = 0; i < sizeof (table) / sizeof (table[0]); ++i)
     {
-      const struct svp64_predicate_map *entry = &table[i];
+      const struct svp64_predicate_cr_map *entry = &table[i];
 
       if (strncmp (str, entry->str, entry->len) != 0)
         continue;
@@ -230,10 +238,112 @@ svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
           continue;
         }
 
-      *mask = entry->mask;
-      *cr = entry->cr;
+      exp->X_op = O_predicate;
+      exp->X_add_number = entry->id;
+
+      return true;
+    }
+
+  return false;
+}
+
+static bool
+svp64_parse_predicate_RC1 (const char *name, expressionS *exp)
+{
+  if (strcmp (name, "RC1") == 0)
+    {
+      exp->X_op = O_predicate;
+      exp->X_add_number = SVP64_PREDICATE_RC1;
+      return true;
+    }
+  else
+    return false;
+}
+
+static void
+svp64_parse_name (const char *name, expressionS *exp, enum expr_mode mode)
+{
+  exp->X_op = O_absent;
+  exp->X_op_symbol = NULL;
+  exp->X_add_symbol = NULL;
+
+  if ((svp64_parse_predicate_cr (name, exp)
+      || svp64_parse_predicate_RC1 (name, exp)) == 0)
+    ppc_parse_name_common (name, exp, mode, svp64_regs, svp64_num_regs);
+}
+
+static char *
+svp64_decode_predicate (char *str, bool *cr, unsigned int *mask)
+{
+  char *origin;
+  expressionS exp;
+
+  origin = str;
+  str = svp64_expression (str, &exp);
+  if (str != origin)
+    {
+      expressionS *sym_exp = NULL;
+      static const struct {
+        unsigned int cr : 1;
+        unsigned int mask : 3 + 2; /* 3-bit plus RC1 */
+       } table[] = {
+        /* SVP64_PREDICATE_1BIT_R3 */ {0, 1},
+        /* SVP64_PREDICATE_R3 */      {0, 2},
+        /* SVP64_PREDICATE_R3_INV */  {0, 3},
+        /* SVP64_PREDICATE_R10 */     {0, 4},
+        /* SVP64_PREDICATE_R10_INV */ {0, 5},
+        /* SVP64_PREDICATE_R30 */     {0, 6},
+        /* SVP64_PREDICATE_R30_INV */ {0, 7},
+        /* SVP64_PREDICATE_LT */      {1, 0},
+        /* SVP64_PREDICATE_NL */      {1, 1},
+        /* SVP64_PREDICATE_GT */      {1, 2},
+        /* SVP64_PREDICATE_NG */      {1, 3},
+        /* SVP64_PREDICATE_EQ */      {1, 4},
+        /* SVP64_PREDICATE_NE */      {1, 5},
+        /* SVP64_PREDICATE_SO */      {1, 6},
+        /* SVP64_PREDICATE_NS */      {1, 7},
+        /* {SVP64_PREDICATE_RC1*/     {0, SVP64_RC1_ACTIVE},
+        /* SVP64_PREDICATE_RC1_INV */ {0, SVP64_RC1_INVERT},
+      };
+      enum svp64_predicate predicate;
+
+      if (exp.X_add_symbol)
+        sym_exp = symbol_get_value_expression (exp.X_add_symbol);
+
+      if ((exp.X_op == O_register) &&
+            ((exp.X_add_number == 3)
+            || (exp.X_add_number == 10)
+            || (exp.X_add_number == 30)))
+        {
+          exp.X_op = O_predicate;
+          if (exp.X_add_number == 3)
+            exp.X_add_number = SVP64_PREDICATE_R3;
+          else if (exp.X_add_number == 10)
+            exp.X_add_number = SVP64_PREDICATE_R10;
+          else if (exp.X_add_number == 30)
+            exp.X_add_number = SVP64_PREDICATE_R30;
+        }
+      else if ((exp.X_op == O_bit_not) && (sym_exp != NULL))
+        {
+          if (sym_exp->X_op == O_register)
+            {
+              if (sym_exp->X_add_number == 3)
+                exp.X_add_number = SVP64_PREDICATE_R3_INV;
+              else if (sym_exp->X_add_number == 10)
+                exp.X_add_number = SVP64_PREDICATE_R10_INV;
+              else if (sym_exp->X_add_number == 30)
+                exp.X_add_number = SVP64_PREDICATE_R30_INV;
+            }
+          else if ((sym_exp->X_op == O_predicate)
+                && (sym_exp->X_add_number == SVP64_PREDICATE_RC1))
+            exp.X_add_number = SVP64_PREDICATE_RC1_INV;
+        }
+      else if (exp.X_op != O_predicate)
+        return NULL;
 
-      *str++ = '\0';
+      predicate = (enum svp64_predicate)exp.X_add_number;
+      *cr = (table[predicate].cr ? true : false);
+      *mask = table[predicate].mask;
 
       return str;
     }
index 05ddb9671e8b56115c2d4f9dcc5ae4e36a16ded3..1d3d12571f015cf3cd7f0d5fc44b64edd22576fe 100644 (file)
@@ -971,8 +971,11 @@ ppc_resolve_symbol (symbolS *sym ATTRIBUTE_UNUSED,
     case O_vector:
       *seg = reg_section;
       break;
+    case O_predicate:
+      *seg = absolute_section;
+      break;
     default:
-      abort ();
+      abort();
     }
 
   return true;
@@ -1002,13 +1005,14 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
     }
 
   /* Accept the above plus <cr bit>, and <cr bit> plus the above.  */
-  if (right->X_op == O_register
-      && left->X_op == O_register
+  if ((right->X_op == O_register || right->X_op == O_predicate)
+      && (left->X_op == O_register || left->X_op == O_predicate)
+      && ((left->X_op == O_predicate) != (right->X_op == O_predicate))
       && op == O_add
-      && ((right->X_md == PPC_OPERAND_CR_BIT
+      && (((right->X_md == PPC_OPERAND_CR_BIT || right->X_op == O_predicate)
           && left->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT))
          || (right->X_md == (PPC_OPERAND_CR_REG | PPC_OPERAND_CR_BIT)
-             && left->X_md == PPC_OPERAND_CR_BIT)))
+             && (left->X_md == PPC_OPERAND_CR_BIT || left->X_op == O_predicate))))
     {
       left->X_md = PPC_OPERAND_CR_BIT;
       right->X_op = O_constant;
@@ -1025,6 +1029,16 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
     {
       if (op == O_add && left->X_op == O_constant)
        left->X_md = right->X_md;
+      else if ((ppc_cpu & PPC_OPCODE_SVP64)
+         && (op == O_left_shift)
+         && (left->X_op == O_constant)
+         && (left->X_add_number == 1)
+         && (right->X_add_number == 3)) /* 1<<r3 */
+       {
+         left->X_op = O_predicate;
+         left->X_add_number = SVP64_PREDICATE_1BIT_R3;
+         return 1;
+       }
       else
        as_warn (_("invalid register expression"));
     }
index fce6c98e0bae0e3fe95b2c129daa7a053164b850..4587802091418b5503c5b8ef6b02009036afb598 100644 (file)
@@ -368,6 +368,9 @@ extern int tc_ppc_regname_to_dw2regnum (char *);
  */
 #define O_vector O_md1
 
+/* Operand is a predicate to s/dm/sm/ff/pr modes. */
+#define O_predicate O_md2
+
 extern bool ppc_resolve_symbol (symbolS *sym, valueT *val, segT *seg);
 #define md_resolve_symbol ppc_resolve_symbol