include/opcode/
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index d7eb9f690f0aff3d50cd330be67f626149ad2d85..be745abbf65aa56b2e9fecbd6a7bc0ffe4993fb9 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-ppc.c -- Assemble for the PowerPC or POWER (RS/6000)
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of GAS, the GNU Assembler.
@@ -20,7 +20,6 @@
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-#include <stdio.h>
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
@@ -183,9 +182,9 @@ const char EXP_CHARS[] = "eE";
    as in 0d1.0.  */
 const char FLT_CHARS[] = "dD";
 
-/* '+' and '-' can be used as postfix predicate predictors for conditional
-   branches.  So they need to be accepted as symbol characters.  */
-const char ppc_symbol_chars[] = "+-";
+/* Anything that can start an operand needs to be mentioned here,
+   to stop the input scrubber eating whitespace.  */
+const char ppc_symbol_chars[] = "%[";
 
 /* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
 int ppc_cie_data_alignment;
@@ -858,6 +857,9 @@ parse_cpu (const char *arg)
           || strcmp (arg, "7455") == 0)
     ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32);
+  else if (strcmp (arg, "e300") == 0)
+    ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32
+              | PPC_OPCODE_E300);
   else if (strcmp (arg, "altivec") == 0)
     {
       if (ppc_cpu == 0)
@@ -906,6 +908,24 @@ parse_cpu (const char *arg)
       ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
                 | PPC_OPCODE_64 | PPC_OPCODE_POWER4);
     }
+  else if (strcmp (arg, "power5") == 0)
+    {
+      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
+                | PPC_OPCODE_POWER5);
+    }
+  else if (strcmp (arg, "power6") == 0)
+    {
+      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
+                | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6);
+    }
+  else if (strcmp (arg, "cell") == 0)
+    {
+      ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
+                | PPC_OPCODE_64 | PPC_OPCODE_POWER4
+                | PPC_OPCODE_CELL);
+    }
   /* -mcom means assemble for the common intersection between Power
      and PowerPC.  At present, we just allow the union, rather
      than the intersection.  */
@@ -1100,10 +1120,14 @@ PowerPC options:\n\
 -mbooke64              generate code for 64-bit PowerPC BookE\n\
 -mbooke, mbooke32      generate code for 32-bit PowerPC BookE\n\
 -mpower4               generate code for Power4 architecture\n\
+-mpower5               generate code for Power5 architecture\n\
+-mpower6               generate code for Power6 architecture\n\
+-mcell                 generate code for Cell Broadband Engine architecture\n\
 -mcom                  generate code Power/PowerPC common instructions\n\
 -many                  generate code for any architecture (PWR/PWRX/PPC)\n"));
   fprintf (stream, _("\
 -maltivec              generate code for AltiVec\n\
+-me300                 generate code for PowerPC e300 family\n\
 -me500, -me500x2       generate code for Motorola e500 core complex\n\
 -mspe                  generate code for Motorola SPE instructions\n\
 -mregnames             Allow symbolic names for registers\n\
@@ -1144,12 +1168,7 @@ ppc_set_cpu ()
       else if (strcmp (default_cpu, "rs6000") == 0)
        ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32;
       else if (strncmp (default_cpu, "powerpc", 7) == 0)
-       {
-         if (default_cpu[7] == '6' && default_cpu[8] == '4')
-           ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64;
-         else
-           ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
-       }
+       ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32;
       else
        as_fatal (_("Unknown default cpu = %s, os = %s"),
                  default_cpu, default_os);
@@ -1209,9 +1228,13 @@ ppc_target_format ()
 #endif
 #endif
 #ifdef OBJ_ELF
+# ifdef TE_VXWORKS
+  return "elf32-powerpc-vxworks";
+# else
   return (target_big_endian
          ? (ppc_obj64 ? "elf64-powerpc" : "elf32-powerpc")
          : (ppc_obj64 ? "elf64-powerpcle" : "elf32-powerpcle"));
+# endif
 #endif
 }
 
@@ -1225,7 +1248,8 @@ ppc_setup_opcodes (void)
   const struct powerpc_opcode *op_end;
   const struct powerpc_macro *macro;
   const struct powerpc_macro *macro_end;
-  bfd_boolean dup_insn = FALSE;
+  unsigned int i;
+  bfd_boolean bad_insn = FALSE;
 
   if (ppc_hash != NULL)
     hash_die (ppc_hash);
@@ -1235,10 +1259,60 @@ ppc_setup_opcodes (void)
   /* Insert the opcodes into a hash table.  */
   ppc_hash = hash_new ();
 
+  /* Check operand masks.  Code here and in the disassembler assumes
+     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;
+
+      right_bit = mask & -mask;
+      mask += right_bit;
+      right_bit = mask & -mask;
+      if (mask != right_bit)
+       {
+         as_bad (_("powerpc_operands[%d].bitm invalid"), i);
+         bad_insn = TRUE;
+       }
+    }
+
   op_end = powerpc_opcodes + powerpc_num_opcodes;
   for (op = powerpc_opcodes; op < op_end; op++)
     {
-      know ((op->opcode & op->mask) == op->opcode);
+      const unsigned char *o;
+      unsigned long omask = op->mask;
+
+      /* The mask had better not trim off opcode bits.  */
+      if ((op->opcode & omask) != op->opcode)
+       {
+         as_bad (_("mask trims opcode bits for %s"),
+                 op->name);
+         bad_insn = TRUE;
+       }
+
+      /* The operands must not overlap the opcode or each other.  */
+      for (o = op->operands; *o; ++o)
+       if (*o >= num_powerpc_operands)
+         {
+           as_bad (_("operand index error for %s"),
+                   op->name);
+           bad_insn = TRUE;
+         }
+       else
+         {
+           const struct powerpc_operand *operand = &powerpc_operands[*o];
+           if (operand->shift >= 0)
+             {
+               unsigned long mask = operand->bitm << operand->shift;
+               if (omask & mask)
+                 {
+                   as_bad (_("operand %d overlap in %s"),
+                           (int) (o - op->operands), op->name);
+                   bad_insn = TRUE;
+                 }
+               omask |= mask;
+             }
+         }
 
       if ((op->flags & ppc_cpu & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) != 0
          && ((op->flags & (PPC_OPCODE_32 | PPC_OPCODE_64)) == 0
@@ -1255,7 +1329,13 @@ ppc_setup_opcodes (void)
              || (ppc_cpu & PPC_OPCODE_BOOKE) == 0)
          && ((op->flags & (PPC_OPCODE_POWER4 | PPC_OPCODE_NOPOWER4)) == 0
              || ((op->flags & PPC_OPCODE_POWER4)
-                 == (ppc_cpu & PPC_OPCODE_POWER4))))
+                 == (ppc_cpu & PPC_OPCODE_POWER4)))
+         && ((op->flags & PPC_OPCODE_POWER5) == 0
+             || ((op->flags & PPC_OPCODE_POWER5)
+                 == (ppc_cpu & PPC_OPCODE_POWER5)))
+         && ((op->flags & PPC_OPCODE_POWER6) == 0
+             || ((op->flags & PPC_OPCODE_POWER6)
+                 == (ppc_cpu & PPC_OPCODE_POWER6))))
        {
          const char *retval;
 
@@ -1267,9 +1347,9 @@ ppc_setup_opcodes (void)
                  && (op->flags & PPC_OPCODE_POWER) != 0)
                continue;
 
-             as_bad (_("Internal assembler error for instruction %s"),
+             as_bad (_("duplicate instruction %s"),
                      op->name);
-             dup_insn = TRUE;
+             bad_insn = TRUE;
            }
        }
     }
@@ -1291,13 +1371,13 @@ ppc_setup_opcodes (void)
          retval = hash_insert (ppc_macro_hash, macro->name, (PTR) macro);
          if (retval != (const char *) NULL)
            {
-             as_bad (_("Internal assembler error for macro %s"), macro->name);
-             dup_insn = TRUE;
+             as_bad (_("duplicate macro %s"), macro->name);
+             bad_insn = TRUE;
            }
        }
     }
 
-  if (dup_insn)
+  if (bad_insn)
     abort ();
 }
 
@@ -1418,49 +1498,52 @@ ppc_insert_operand (insn, operand, val, file, line)
      char *file;
      unsigned int line;
 {
-  if (operand->bits != 32)
+  long min, max, right;
+  offsetT test;
+  
+  max = operand->bitm;
+  right = max & -max;
+  min = 0;
+
+  if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
     {
-      long min, max;
-      offsetT test;
+      if ((operand->flags & PPC_OPERAND_SIGNOPT) == 0)
+       max >>= 1;
+      min = ~(max | ((max & -max) - 1)) ;
 
-      if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
+      if (!ppc_obj64)
        {
-         if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0)
-           max = (1 << operand->bits) - 1;
-         else
-           max = (1 << (operand->bits - 1)) - 1;
-         min = - (1 << (operand->bits - 1));
-
-         if (!ppc_obj64)
+         /* Some people write 32 bit hex constants with the sign
+            extension done by hand.  This shouldn't really be
+            valid, but, to permit this code to assemble on a 64
+            bit host, we sign extend the 32 bit value.  */
+         if (val > 0
+             && (val & (offsetT) 0x80000000) != 0
+             && (val & (offsetT) 0xffffffff) == val)
            {
-             /* Some people write 32 bit hex constants with the sign
-                extension done by hand.  This shouldn't really be
-                valid, but, to permit this code to assemble on a 64
-                bit host, we sign extend the 32 bit value.  */
-             if (val > 0
-                 && (val & (offsetT) 0x80000000) != 0
-                 && (val & (offsetT) 0xffffffff) == val)
-               {
-                 val -= 0x80000000;
-                 val -= 0x80000000;
-               }
+             val -= 0x80000000;
+             val -= 0x80000000;
            }
        }
-      else
-       {
-         max = (1 << operand->bits) - 1;
-         min = 0;
-       }
-
-      if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
-       test = - val;
-      else
-       test = val;
+    }
 
-      if (test < (offsetT) min || test > (offsetT) max)
-       as_bad_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
+  if ((operand->flags & PPC_OPERAND_PLUS1) != 0)
+    {
+      max++;
+      min++;
     }
 
+  if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
+    test = - val;
+  else
+    test = val;
+
+  if (test < (offsetT) min
+      || test > (offsetT) max
+      || (test & (right - 1)) != 0)
+    as_bad_value_out_of_range (_("operand"),
+                              test, (offsetT) min, (offsetT) max, file, line);
+
   if (operand->insert)
     {
       const char *errmsg;
@@ -1471,8 +1554,7 @@ ppc_insert_operand (insn, operand, val, file, line)
        as_bad_where (file, line, errmsg);
     }
   else
-    insn |= (((long) val & ((1 << operand->bits) - 1))
-            << operand->shift);
+    insn |= ((long) val & operand->bitm) << operand->shift;
 
   return insn;
 }
@@ -1916,7 +1998,7 @@ ppc_frob_file_before_adjust ()
       dotname = xmalloc (len + 1);
       dotname[0] = '.';
       memcpy (dotname + 1, name, len);
-      dotsym = symbol_find (dotname);
+      dotsym = symbol_find_noref (dotname, 1);
       free (dotname);
       if (dotsym != NULL && (symbol_used_p (dotsym)
                             || symbol_used_in_reloc_p (dotsym)))
@@ -2641,7 +2723,7 @@ md_assemble (str)
      BFD_RELOC_UNUSED plus the operand index.  This lets us easily
      handle fixups for any operand type, although that is admittedly
      not a very exciting feature.  We pick a BFD reloc type in
-     md_apply_fix3.  */
+     md_apply_fix.  */
   for (i = 0; i < fc; i++)
     {
       const struct powerpc_operand *operand;
@@ -4401,6 +4483,7 @@ ppc_pe_comm (lcomm)
     {
       S_SET_VALUE (symbolP, (valueT) temp);
       S_SET_EXTERNAL (symbolP);
+      S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
     }
 
   demand_empty_rest_of_line ();
@@ -4825,6 +4908,10 @@ ppc_frob_label (sym)
                     &symbol_rootP, &symbol_lastP);
       symbol_get_tc (ppc_current_csect)->within = sym;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* This variable is set by ppc_frob_symbol if any absolute symbols are
@@ -5236,13 +5323,15 @@ md_number_to_chars (buf, val, n)
 /* Align a section (I don't know why this is machine dependent).  */
 
 valueT
-md_section_align (seg, addr)
-     asection *seg;
-     valueT addr;
+md_section_align (asection *seg ATTRIBUTE_UNUSED, valueT addr)
 {
+#ifdef OBJ_ELF
+  return addr;
+#else
   int align = bfd_get_section_alignment (stdoutput, seg);
 
   return ((addr + (1 << align) - 1) & (-1 << align));
+#endif
 }
 
 /* We don't have any form of relaxing.  */
@@ -5460,6 +5549,7 @@ ppc_force_relocation (fix)
     case BFD_RELOC_PPC_B16_BRNTAKEN:
     case BFD_RELOC_PPC_BA16_BRTAKEN:
     case BFD_RELOC_PPC_BA16_BRNTAKEN:
+    case BFD_RELOC_24_PLT_PCREL:
     case BFD_RELOC_PPC64_TOC:
       return 1;
     default:
@@ -5489,6 +5579,47 @@ ppc_fix_adjustable (fix)
 }
 #endif
 
+/* Implement HANDLE_ALIGN.  This writes the NOP pattern into an
+   rs_align_code frag.  */
+
+void
+ppc_handle_align (struct frag *fragP)
+{
+  valueT count = (fragP->fr_next->fr_address
+                 - (fragP->fr_address + fragP->fr_fix));
+
+  if (count != 0 && (count & 3) == 0)
+    {
+      char *dest = fragP->fr_literal + fragP->fr_fix;
+
+      fragP->fr_var = 4;
+      md_number_to_chars (dest, 0x60000000, 4);
+
+      if ((ppc_cpu & PPC_OPCODE_POWER6) != 0)
+       {
+         /* For power6, we want the last nop to be a group terminating
+            one, "ori 1,1,0".  Do this by inserting an rs_fill frag
+            immediately after this one, with its address set to the last
+            nop location.  This will automatically reduce the number of
+            nops in the current frag by one.  */
+         if (count > 4)
+           {
+             struct frag *group_nop = xmalloc (SIZEOF_STRUCT_FRAG + 4);
+
+             memcpy (group_nop, fragP, SIZEOF_STRUCT_FRAG);
+             group_nop->fr_address = group_nop->fr_next->fr_address - 4;
+             group_nop->fr_fix = 0;
+             group_nop->fr_offset = 1;
+             group_nop->fr_type = rs_fill;
+             fragP->fr_next = group_nop;
+             dest = group_nop->fr_literal;
+           }
+
+         md_number_to_chars (dest, 0x60210000, 4);
+       }
+    }
+}
+
 /* Apply a fixup to the object code.  This is called for all the
    fixups we generated by the call to fix_new_exp, above.  In the call
    above we used a reloc code which was the largest legal reloc code
@@ -5499,7 +5630,7 @@ ppc_fix_adjustable (fix)
    fixup.  */
 
 void
-md_apply_fix3 (fixP, valP, seg)
+md_apply_fix (fixP, valP, seg)
      fixS *fixP;
      valueT * valP;
      segT seg ATTRIBUTE_UNUSED;
@@ -5517,11 +5648,11 @@ md_apply_fix3 (fixP, valP, seg)
     fixP->fx_done = 1;
 #else
   /* FIXME FIXME FIXME: The value we are passed in *valP includes
-     the symbol values.  Since we are using BFD_ASSEMBLER, if we are
-     doing this relocation the code in write.c is going to call
-     bfd_install_relocation, which is also going to use the symbol
-     value.  That means that if the reloc is fully resolved we want to
-     use *valP since bfd_install_relocation is not being used.
+     the symbol values.  If we are doing this relocation the code in
+     write.c is going to call bfd_install_relocation, which is also
+     going to use the symbol value.  That means that if the reloc is
+     fully resolved we want to use *valP since bfd_install_relocation is
+     not being used.
      However, if the reloc is not fully resolved we do not want to use
      *valP, and must use fx_offset instead.  However, if the reloc
      is PC relative, we do want to use *valP since it includes the
@@ -5559,7 +5690,7 @@ md_apply_fix3 (fixP, valP, seg)
         csect.  Other usages, such as `.long sym', generate relocs.  This
         is the documented behaviour of non-TOC symbols.  */
       if ((operand->flags & PPC_OPERAND_PARENS) != 0
-         && operand->bits == 16
+         && (operand->bitm & 0xfff0) == 0xfff0
          && operand->shift == 0
          && (operand->insert == NULL || ppc_obj64)
          && fixP->fx_addsy != NULL
@@ -5597,11 +5728,11 @@ md_apply_fix3 (fixP, valP, seg)
         We are only prepared to turn a few of the operands into
         relocs.  */
       if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
-         && operand->bits == 26
+         && operand->bitm == 0x3fffffc
          && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_B26;
       else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0
-         && operand->bits == 16
+         && operand->bitm == 0xfffc
          && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_B16;
@@ -5612,11 +5743,11 @@ md_apply_fix3 (fixP, valP, seg)
 #endif
        }
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
-              && operand->bits == 26
+              && operand->bitm == 0x3fffffc
               && operand->shift == 0)
        fixP->fx_r_type = BFD_RELOC_PPC_BA26;
       else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0
-              && operand->bits == 16
+              && operand->bitm == 0xfffc
               && operand->shift == 0)
        {
          fixP->fx_r_type = BFD_RELOC_PPC_BA16;
@@ -5628,7 +5759,7 @@ md_apply_fix3 (fixP, valP, seg)
        }
 #if defined (OBJ_XCOFF) || defined (OBJ_ELF)
       else if ((operand->flags & PPC_OPERAND_PARENS) != 0
-              && operand->bits == 16
+              && (operand->bitm & 0xfff0) == 0xfff0
               && operand->shift == 0)
        {
          if (ppc_is_toc_sym (fixP->fx_addsy))
@@ -5999,6 +6130,13 @@ md_apply_fix3 (fixP, valP, seg)
 
 #ifdef OBJ_ELF
   fixP->fx_addnumber = value;
+
+  /* PowerPC uses RELA relocs, ie. the reloc addend is stored separately
+     from the section contents.  If we are going to be emitting a reloc
+     then the section contents are immaterial, so don't warn if they
+     happen to overflow.  Leave such warnings to ld.  */
+  if (!fixP->fx_done)
+    fixP->fx_no_overflow = 1;
 #else
   if (fixP->fx_r_type != BFD_RELOC_PPC_TOC16)
     fixP->fx_addnumber = 0;
@@ -6050,7 +6188,7 @@ ppc_cfi_frame_initial_instructions ()
 }
 
 int
-tc_ppc_regname_to_dw2regnum (const char *regname)
+tc_ppc_regname_to_dw2regnum (char *regname)
 {
   unsigned int regnum = -1;
   unsigned int i;
This page took 0.031734 seconds and 4 git commands to generate.