2003-08-24 Jason Eckhardt <jle@rice.edu>
[deliverable/binutils-gdb.git] / gas / config / tc-ppc.c
index 56af40abfbdc8ea8633a61d94f7c63391987f821..30aa2fd62091528eb3dc19196e1e951023b7f4f5 100644 (file)
@@ -24,7 +24,7 @@
 #include "as.h"
 #include "safe-ctype.h"
 #include "subsegs.h"
-
+#include "dw2gencfi.h"
 #include "opcode/ppc.h"
 
 #ifdef OBJ_ELF
@@ -111,7 +111,7 @@ static void ppc_ec PARAMS ((int));
 static void ppc_ef PARAMS ((int));
 static void ppc_es PARAMS ((int));
 static void ppc_csect PARAMS ((int));
-static void ppc_change_csect PARAMS ((symbolS *));
+static void ppc_change_csect PARAMS ((symbolS *, offsetT));
 static void ppc_function PARAMS ((int));
 static void ppc_extern PARAMS ((int));
 static void ppc_lglobl PARAMS ((int));
@@ -182,6 +182,13 @@ const char EXP_CHARS[] = "eE";
 /* Characters which mean that a number is a floating point constant,
    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[] = "+-";
+
+/* The dwarf2 data alignment, adjusted for 32 or 64 bit.  */
+int ppc_cie_data_alignment;
 \f
 /* The target specific pseudo-ops which we support.  */
 
@@ -233,8 +240,6 @@ const pseudo_typeS md_pseudo_table[] =
   { "rdata",   ppc_elf_rdata,  0 },
   { "rodata",  ppc_elf_rdata,  0 },
   { "lcomm",   ppc_elf_lcomm,  0 },
-  { "file",    (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
-  { "loc",     dwarf2_directive_loc, 0 },
 #endif
 
 #ifdef TE_PE
@@ -905,6 +910,9 @@ md_parse_option (c, arg)
               || strcmp (arg, "405") == 0)
        ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC
                   | PPC_OPCODE_403 | PPC_OPCODE_32);
+      else if (strcmp (arg, "440") == 0)
+       ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
+                  | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI);
       else if (strcmp (arg, "7400") == 0
               || strcmp (arg, "7410") == 0
               || strcmp (arg, "7450") == 0
@@ -1060,36 +1068,41 @@ md_show_usage (stream)
 {
   fprintf (stream, _("\
 PowerPC options:\n\
+-a32                   generate ELF32/XCOFF32\n\
+-a64                   generate ELF64/XCOFF64\n\
 -u                     ignored\n\
 -mpwrx, -mpwr2         generate code for POWER/2 (RIOS2)\n\
 -mpwr                  generate code for POWER (RIOS1)\n\
 -m601                  generate code for PowerPC 601\n\
 -mppc, -mppc32, -m603, -m604\n\
                        generate code for PowerPC 603/604\n\
--m403, -m405            generate code for PowerPC 403/405\n\
+-m403, -m405           generate code for PowerPC 403/405\n\
+-m440                  generate code for PowerPC 440\n\
 -m7400, -m7410, -m7450, -m7455\n\
-                       generate code For PowerPC 7400/7410/7450/7455\n\
+                       generate code For PowerPC 7400/7410/7450/7455\n"));
+  fprintf (stream, _("\
 -mppc64, -m620         generate code for PowerPC 620/625/630\n\
 -mppc64bridge          generate code for PowerPC 64, including bridge insns\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\
--maltivec              generate code for AltiVec\n\
 -mcom                  generate code Power/PowerPC common instructions\n\
--many                  generate code for any architecture (PWR/PWRX/PPC)\n\
--mregnames             Allow symbolic names for registers\n\
--mno-regnames          Do not allow symbolic names for registers\n"));
+-many                  generate code for any architecture (PWR/PWRX/PPC)\n"));
   fprintf (stream, _("\
+-maltivec              generate code for AltiVec\n\
 -me500, -me500x2       generate code for Motorola e500 core complex\n\
--mspe                  generate code for Motorola SPE instructions\n"));
+-mspe                  generate code for Motorola SPE instructions\n\
+-mregnames             Allow symbolic names for registers\n\
+-mno-regnames          Do not allow symbolic names for registers\n"));
 #ifdef OBJ_ELF
   fprintf (stream, _("\
 -mrelocatable          support for GCC's -mrelocatble option\n\
 -mrelocatable-lib      support for GCC's -mrelocatble-lib option\n\
 -memb                  set PPC_EMB bit in ELF flags\n\
--mlittle, -mlittle-endian\n\
+-mlittle, -mlittle-endian, -l, -le\n\
                        generate code for a little endian machine\n\
--mbig, -mbig-endian    generate code for a big endian machine\n\
+-mbig, -mbig-endian, -b, -be\n\
+                       generate code for a big endian machine\n\
 -msolaris              generate code for Solaris\n\
 -mno-solaris           do not generate code for Solaris\n\
 -V                     print assembler version number\n\
@@ -1202,6 +1215,8 @@ md_begin ()
 
   ppc_set_cpu ();
 
+  ppc_cie_data_alignment = ppc_obj64 ? -8 : -4;
+
 #ifdef OBJ_ELF
   /* Set the ELF flags if desired.  */
   if (ppc_flags && !msolaris)
@@ -1336,7 +1351,7 @@ ppc_cleanup ()
     md_number_to_chars (p, (valueT) 8, 4);
 
     p = frag_more (4);
-    md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4);
+    md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4);
 
     p = frag_more (4);
     md_number_to_chars (p, (valueT) 2, 4);
@@ -1580,40 +1595,38 @@ ppc_elf_suffix (str_p, exp_p)
          }
 
        if (!ppc_obj64)
+         if (exp_p->X_add_number != 0
+             && (reloc == (int) BFD_RELOC_16_GOTOFF
+                 || reloc == (int) BFD_RELOC_LO16_GOTOFF
+                 || reloc == (int) BFD_RELOC_HI16_GOTOFF
+                 || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
+           as_warn (_("identifier+constant@got means identifier@got+constant"));
+
+       /* Now check for identifier@suffix+constant.  */
+       if (*str == '-' || *str == '+')
          {
-           if (exp_p->X_add_number != 0
-               && (reloc == (int) BFD_RELOC_16_GOTOFF
-                   || reloc == (int) BFD_RELOC_LO16_GOTOFF
-                   || reloc == (int) BFD_RELOC_HI16_GOTOFF
-                   || reloc == (int) BFD_RELOC_HI16_S_GOTOFF))
-             as_warn (_("identifier+constant@got means identifier@got+constant"));
-
-           /* Now check for identifier@suffix+constant.  */
-           if (*str == '-' || *str == '+')
+           char *orig_line = input_line_pointer;
+           expressionS new_exp;
+
+           input_line_pointer = str;
+           expression (&new_exp);
+           if (new_exp.X_op == O_constant)
              {
-               char *orig_line = input_line_pointer;
-               expressionS new_exp;
-
-               input_line_pointer = str;
-               expression (&new_exp);
-               if (new_exp.X_op == O_constant)
-                 {
-                   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;
+               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;
          }
        *str_p = str;
 
        if (reloc == (int) BFD_RELOC_PPC64_TOC
-           && exp_p->X_op == O_symbol)
+           && exp_p->X_op == O_symbol
+           && strcmp (S_GET_NAME (exp_p->X_add_symbol), ".TOC.") == 0)
          {
-           /* This reloc type ignores the symbol.  Change the symbol
-              so that the dummy .TOC. symbol can be omitted from the
-              object file.  */
+           /* Change the symbol so that the dummy .TOC. symbol can be
+              omitted from the object file.  */
            exp_p->X_add_symbol = &abs_symbol;
          }
 
@@ -2443,7 +2456,7 @@ md_assemble (str)
            }
 
          if (ppc_obj64
-             && (operand->flags & PPC_OPERAND_DS) != 0)
+             && (operand->flags & (PPC_OPERAND_DS | PPC_OPERAND_DQ)) != 0)
            {
              switch (reloc)
                {
@@ -2748,7 +2761,7 @@ ppc_section_letter (letter, ptr_msg)
     return SHF_EXCLUDE;
 
   *ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
-  return 0;
+  return -1;
 }
 
 int
@@ -3002,6 +3015,7 @@ ppc_csect (ignore)
   char *name;
   char endc;
   symbolS *sym;
+  offsetT align;
 
   name = input_line_pointer;
   endc = get_symbol_end ();
@@ -3016,22 +3030,24 @@ ppc_csect (ignore)
       symbol_get_tc (sym)->class = XMC_PR;
     }
 
-  ppc_change_csect (sym);
-
+  align = 2;
   if (*input_line_pointer == ',')
     {
       ++input_line_pointer;
-      symbol_get_tc (sym)->align = get_absolute_expression ();
+      align = get_absolute_expression ();
     }
 
+  ppc_change_csect (sym, align);
+
   demand_empty_rest_of_line ();
 }
 
 /* Change to a different csect.  */
 
 static void
-ppc_change_csect (sym)
+ppc_change_csect (sym, align)
      symbolS *sym;
+     offsetT align;
 {
   if (S_IS_DEFINED (sym))
     subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg);
@@ -3041,11 +3057,14 @@ ppc_change_csect (sym)
       int after_toc;
       int hold_chunksize;
       symbolS *list;
+      int is_code;
+      segT sec;
 
       /* This is a new csect.  We need to look at the symbol class to
         figure out whether it should go in the text section or the
         data section.  */
       after_toc = 0;
+      is_code = 0;
       switch (symbol_get_tc (sym)->class)
        {
        case XMC_PR:
@@ -3060,6 +3079,7 @@ ppc_change_csect (sym)
          symbol_get_tc (sym)->subseg = ppc_text_subsegment;
          ++ppc_text_subsegment;
          list_ptr = &ppc_text_csects;
+         is_code = 1;
          break;
        case XMC_RW:
        case XMC_TC0:
@@ -3087,18 +3107,24 @@ ppc_change_csect (sym)
       hold_chunksize = chunksize;
       chunksize = 64;
 
-      subseg_new (segment_name (S_GET_SEGMENT (sym)),
-                 symbol_get_tc (sym)->subseg);
+      sec = subseg_new (segment_name (S_GET_SEGMENT (sym)),
+                       symbol_get_tc (sym)->subseg);
 
       chunksize = hold_chunksize;
 
       if (after_toc)
        ppc_after_toc_frag = frag_now;
 
+      record_alignment (sec, align);
+      if (is_code)
+       frag_align_code (align, 0);
+      else
+       frag_align (align, 0, 0);
+
       symbol_set_frag (sym, frag_now);
       S_SET_VALUE (sym, (valueT) frag_now_fix ());
 
-      symbol_get_tc (sym)->align = 2;
+      symbol_get_tc (sym)->align = align;
       symbol_get_tc (sym)->output = 1;
       symbol_get_tc (sym)->within = sym;
 
@@ -3136,7 +3162,7 @@ ppc_section (type)
 
   sym = symbol_find_or_make (name);
 
-  ppc_change_csect (sym);
+  ppc_change_csect (sym, 2);
 
   demand_empty_rest_of_line ();
 }
@@ -3173,7 +3199,7 @@ ppc_named_section (ignore)
 
   sym = symbol_find_or_make (real_name);
 
-  ppc_change_csect (sym);
+  ppc_change_csect (sym, 2);
 
   demand_empty_rest_of_line ();
 }
@@ -3844,7 +3870,7 @@ ppc_vbyte (dummy)
    give to this location in the toc; this will be a symbol with class
    TC.  The rest of the arguments are N-byte values to actually put at
    this location in the TOC; often there is just one more argument, a
-   relocateable symbol reference.  The size of the value to store
+   relocatable symbol reference.  The size of the value to store
    depends on target word size.  A 32-bit target uses 4-byte values, a
    64-bit target uses 8-byte values.
 
@@ -5043,8 +5069,9 @@ void
 ppc_frob_section (sec)
      asection *sec;
 {
-  static bfd_size_type vma = 0;
+  static bfd_vma vma = 0;
 
+  vma = md_section_align (sec, vma);
   bfd_set_section_vma (stdoutput, sec, vma);
   vma += bfd_section_size (stdoutput, sec);
 }
@@ -5524,15 +5551,26 @@ 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->shift == 0
-              && ppc_is_toc_sym (fixP->fx_addsy))
+              && operand->shift == 0)
        {
-         fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
+         if (ppc_is_toc_sym (fixP->fx_addsy))
+           {
+             fixP->fx_r_type = BFD_RELOC_PPC_TOC16;
 #ifdef OBJ_ELF
-         if (ppc_obj64
-             && (operand->flags & PPC_OPERAND_DS) != 0)
-           fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
+             if (ppc_obj64
+                 && (operand->flags & PPC_OPERAND_DS) != 0)
+               fixP->fx_r_type = BFD_RELOC_PPC64_TOC16_DS;
 #endif
+           }
+         else
+           {
+             fixP->fx_r_type = BFD_RELOC_16;
+#ifdef OBJ_ELF
+             if (ppc_obj64
+                 && (operand->flags & PPC_OPERAND_DS) != 0)
+               fixP->fx_r_type = BFD_RELOC_PPC64_ADDR16_DS;
+#endif
+           }
          fixP->fx_size = 2;
          if (target_big_endian)
            fixP->fx_where += 2;
@@ -5699,13 +5737,18 @@ md_apply_fix3 (fixP, valP, seg)
            abort ();
          {
            unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
-           unsigned long val;
+           unsigned long val, mask;
 
            if (target_big_endian)
-             val = bfd_getb16 (where);
+             val = bfd_getb32 (where - 2);
            else
-             val = bfd_getl16 (where);
-           val |= (value & 0xfffc);
+             val = bfd_getl32 (where);
+           mask = 0xfffc;
+           /* lq insns reserve the four lsbs.  */
+           if ((ppc_cpu & PPC_OPCODE_POWER4) != 0
+               && (val & (0x3f << 26)) == (56u << 26))
+             mask = 0xfff0;
+           val |= value & mask;
            if (target_big_endian)
              bfd_putb16 ((bfd_vma) val, where);
            else
@@ -5713,6 +5756,12 @@ md_apply_fix3 (fixP, valP, seg)
          }
          break;
 
+       case BFD_RELOC_PPC_B16_BRTAKEN:
+       case BFD_RELOC_PPC_B16_BRNTAKEN:
+       case BFD_RELOC_PPC_BA16_BRTAKEN:
+       case BFD_RELOC_PPC_BA16_BRNTAKEN:
+         break;
+
        case BFD_RELOC_PPC_TLS:
        case BFD_RELOC_PPC_DTPMOD:
        case BFD_RELOC_PPC_TPREL16:
@@ -5879,3 +5928,49 @@ tc_gen_reloc (seg, fixp)
 
   return reloc;
 }
+
+void
+ppc_cfi_frame_initial_instructions ()
+{
+  cfi_add_CFA_def_cfa (1, 0);
+}
+
+int
+tc_ppc_regname_to_dw2regnum (const char *regname)
+{
+  unsigned int regnum = -1;
+  unsigned int i;
+  const char *p;
+  char *q;
+  static struct { char *name; int dw2regnum; } regnames[] =
+    {
+      { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 },
+      { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 },
+      { "cc", 68 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 },
+      { "spe_acc", 111 }, { "spefscr", 112 }
+    };
+
+  for (i = 0; i < ARRAY_SIZE (regnames); ++i)
+    if (strcmp (regnames[i].name, regname) == 0)
+      return regnames[i].dw2regnum;
+
+  if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v')
+    {
+      p = regname + 1 + (regname[1] == '.');
+      regnum = strtoul (p, &q, 10);
+      if (p == q || *q || regnum >= 32)
+       return -1;
+      if (regname[0] == 'f')
+        regnum += 32;
+      else if (regname[0] == 'v')
+        regnum += 77;
+    }
+  else if (regname[0] == 'c' && regname[1] == 'r')
+    {
+      p = regname + 2 + (regname[2] == '.');
+      if (p[0] < '0' || p[0] > '7' || p[1])
+        return -1;
+      regnum = p[0] - '0' + 68;
+    }
+  return regnum;
+}
This page took 0.029153 seconds and 4 git commands to generate.