Update year range in copyright notice of binutils files
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index fd5cc35cd26ec47e29b22394c7f5c3d8d996d4e1..35da05c510e5f664368b2f22fa2a0616f86b425c 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
-   Copyright (C) 1994-2017 Free Software Foundation, Inc.
+   Copyright (C) 1994-2018 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
@@ -217,7 +217,7 @@ static enum {
 
 /* Warn on emitting data to code sections.  */
 int warn_476;
-unsigned long last_insn;
+uint64_t last_insn;
 segT last_seg;
 subsegT last_subseg;
 \f
@@ -974,7 +974,7 @@ ppc_optimize_expr (expressionS *left, operatorT op, expressionS *right)
   /* Accept reg +/- constant.  */
   if (left->X_op == O_register
       && !((op == O_add || op == O_subtract) && right->X_op == O_constant))
-    as_bad (_("invalid register expression"));
+    as_warn (_("invalid register expression"));
 
   /* Accept constant + reg.  */
   if (right->X_op == O_register)
@@ -982,7 +982,7 @@ 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
-       as_bad (_("invalid register expression"));
+       as_warn (_("invalid register expression"));
     }
 
   return 0;
@@ -1193,7 +1193,8 @@ md_parse_option (int c, const char *arg)
 
     case 'm':
       new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, arg);
-      if (new_cpu != 0)
+      /* "raw" is only valid for the disassembler.  */
+      if (new_cpu != 0 && (new_cpu & PPC_OPCODE_RAW) == 0)
        {
          ppc_cpu = new_cpu;
          if (strcmp (arg, "vle") == 0)
@@ -1205,6 +1206,16 @@ md_parse_option (int c, const char *arg)
            }
        }
 
+      else if (strcmp (arg, "no-vle") == 0)
+       {
+         sticky &= ~PPC_OPCODE_VLE;
+
+         new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, "booke");
+         new_cpu &= ~PPC_OPCODE_VLE;
+
+         ppc_cpu = new_cpu;
+       }
+
       else if (strcmp (arg, "regnames") == 0)
        reg_names_p = TRUE;
 
@@ -1257,6 +1268,10 @@ md_parse_option (int c, const char *arg)
          msolaris = FALSE;
          ppc_comment_chars = ppc_eabi_comment_chars;
        }
+      else if (strcmp (arg, "spe2") == 0)
+       {
+         ppc_cpu |= PPC_OPCODE_SPE2;
+       }
 #endif
       else
        {
@@ -1345,7 +1360,6 @@ PowerPC options:\n\
   fprintf (stream, _("\
 -maltivec               generate code for AltiVec\n\
 -mvsx                   generate code for Vector-Scalar (VSX) instructions\n\
--mhtm                   generate code for Hardware Transactional Memory\n\
 -me300                  generate code for PowerPC e300 family\n\
 -me500, -me500x2        generate code for Motorola e500 core complex\n\
 -me500mc,               generate code for Freescale e500mc core complex\n\
@@ -1353,6 +1367,7 @@ PowerPC options:\n\
 -me5500,                generate code for Freescale e5500 core complex\n\
 -me6500,                generate code for Freescale e6500 core complex\n\
 -mspe                   generate code for Motorola SPE instructions\n\
+-mspe2                  generate code for Freescale SPE2 instructions\n\
 -mvle                   generate code for Freescale VLE instructions\n\
 -mtitan                 generate code for AppliedMicro Titan core complex\n\
 -mregnames              Allow symbolic names for registers\n\
@@ -1482,7 +1497,7 @@ static bfd_boolean
 insn_validate (const struct powerpc_opcode *op)
 {
   const unsigned char *o;
-  unsigned long omask = op->mask;
+  uint64_t omask = op->mask;
 
   /* The mask had better not trim off opcode bits.  */
   if ((op->opcode & omask) != op->opcode)
@@ -1504,7 +1519,7 @@ insn_validate (const struct powerpc_opcode *op)
          const struct powerpc_operand *operand = &powerpc_operands[*o];
          if (operand->shift != (int) PPC_OPSHIFT_INV)
            {
-             unsigned long mask;
+             uint64_t mask;
 
              if (operand->shift >= 0)
                mask = operand->bitm << operand->shift;
@@ -1555,8 +1570,8 @@ ppc_setup_opcodes (void)
         all the 1's in the mask are contiguous.  */
       for (i = 0; i < num_powerpc_operands; ++i)
        {
-         unsigned long mask = powerpc_operands[i].bitm;
-         unsigned long right_bit;
+         uint64_t mask = powerpc_operands[i].bitm;
+         uint64_t right_bit;
          unsigned int j;
 
          right_bit = mask & -mask;
@@ -1589,10 +1604,10 @@ ppc_setup_opcodes (void)
              int new_opcode = PPC_OP (op[0].opcode);
 
 #ifdef PRINT_OPCODE_TABLE
-             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%x\tmask: 0x%x\tflags: 0x%llx\n",
+             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
                      op->name, (unsigned int) (op - powerpc_opcodes),
-                     (unsigned int) new_opcode, (unsigned int) op->opcode,
-                     (unsigned int) op->mask, (unsigned long long) op->flags);
+                     (unsigned int) new_opcode, (unsigned long long) op->opcode,
+                     (unsigned long long) op->mask, (unsigned long long) op->flags);
 #endif
 
              /* The major opcodes had better be sorted.  Code in the
@@ -1654,10 +1669,10 @@ ppc_setup_opcodes (void)
              new_seg = VLE_OP_TO_SEG (new_seg);
 
 #ifdef PRINT_OPCODE_TABLE
-             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%x\tmask: 0x%x\tflags: 0x%llx\n",
+             printf ("%-14s\t#%04u\tmajor op: 0x%x\top: 0x%llx\tmask: 0x%llx\tflags: 0x%llx\n",
                      op->name, (unsigned int) (op - powerpc_opcodes),
-                     (unsigned int) new_seg, (unsigned int) op->opcode,
-                     (unsigned int) op->mask, (unsigned long long) op->flags);
+                     (unsigned int) new_seg, (unsigned long long) op->opcode,
+                     (unsigned long long) op->mask, (unsigned long long) op->flags);
 #endif
              /* The major opcodes had better be sorted.  Code in the
                 disassembler assumes the insns are sorted according to
@@ -1688,6 +1703,54 @@ ppc_setup_opcodes (void)
        }
     }
 
+  /* SPE2 instructions */
+  if ((ppc_cpu & PPC_OPCODE_SPE2) == PPC_OPCODE_SPE2)
+    {
+      op_end = spe2_opcodes + spe2_num_opcodes;
+      for (op = spe2_opcodes; op < op_end; op++)
+       {
+         if (ENABLE_CHECKING)
+           {
+             if (op != spe2_opcodes)
+               {
+               unsigned old_seg, new_seg;
+
+               old_seg = VLE_OP (op[-1].opcode, op[-1].mask);
+               old_seg = VLE_OP_TO_SEG (old_seg);
+               new_seg = VLE_OP (op[0].opcode, op[0].mask);
+               new_seg = VLE_OP_TO_SEG (new_seg);
+
+               /* The major opcodes had better be sorted.  Code in the
+                   disassembler assumes the insns are sorted according to
+                   major opcode.  */
+               if (new_seg < old_seg)
+                 {
+                 as_bad (_("major opcode is not sorted for %s"), op->name);
+                 bad_insn = TRUE;
+                 }
+               }
+
+             bad_insn |= insn_validate (op);
+           }
+
+         if ((ppc_cpu & op->flags) != 0 && !(ppc_cpu & op->deprecated))
+           {
+             const char *retval;
+
+             retval = hash_insert (ppc_hash, op->name, (void *) op);
+             if (retval != NULL)
+               {
+                 as_bad (_("duplicate instruction %s"),
+                         op->name);
+                 bad_insn = TRUE;
+               }
+           }
+       }
+
+      for (op = spe2_opcodes; op < op_end; op++)
+       hash_insert (ppc_hash, op->name, (void *) op);
+    }
+
   /* Insert the macros into a hash table.  */
   ppc_macro_hash = hash_new ();
 
@@ -1821,15 +1884,15 @@ ppc_cleanup (void)
 
 /* Insert an operand value into an instruction.  */
 
-static unsigned long
-ppc_insert_operand (unsigned long insn,
+static uint64_t
+ppc_insert_operand (uint64_t insn,
                    const struct powerpc_operand *operand,
-                   offsetT val,
+                   int64_t val,
                    ppc_cpu_t cpu,
                    const char *file,
                    unsigned int line)
 {
-  long min, max, right;
+  int64_t min, max, right;
 
   max = operand->bitm;
   right = max & -max;
@@ -1858,7 +1921,7 @@ ppc_insert_operand (unsigned long insn,
 
   if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
     {
-      long tmp = min;
+      int64_t tmp = min;
       min = -max;
       max = -tmp;
     }
@@ -1871,18 +1934,18 @@ ppc_insert_operand (unsigned long insn,
         sign extend the 32-bit value to 64 bits if so doing makes the
         value valid.  */
       if (val > max
-         && (offsetT) (val - 0x80000000 - 0x80000000) >= min
-         && (offsetT) (val - 0x80000000 - 0x80000000) <= max
-         && ((val - 0x80000000 - 0x80000000) & (right - 1)) == 0)
-       val = val - 0x80000000 - 0x80000000;
+         && (val - (1LL << 32)) >= min
+         && (val - (1LL << 32)) <= max
+         && ((val - (1LL << 32)) & (right - 1)) == 0)
+       val = val - (1LL << 32);
 
       /* Similarly, people write expressions like ~(1<<15), and expect
         this to be OK for a 32-bit unsigned value.  */
       else if (val < min
-              && (offsetT) (val + 0x80000000 + 0x80000000) >= min
-              && (offsetT) (val + 0x80000000 + 0x80000000) <= max
-              && ((val + 0x80000000 + 0x80000000) & (right - 1)) == 0)
-       val = val + 0x80000000 + 0x80000000;
+              && (val + (1LL << 32)) >= min
+              && (val + (1LL << 32)) <= max
+              && ((val + (1LL << 32)) & (right - 1)) == 0)
+       val = val + (1LL << 32);
 
       else if (val < min
               || val > max
@@ -1895,14 +1958,14 @@ ppc_insert_operand (unsigned long insn,
       const char *errmsg;
 
       errmsg = NULL;
-      insn = (*operand->insert) (insn, (long) val, cpu, &errmsg);
+      insn = (*operand->insert) (insn, val, cpu, &errmsg);
       if (errmsg != (const char *) NULL)
        as_bad_where (file, line, "%s", errmsg);
     }
   else if (operand->shift >= 0)
-    insn |= ((long) val & operand->bitm) << operand->shift;
+    insn |= (val & operand->bitm) << operand->shift;
   else
-    insn |= ((long) val & operand->bitm) >> -operand->shift;
+    insn |= (val & operand->bitm) >> -operand->shift;
 
   return insn;
 }
@@ -2676,7 +2739,7 @@ md_assemble (char *str)
 {
   char *s;
   const struct powerpc_opcode *opcode;
-  unsigned long insn;
+  uint64_t insn;
   const unsigned char *opindex_ptr;
   int skip_optional;
   int need_paren;
@@ -2805,7 +2868,7 @@ md_assemble (char *str)
          && !((operand->flags & PPC_OPERAND_OPTIONAL32) != 0 && ppc_obj64)
          && skip_optional)
        {
-         long val = ppc_optional_operand_value (operand);
+         int64_t val = ppc_optional_operand_value (operand);
          if (operand->insert)
            {
              insn = (*operand->insert) (insn, val, ppc_cpu, &errmsg);
@@ -2813,9 +2876,9 @@ md_assemble (char *str)
                as_bad ("%s", errmsg);
            }
          else if (operand->shift >= 0)
-           insn |= ((long) val & operand->bitm) << operand->shift;
+           insn |= (val & operand->bitm) << operand->shift;
          else
-           insn |= ((long) val & operand->bitm) >> -operand->shift;
+           insn |= (val & operand->bitm) >> -operand->shift;
 
          if ((operand->flags & PPC_OPERAND_NEXT) != 0)
            next_opindex = *opindex_ptr + 1;
@@ -2976,8 +3039,8 @@ md_assemble (char *str)
              && !((ex.X_md & PPC_OPERAND_GPR) != 0
                   && ex.X_add_number != 0
                   && (operand->flags & PPC_OPERAND_GPR_0) != 0))
-           as_bad (_("invalid register expression"));
-         insn = ppc_insert_operand (insn, operand, ex.X_add_number & 0xff,
+           as_warn (_("invalid register expression"));
+         insn = ppc_insert_operand (insn, operand, ex.X_add_number,
                                     ppc_cpu, (char *) NULL, 0);
        }
       else if (ex.X_op == O_constant)
@@ -3151,12 +3214,12 @@ md_assemble (char *str)
              /* addpcis.  */
              if (opcode->opcode == (19 << 26) + (2 << 1)
                  && reloc == BFD_RELOC_HI16_S)
-               reloc = BFD_RELOC_PPC_REL16DX_HA;
+               reloc = BFD_RELOC_PPC_16DX_HA;
 
              /* If VLE-mode convert LO/HI/HA relocations.  */
              if (opcode->flags & PPC_OPCODE_VLE)
                {
-                 int tmp_insn = insn & opcode->mask;
+                 uint64_t tmp_insn = insn & opcode->mask;
 
                  int use_a_reloc = (tmp_insn == E_OR2I_INSN
                                     || tmp_insn == E_AND2I_DOT_INSN
@@ -3630,6 +3693,16 @@ ppc_section_flags (flagword flags, bfd_vma attr ATTRIBUTE_UNUSED, int type)
 
   return flags;
 }
+
+bfd_vma
+ppc_elf_section_letter (int letter, const char **ptrmsg)
+{
+  if (letter == 'v')
+    return SHF_PPC_VLE;
+
+  *ptrmsg = _("bad .section directive: want a,e,v,w,x,M,S,G,T in string");
+  return -1;
+}
 #endif /* OBJ_ELF */
 
 \f
@@ -6566,10 +6639,50 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
     }
 #endif
 
-  if (fixP->fx_subsy != (symbolS *) NULL)
+  /* We are only able to convert some relocs to pc-relative.  */
+  if (fixP->fx_pcrel)
+    {
+      switch (fixP->fx_r_type)
+       {
+       case BFD_RELOC_LO16:
+         fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16:
+         fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
+         break;
+
+       case BFD_RELOC_HI16_S:
+         fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
+         break;
+
+       case BFD_RELOC_64:
+         fixP->fx_r_type = BFD_RELOC_64_PCREL;
+         break;
+
+       case BFD_RELOC_32:
+         fixP->fx_r_type = BFD_RELOC_32_PCREL;
+         break;
+
+       case BFD_RELOC_16:
+         fixP->fx_r_type = BFD_RELOC_16_PCREL;
+         break;
+
+       case BFD_RELOC_PPC_16DX_HA:
+         fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+         break;
+
+       default:
+         break;
+       }
+    }
+  else if (!fixP->fx_done
+          && fixP->fx_r_type == BFD_RELOC_PPC_16DX_HA)
     {
-      /* We can't actually support subtracting a symbol.  */
-      as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
+      /* addpcis is relative to next insn address.  */
+      value -= 4;
+      fixP->fx_r_type = BFD_RELOC_PPC_REL16DX_HA;
+      fixP->fx_pcrel = 1;
     }
 
   operand = NULL;
@@ -6651,6 +6764,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
 
     case BFD_RELOC_HI16_S:
     case BFD_RELOC_HI16_S_PCREL:
+    case BFD_RELOC_PPC_16DX_HA:
     case BFD_RELOC_PPC_REL16DX_HA:
 #ifdef OBJ_ELF
       if (REPORT_OVERFLOW_HI && ppc_obj64)
@@ -7078,83 +7192,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg)
                       _("data in executable section"));
     }
 
-  /* We are only able to convert some relocs to pc-relative.  */
-  if (!fixP->fx_done && fixP->fx_pcrel)
-    {
-      switch (fixP->fx_r_type)
-       {
-       case BFD_RELOC_LO16:
-         fixP->fx_r_type = BFD_RELOC_LO16_PCREL;
-         break;
-
-       case BFD_RELOC_HI16:
-         fixP->fx_r_type = BFD_RELOC_HI16_PCREL;
-         break;
-
-       case BFD_RELOC_HI16_S:
-         fixP->fx_r_type = BFD_RELOC_HI16_S_PCREL;
-         break;
-
-       case BFD_RELOC_64:
-         fixP->fx_r_type = BFD_RELOC_64_PCREL;
-         break;
-
-       case BFD_RELOC_32:
-         fixP->fx_r_type = BFD_RELOC_32_PCREL;
-         break;
-
-       case BFD_RELOC_16:
-         fixP->fx_r_type = BFD_RELOC_16_PCREL;
-         break;
-
-         /* Some of course are already pc-relative.  */
-       case BFD_RELOC_LO16_PCREL:
-       case BFD_RELOC_HI16_PCREL:
-       case BFD_RELOC_HI16_S_PCREL:
-       case BFD_RELOC_PPC_REL16DX_HA:
-       case BFD_RELOC_64_PCREL:
-       case BFD_RELOC_32_PCREL:
-       case BFD_RELOC_16_PCREL:
-       case BFD_RELOC_PPC_B16:
-       case BFD_RELOC_PPC_B16_BRTAKEN:
-       case BFD_RELOC_PPC_B16_BRNTAKEN:
-       case BFD_RELOC_PPC_B26:
-       case BFD_RELOC_PPC_LOCAL24PC:
-       case BFD_RELOC_24_PLT_PCREL:
-       case BFD_RELOC_32_PLT_PCREL:
-       case BFD_RELOC_64_PLT_PCREL:
-       case BFD_RELOC_PPC_VLE_REL8:
-       case BFD_RELOC_PPC_VLE_REL15:
-       case BFD_RELOC_PPC_VLE_REL24:
-         break;
-
-       default:
-         if (fixP->fx_addsy)
-           {
-             const char *sfile;
-             unsigned int sline;
-
-             /* Use expr_symbol_where to see if this is an
-                expression symbol.  */
-             if (expr_symbol_where (fixP->fx_addsy, &sfile, &sline))
-               as_bad_where (fixP->fx_file, fixP->fx_line,
-                             _("unresolved expression that must"
-                               " be resolved"));
-             else
-               as_bad_where (fixP->fx_file, fixP->fx_line,
-                             _("cannot emit PC relative %s relocation"
-                               " against %s"),
-                             bfd_get_reloc_code_name (fixP->fx_r_type),
-                             S_GET_NAME (fixP->fx_addsy));
-           }
-         else
-           as_bad_where (fixP->fx_file, fixP->fx_line,
-                         _("unable to resolve expression"));
-         fixP->fx_done = 1;
-         break;
-       }
-    }
-
 #ifdef OBJ_ELF
   ppc_elf_validate_fix (fixP, seg);
   fixP->fx_addnumber = value;
This page took 0.030092 seconds and 4 git commands to generate.