ppc: introduce non-zero operand flag
authorDmitry Selyutin <ghostmansd@gmail.com>
Thu, 23 Jun 2022 16:10:54 +0000 (19:10 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Thu, 23 Jun 2022 20:04:33 +0000 (23:04 +0300)
svstep and svshape instructions subtract 1 before encoding some of the
operands. Obviously zero is not supported for these operands. Whilst
PPC_OPERAND_PLUS1 fits perfectly to mark that maximal value should be
incremented, there is no flag which marks the fact that zero values are
not allowed. This patch adds a new flag, PPC_OPERAND_NONZERO, for this
purpose.

gas/config/tc-ppc.c
include/opcode/ppc.h
opcodes/ppc-dis.c

index 76bdfb2e351a1e1bd8fcf9f1aa1d093d553d6d98..c048721ed0529df889299244d00fa32d3b0dc311 100644 (file)
@@ -1643,10 +1643,16 @@ ppc_setup_opcodes (void)
         all the 1's in the mask are contiguous.  */
       for (i = 0; i < num_powerpc_operands; ++i)
        {
+
          uint64_t mask = powerpc_operands[i].bitm;
+          unsigned long flags = powerpc_operands[i].flags;
          uint64_t right_bit;
          unsigned int j;
 
+         if ((flags & (PPC_OPERAND_PLUS1 | PPC_OPERAND_NONZERO)) ==
+               (PPC_OPERAND_PLUS1 | PPC_OPERAND_NONZERO))
+           as_bad ("mutually exclusive operand flags");
+
          right_bit = mask & -mask;
          mask += right_bit;
          right_bit = mask & -mask;
@@ -1968,6 +1974,11 @@ ppc_insert_operand (uint64_t insn,
       max = (max >> 1) & -right;
       min = ~max & -right;
     }
+  else if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
+    {
+      ++min;
+      ++max;
+    }
 
   if ((operand->flags & PPC_OPERAND_PLUS1) != 0)
     max++;
@@ -2018,10 +2029,15 @@ ppc_insert_operand (uint64_t insn,
       if (errmsg != (const char *) NULL)
        as_bad_where (file, line, "%s", errmsg);
     }
-  else if (operand->shift >= 0)
-    insn |= (val & operand->bitm) << operand->shift;
   else
-    insn |= (val & operand->bitm) >> -operand->shift;
+    {
+      if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
+       --val;
+      if (operand->shift >= 0)
+       insn |= (val & operand->bitm) << operand->shift;
+      else
+       insn |= (val & operand->bitm) >> -operand->shift;
+    }
 
   return insn;
 }
index d5752a42e67b9119fcdc2bd16bd5f06e3a9bee26..df06671db49b9d90df5edd31b134328e5933ae6d 100644 (file)
@@ -463,6 +463,13 @@ extern const unsigned int num_powerpc_operands;
 #define PPC_OPERAND_FCR (0x1000000)
 #define PPC_OPERAND_UDI (0x2000000)
 
+/*
+ * Valid range of operand is 1..n rather than 0..n-1.
+ * Before encoding, the operand value is decremented.
+ * After decoding. the operand value is incremented.
+ */
+#define PPC_OPERAND_NONZERO 0x4000000
+
 extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
 
 static inline int64_t
index f61e6518f14c0106a93059057693f88dbddb70bb..d5b23c8a75c8db19a8c51da36d4c3061bb20c103 100644 (file)
@@ -545,6 +545,9 @@ operand_value_powerpc (const struct powerpc_operand *operand,
        }
     }
 
+  if ((operand->flags & PPC_OPERAND_NONZERO) != 0)
+    ++value;
+
   return value;
 }