ppc: extend opindex to 16 bits
authorDmitry Selyutin <ghostmansd@gmail.com>
Thu, 12 May 2022 07:32:11 +0000 (10:32 +0300)
committerAlan Modra <amodra@gmail.com>
Wed, 25 May 2022 02:43:44 +0000 (12:13 +0930)
With the upcoming SVP64 extension[0] to PowerPC architecture, it became
evident that PowerPC operand indices no longer fit 8 bits. This patch
switches the underlying type to uint16_t, also introducing a special
typedef so that any future extension goes even smoother.

[0] https://libre-soc.org

include/
* opcode/ppc.h (ppc_opindex_t): New typedef.
(struct powerpc_opcode): Use it.
(PPC_OPINDEX_MAX): Define.
gas/
* write.h (struct fix): Increase size of fx_pcrel_adjust.
Reorganise.
* config/tc-ppc.c (insn_validate): Use ppc_opindex_t for operands.
(md_assemble): Likewise.
(md_apply_fix): Likewise.  Mask fx_pcrel_adjust with PPC_OPINDEX_MAX.
(ppc_setup_opcodes): Adjust opcode index assertion.
opcodes/
* ppc-dis.c (skip_optional_operands): Use ppc_opindex_t for
operand pointer.
(lookup_powerpc, lookup_prefix, lookup_vle, lookup_spe2): Likewise.
(print_insn_powerpc): Likewise.

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

index 72128af501bbe572456433e93fc293172943852e..4d789fd16a9a4af8ce4b4894c235273da09d67ff 100644 (file)
@@ -1553,7 +1553,7 @@ ppc_target_format (void)
 static bool
 insn_validate (const struct powerpc_opcode *op)
 {
-  const unsigned char *o;
+  const ppc_opindex_t *o;
   uint64_t omask = op->mask;
 
   /* The mask had better not trim off opcode bits.  */
@@ -1634,8 +1634,8 @@ ppc_setup_opcodes (void)
       unsigned int i;
 
       /* An index into powerpc_operands is stored in struct fix
-        fx_pcrel_adjust which is 8 bits wide.  */
-      gas_assert (num_powerpc_operands < 256);
+        fx_pcrel_adjust which is a 16 bit field.  */
+      gas_assert (num_powerpc_operands <= PPC_OPINDEX_MAX + 1);
 
       /* Check operand masks.  Code here and in the disassembler assumes
         all the 1's in the mask are contiguous.  */
@@ -3251,7 +3251,7 @@ md_assemble (char *str)
   char *s;
   const struct powerpc_opcode *opcode;
   uint64_t insn;
-  const unsigned char *opindex_ptr;
+  const ppc_opindex_t *opindex_ptr;
   int need_paren;
   int next_opindex;
   struct ppc_fixup fixups[MAX_INSN_FIXUPS];
@@ -3348,7 +3348,7 @@ md_assemble (char *str)
        {
          if (num_optional_operands == 0)
            {
-             const unsigned char *optr;
+             const ppc_opindex_t *optr;
              int total = 0;
              int provided = 0;
              int omitted;
@@ -7011,7 +7011,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
   if (fixP->fx_pcrel_adjust != 0)
     {
       /* This is a fixup on an instruction.  */
-      int opindex = fixP->fx_pcrel_adjust & 0xff;
+      ppc_opindex_t opindex = fixP->fx_pcrel_adjust & PPC_OPINDEX_MAX;
 
       operand = &powerpc_operands[opindex];
 #ifdef OBJ_XCOFF
index 501bdd828fc96e423a689141ab425743f484da3c..3e31342cfc8fbcd90af73d12c141f767354484e8 100644 (file)
@@ -52,6 +52,16 @@ struct fix
   /* These small fields are grouped together for compactness of
      this structure, and efficiency of access on some architectures.  */
 
+  /* pc-relative offset adjust (only used by some CPU specific code).
+     A 4-bit field would be sufficient for most uses, except for ppc
+     which pokes an operand table index here.  Bits may be stolen
+     from here should that be necessary, provided PPC_OPINDEX_MAX is
+     adjusted suitably.  */
+  int fx_pcrel_adjust : 16;
+
+  /* How many bytes are involved? */
+  unsigned fx_size : 8;
+
   /* Is this a pc-relative relocation?  */
   unsigned fx_pcrel : 1;
 
@@ -73,13 +83,7 @@ struct fix
   unsigned fx_tcbit2 : 1;
 
   /* Spare bits.  */
-  unsigned fx_unused : 10;
-
-  /* pc-relative offset adjust (only used by some CPU specific code) */
-  int fx_pcrel_adjust : 8;
-
-  /* How many bytes are involved? */
-  unsigned fx_size : 8;
+  unsigned fx_unused : 2;
 
   bfd_reloc_code_real_type fx_r_type;
 
index a9c2529831108c50fd570ad7b0a45937eaa470f1..7bc6ee216e189f505573eeec451ad4591c440dc7 100644 (file)
@@ -29,6 +29,12 @@ extern "C" {
 #endif
 
 typedef uint64_t ppc_cpu_t;
+typedef uint16_t ppc_opindex_t;
+
+/* Smaller of ppc_opindex_t and fx_pcrel_adjust maximum.  Note that
+   values extracted from fx_pcrel_adjust are masked with this constant,
+   effectively making the field unsigned.  */
+#define PPC_OPINDEX_MAX 0xffff
 
 /* The opcode table is an array of struct powerpc_opcode.  */
 
@@ -60,7 +66,7 @@ struct powerpc_opcode
   /* An array of operand codes.  Each code is an index into the
      operand table.  They appear in the order which the operands must
      appear in assembly code, and are terminated by a zero.  */
-  unsigned char operands[8];
+  ppc_opindex_t operands[8];
 };
 
 /* The table itself is sorted by major opcode number, and is otherwise
index 38ddeca26231b81ef12c73c6096a6fa60a47f6ed..45e8faeef5e55738546c5233032765072f0ce2b3 100644 (file)
@@ -546,7 +546,7 @@ operand_value_powerpc (const struct powerpc_operand *operand,
 /* Determine whether the optional operand(s) should be printed.  */
 
 static bool
-skip_optional_operands (const unsigned char *opindex,
+skip_optional_operands (const ppc_opindex_t *opindex,
                        uint64_t insn, ppc_cpu_t dialect, bool *is_pcrel)
 {
   const struct powerpc_operand *operand;
@@ -592,7 +592,7 @@ lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
        opcode < opcode_end;
        ++opcode)
     {
-      const unsigned char *opindex;
+      const ppc_opindex_t *opindex;
       const struct powerpc_operand *operand;
       int invalid;
 
@@ -637,7 +637,7 @@ lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
        opcode < opcode_end;
        ++opcode)
     {
-      const unsigned char *opindex;
+      const ppc_opindex_t *opindex;
       const struct powerpc_operand *operand;
       int invalid;
 
@@ -691,7 +691,7 @@ lookup_vle (uint64_t insn, ppc_cpu_t dialect)
       uint64_t table_mask = opcode->mask;
       bool table_op_is_short = PPC_OP_SE_VLE(table_mask);
       uint64_t insn2;
-      const unsigned char *opindex;
+      const ppc_opindex_t *opindex;
       const struct powerpc_operand *operand;
       int invalid;
 
@@ -746,7 +746,7 @@ lookup_spe2 (uint64_t insn, ppc_cpu_t dialect)
       uint64_t table_opcd = opcode->opcode;
       uint64_t table_mask = opcode->mask;
       uint64_t insn2;
-      const unsigned char *opindex;
+      const ppc_opindex_t *opindex;
       const struct powerpc_operand *operand;
       int invalid;
 
@@ -925,7 +925,7 @@ print_insn_powerpc (bfd_vma memaddr,
 
   if (opcode != NULL)
     {
-      const unsigned char *opindex;
+      const ppc_opindex_t *opindex;
       const struct powerpc_operand *operand;
       enum {
        need_comma = 0,