+2021-04-12  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (insn_validate): Use uint64_t for operand values.
+       (md_assemble): Likewise.  Handle bignum operands.
+       (ppc_elf_suffix): Handle O_big.  Remove unnecessary input_line_pointer
+       check.
+       * expr.c: Delete unnecessary forward declarations.
+       (generic_bignum_to_int32): Return uint32_t.
+       (generic_bignum_to_int64): Return uint64_t.  Compile always.
+       (operand): Twiddle X_extrabit for unary '~'.  Set X_unsigned and
+       clear X_extrabit for unary '!'.
+       * expr.h (generic_bignum_to_int32): Declare.
+       (generic_bignum_to_int64): Declare.
+       * testsuite/gas/ppc/prefix-pcrel.s,
+       * testsuite/gas/ppc/prefix-pcrel.d: Add more instructions.
+
+2021-04-09  Tejas Belagod  <tejas.belagod@arm.com>
+
 2021-04-12  Nelson Chu  <nelson.chu@sifive.com>
 
        * testsuite/gas/riscv/march-fail-order-x-std.d: Renamed from
 
 2021-04-09  Tejas Belagod  <tejas.belagod@arm.com>
 
-       * config/tc-aarch64.c (warn_unpredictable_ldst): Clean-up diagnostic messages
-       for LD/ST Exclusive instructions.
+       * config/tc-aarch64.c (warn_unpredictable_ldst): Clean-up
+       diagnostic messages for LD/ST Exclusive instructions.
        * testsuite/gas/aarch64/diagnostic.s: Add a diagnostic test for STLXP.
-       * testsuite/gas/aarch64/diagnostic.l: Fix-up test after message clean-up.
+       * testsuite/gas/aarch64/diagnostic.l: Fix-up test after message
+       clean-up.
 
 2021-04-09  Alan Modra  <amodra@gmail.com>
 
        well as Intel syntax tests.
        * testsuite/gas/i386/invlpgb.d, testsuite/gas/i386/snp.d: Adjust
        expectations.
-       * testsuite/gas/i386/invlpgb64.d, testsuite/gas/i386/snp64.d: 
+       * testsuite/gas/i386/invlpgb64.d, testsuite/gas/i386/snp64.d:
        Likewise. Drop passing --def-sym to as.
 
 2021-03-25  Jan Beulich  <jbeulich@suse.com>
 2021-02-12  Nick Clifton  <nickc@redhat.com>
 
        * testsuite/gas/mach-o/sections-1.d: Stop automatic debug link
-        following.
+       following.
        * testsuite/gas/xgate/insns-dwarf2.d: Likewise.
 
 2021-02-12  Alan Modra  <amodra@gmail.com>
 
          if (operand->shift == (int) PPC_OPSHIFT_INV)
            {
              const char *errmsg;
-             int64_t val;
+             uint64_t val;
 
              errmsg = NULL;
              val = -1;
       {
        int reloc = ptr->reloc;
 
-       if (!ppc_obj64 && exp_p->X_add_number != 0)
+       if (!ppc_obj64 && (exp_p->X_op == O_big || exp_p->X_add_number != 0))
          {
            switch (reloc)
              {
 
            input_line_pointer = str;
            expression (&new_exp);
-           if (new_exp.X_op == O_constant)
+           if (new_exp.X_op == O_constant && exp_p->X_op != O_big)
              {
                exp_p->X_add_number += new_exp.X_add_number;
                str = input_line_pointer;
              }
-
-           if (&input_line_pointer != str_p)
-             input_line_pointer = orig_line;
+           input_line_pointer = orig_line;
          }
        *str_p = str;
 
            }
          if (--num_optional_provided < 0)
            {
-             int64_t val = ppc_optional_operand_value (operand, insn, ppc_cpu,
-                                                       num_optional_provided);
+             uint64_t val = ppc_optional_operand_value (operand, insn, ppc_cpu,
+                                                        num_optional_provided);
              if (operand->insert)
                {
                  insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
          insn = ppc_insert_operand (insn, operand, ex.X_add_number,
                                     ppc_cpu, (char *) NULL, 0);
        }
-      else if (ex.X_op == O_constant)
+      else if (ex.X_op == O_constant
+              || (ex.X_op == O_big && ex.X_add_number > 0))
        {
+         uint64_t val;
+         if (ex.X_op == O_constant)
+           {
+             val = ex.X_add_number;
+             if (sizeof (ex.X_add_number) < sizeof (val)
+                 && (ex.X_add_number < 0) != ex.X_extrabit)
+               val = val ^ ((addressT) -1 ^ (uint64_t) -1);
+           }
+         else
+           val = generic_bignum_to_int64 ();
 #ifdef OBJ_ELF
          /* Allow @HA, @L, @H on constants.  */
-         bfd_reloc_code_real_type reloc;
          char *orig_str = str;
+         bfd_reloc_code_real_type reloc = ppc_elf_suffix (&str, &ex);
 
-         if ((reloc = ppc_elf_suffix (&str, &ex)) != BFD_RELOC_NONE)
+         if (ex.X_op == O_constant)
+           {
+             val = ex.X_add_number;
+             if (sizeof (ex.X_add_number) < sizeof (val)
+                 && (ex.X_add_number < 0) != ex.X_extrabit)
+               val = val ^ ((addressT) -1 ^ (uint64_t) -1);
+           }
+         if (reloc != BFD_RELOC_NONE)
            switch (reloc)
              {
              default:
                break;
 
              case BFD_RELOC_LO16:
-               ex.X_add_number &= 0xffff;
+               val &= 0xffff;
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_HI16:
                if (REPORT_OVERFLOW_HI && ppc_obj64)
                  {
                    /* PowerPC64 @h is tested for overflow.  */
-                   ex.X_add_number = (addressT) ex.X_add_number >> 16;
+                   val = val >> 16;
                    if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
                      {
-                       addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
-                       ex.X_add_number
-                         = ((addressT) ex.X_add_number ^ sign) - sign;
+                       uint64_t sign = (((uint64_t) -1 >> 16) + 1) >> 1;
+                       val = (val ^ sign) - sign;
                      }
                    break;
                  }
                /* Fallthru */
 
              case BFD_RELOC_PPC64_ADDR16_HIGH:
-               ex.X_add_number = PPC_HI (ex.X_add_number);
+               val = PPC_HI (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_HI16_S:
                if (REPORT_OVERFLOW_HI && ppc_obj64)
                  {
                    /* PowerPC64 @ha is tested for overflow.  */
-                   ex.X_add_number
-                     = ((addressT) ex.X_add_number + 0x8000) >> 16;
+                   val = (val + 0x8000) >> 16;
                    if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
                      {
-                       addressT sign = (((addressT) -1 >> 16) + 1) >> 1;
-                       ex.X_add_number
-                         = ((addressT) ex.X_add_number ^ sign) - sign;
+                       uint64_t sign = (((uint64_t) -1 >> 16) + 1) >> 1;
+                       val = (val ^ sign) - sign;
                      }
                    break;
                  }
                /* Fallthru */
 
              case BFD_RELOC_PPC64_ADDR16_HIGHA:
-               ex.X_add_number = PPC_HA (ex.X_add_number);
+               val = PPC_HA (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_PPC64_HIGHER:
-               ex.X_add_number = PPC_HIGHER (ex.X_add_number);
+               val = PPC_HIGHER (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_PPC64_HIGHER_S:
-               ex.X_add_number = PPC_HIGHERA (ex.X_add_number);
+               val = PPC_HIGHERA (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_PPC64_HIGHEST:
-               ex.X_add_number = PPC_HIGHEST (ex.X_add_number);
+               val = PPC_HIGHEST (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
 
              case BFD_RELOC_PPC64_HIGHEST_S:
-               ex.X_add_number = PPC_HIGHESTA (ex.X_add_number);
+               val = PPC_HIGHESTA (val);
                if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-                 ex.X_add_number = SEX16 (ex.X_add_number);
+                 val = SEX16 (val);
                break;
              }
 #endif /* OBJ_ELF */
-         insn = ppc_insert_operand (insn, operand, ex.X_add_number,
-                                    ppc_cpu, (char *) NULL, 0);
+         insn = ppc_insert_operand (insn, operand, val, ppc_cpu, NULL, 0);
        }
       else
        {
 
 
 bool literal_prefix_dollar_hex = false;
 
-static void floating_constant (expressionS * expressionP);
-static valueT generic_bignum_to_int32 (void);
-#ifdef BFD64
-static valueT generic_bignum_to_int64 (void);
-#endif
-static void integer_constant (int radix, expressionS * expressionP);
-static void mri_char_constant (expressionS *);
 static void clean_up_expression (expressionS * expressionP);
-static segT operand (expressionS *, enum expr_mode);
-static operatorT operatorf (int *);
 
 /* We keep a mapping of expression symbols to file positions, so that
    we can provide better error messages.  */
   expressionP->X_add_number = -1;
 }
 
-static valueT
+uint32_t
 generic_bignum_to_int32 (void)
 {
-  valueT number =
-    ((((valueT) generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
-     | ((valueT) generic_bignum[0] & LITTLENUM_MASK));
-  number &= 0xffffffff;
-  return number;
+  return ((((uint32_t) generic_bignum[1] & LITTLENUM_MASK)
+          << LITTLENUM_NUMBER_OF_BITS)
+         | ((uint32_t) generic_bignum[0] & LITTLENUM_MASK));
 }
 
-#ifdef BFD64
-static valueT
+uint64_t
 generic_bignum_to_int64 (void)
 {
-  valueT number =
-    ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK)
-         << LITTLENUM_NUMBER_OF_BITS)
-        | ((valueT) generic_bignum[2] & LITTLENUM_MASK))
-       << LITTLENUM_NUMBER_OF_BITS)
-       | ((valueT) generic_bignum[1] & LITTLENUM_MASK))
-      << LITTLENUM_NUMBER_OF_BITS)
-     | ((valueT) generic_bignum[0] & LITTLENUM_MASK));
-  return number;
+  return ((((((((uint64_t) generic_bignum[3] & LITTLENUM_MASK)
+              << LITTLENUM_NUMBER_OF_BITS)
+             | ((uint64_t) generic_bignum[2] & LITTLENUM_MASK))
+            << LITTLENUM_NUMBER_OF_BITS)
+           | ((uint64_t) generic_bignum[1] & LITTLENUM_MASK))
+          << LITTLENUM_NUMBER_OF_BITS)
+         | ((uint64_t) generic_bignum[0] & LITTLENUM_MASK));
 }
-#endif
 
 static void
 integer_constant (int radix, expressionS *expressionP)
                  expressionP->X_extrabit ^= 1;
              }
            else if (c == '~' || c == '"')
-             expressionP->X_add_number = ~ expressionP->X_add_number;
+             {
+               expressionP->X_add_number = ~ expressionP->X_add_number;
+               expressionP->X_extrabit ^= 1;
+             }
            else if (c == '!')
-             expressionP->X_add_number = ! expressionP->X_add_number;
+             {
+               expressionP->X_add_number = ! expressionP->X_add_number;
+               expressionP->X_unsigned = 1;
+               expressionP->X_extrabit = 0;
+             }
          }
        else if (expressionP->X_op == O_big
                 && expressionP->X_add_number <= 0
 
 
 extern symbolS *expr_build_uconstant (offsetT);
 extern symbolS *expr_build_dot (void);
+extern uint32_t generic_bignum_to_int32 (void);
+extern uint64_t generic_bignum_to_int64 (void);
 
 int resolve_expression (expressionS *);
 
 
 .*:    (df eb 00 60|60 00 eb df) 
 .*:    (04 10 00 00|00 00 10 04)       pstxv   vs63,96 # 3d8
 .*:    (df e0 00 60|60 00 e0 df) 
+.*:    (06 00 7f ff|ff 7f 00 06)       pli     r1,2147483647
+.*:    (38 20 ff ff|ff ff 20 38) 
+.*:    (06 00 80 00|00 80 00 06)       pli     r2,2147483648
+.*:    (38 40 00 00|00 00 40 38) 
+.*:    (06 00 ff ff|ff ff 00 06)       pli     r3,4294967295
+.*:    (38 60 ff ff|ff ff 60 38) 
+.*:    (06 00 00 00|00 00 00 06)       pli     r4,0
+.*:    (38 80 00 00|00 00 80 38) 
+.*:    (06 03 ff ff|ff ff 03 06)       pli     r5,-1
+.*:    (38 a0 ff ff|ff ff a0 38) 
+.*:    (06 03 80 00|00 80 03 06)       pli     r6,-2147483647
+.*:    (38 c0 00 01|01 00 c0 38) 
+.*:    (06 03 80 00|00 80 03 06)       pli     r7,-2147483648
+.*:    (38 e0 00 00|00 00 e0 38) 
+.*:    (06 03 80 00|00 80 03 06)       pli     r8,-2147483648
+.*:    (39 00 00 00|00 00 00 39) 
+.*:    (06 03 7f ff|ff 7f 03 06)       pli     r9,-2147483649
+.*:    (39 20 ff ff|ff ff 20 39) 
 #pass
 
        pstxv   13,96(0),1
        pstxv   63,96(11),0
        pstxv   63,96(0),1
+
+# test d34 values of interest when bfd_vma is 32-bit
+       pli     1,0x7fffffff
+       pli     2,0x80000000
+       pli     3,0xffffffff
+       pli     4,0
+       pli     5,-1
+       pli     6,-0x7fffffff
+       pli     7,-0x80000000
+       pli     8,~0x7fffffff
+       pli     9,~0x80000000