gas/
[deliverable/binutils-gdb.git] / gas / config / tc-ia64.c
index 751488bb5203a7ebb4859f88ee7823ab4178e55b..484b25c45e1329ab5d809c8ac640c7c5d535d793 100644 (file)
@@ -229,6 +229,13 @@ static struct
        that are predicatable.  */
     expressionS qp;
 
+    /* Optimize for which CPU.  */
+    enum
+      {
+       itanium1,
+       itanium2
+      } tune;
+
     /* What to do when hint.b is used.  */
     enum
       {
@@ -321,6 +328,21 @@ static struct
   }
 md;
 
+/* These are not const, because they are modified to MMI for non-itanium1
+   targets below.  */
+/* MFI bundle of nops.  */
+static unsigned char le_nop[16] =
+{
+  0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
+};
+/* MFI bundle of nops with stop-bit.  */
+static unsigned char le_nop_stop[16] =
+{
+  0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
+};
+
 /* application registers:  */
 
 #define AR_K0          0
@@ -3438,7 +3460,7 @@ static char *special_linkonce_name[] =
   };
 
 static void
-start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
+start_unwind_section (const segT text_seg, int sec_index)
 {
   /*
     Use a slightly ugly scheme to derive the unwind section names from
@@ -3500,8 +3522,6 @@ start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
       prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
       suffix += sizeof (".gnu.linkonce.t.") - 1;
     }
-  else if (linkonce_empty)
-    return;
 
   prefix_len = strlen (prefix);
   suffix_len = strlen (suffix);
@@ -3589,7 +3609,7 @@ generate_unwind_image (const segT text_seg)
       expressionS exp;
       bfd_reloc_code_real_type reloc;
 
-      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 0);
+      start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
 
       /* Make sure the section has 4 byte alignment for ILP32 and
         8 byte alignment for LP64.  */
@@ -3630,8 +3650,6 @@ generate_unwind_image (const segT text_seg)
          unwind.personality_routine = 0;
        }
     }
-  else
-    start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 1);
 
   free_saved_prologue_counts ();
   unwind.list = unwind.tail = unwind.current_entry = NULL;
@@ -4404,7 +4422,7 @@ dot_endp (dummy)
       subseg_set (md.last_text_seg, 0);
       proc_end = expr_build_dot ();
 
-      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 0);
+      start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
 
       /* Make sure that section has 4 byte alignment for ILP32 and
          8 byte alignment for LP64.  */
@@ -4444,9 +4462,6 @@ dot_endp (dummy)
                            bytes_per_address);
 
     }
-  else
-    start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 1);
-
   subseg_set (saved_seg, saved_subseg);
 
   if (unwind.proc_start)
@@ -6459,7 +6474,7 @@ emit_one_bundle ()
   bfd_vma insn[3] = { -1, -1, -1 };
   struct ia64_opcode *idesc;
   int end_of_insn_group = 0, user_template = -1;
-  int n, i, j, first, curr;
+  int n, i, j, first, curr, last_slot;
   unw_rec_list *ptr, *last_ptr, *end_ptr;
   bfd_vma t0 = 0, t1 = 0;
   struct label_fix *lfix;
@@ -6511,6 +6526,7 @@ emit_one_bundle ()
   curr = first;
   idesc = md.slot[curr].idesc;
   end_of_insn_group = 0;
+  last_slot = -1;
   for (i = 0; i < 3 && md.num_slots_in_use > 0; ++i)
     {
       /* If we have unwind records, we may need to update some now.  */
@@ -6776,27 +6792,7 @@ emit_one_bundle ()
        }
 
       if (insn_unit != required_unit)
-       {
-         if (required_unit == IA64_UNIT_L
-             && insn_unit == IA64_UNIT_I
-             && !(idesc->flags & IA64_OPCODE_X_IN_MLX))
-           {
-             /* we got ourselves an MLX template but the current
-                instruction isn't an X-unit, or an I-unit instruction
-                that can go into the X slot of an MLX template.  Duh.  */
-             if (md.num_slots_in_use >= NUM_SLOTS)
-               {
-                 as_bad_where (md.slot[curr].src_file,
-                               md.slot[curr].src_line,
-                               "`%s' can't go in X slot of "
-                               "MLX template", idesc->name);
-                 /* drop this insn so we don't livelock:  */
-                 --md.num_slots_in_use;
-               }
-             break;
-           }
-         continue;             /* try next slot */
-       }
+       continue;               /* Try next slot.  */
 
       if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen)
        {
@@ -6830,6 +6826,7 @@ emit_one_bundle ()
          ++i;
        }
       --md.num_slots_in_use;
+      last_slot = i;
 
       /* now is a good time to fix up the labels for this insn:  */
       for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
@@ -6874,10 +6871,35 @@ emit_one_bundle ()
     {
       if (md.num_slots_in_use > 0)
        {
-         as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
-                       "`%s' does not fit into %s template",
-                       idesc->name, ia64_templ_desc[template].name);
-         --md.num_slots_in_use;
+         if (last_slot >= 2)
+           as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                         "`%s' does not fit into bundle", idesc->name);
+         else if (last_slot < 0)
+           {
+             as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                           "`%s' does not fit into %s template",
+                           idesc->name, ia64_templ_desc[template].name);
+             /* Drop first insn so we don't livelock.  */
+             --md.num_slots_in_use;
+             know (curr == first);
+             ia64_free_opcode (md.slot[curr].idesc);
+             memset (md.slot + curr, 0, sizeof (md.slot[curr]));
+             md.slot[curr].user_template = -1;
+           }
+         else
+           {
+             const char *where;
+
+             if (template == 2)
+               where = "X slot";
+             else if (last_slot == 0)
+               where = "slots 2 or 3";
+             else
+               where = "slot 3";
+             as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
+                           "`%s' can't go in %s of %s template",
+                           idesc->name, where, ia64_templ_desc[template].name);
+           }
        }
       else
        as_bad_where (md.slot[curr].src_file, md.slot[curr].src_line,
@@ -6950,6 +6972,16 @@ md_parse_option (c, arg)
          else
            return 0;
        }
+      else if (strncmp (arg, "tune=", 5) == 0)
+       {
+         arg += 5;
+         if (strcmp (arg, "itanium1") == 0)
+           md.tune = itanium1;
+         else if (strcmp (arg, "itanium2") == 0)
+           md.tune = itanium2;
+         else
+           return 0;
+       }
       else
        return 0;
       break;
@@ -7062,6 +7094,8 @@ IA-64 options:\n\
                          EF_IA_64_NOFUNCDESC_CONS_GP)\n\
   -milp32|-milp64|-mlp64|-mp64 select data model (default -mlp64)\n\
   -mle | -mbe            select little- or big-endian byte order (default -mle)\n\
+  -mtune=[itanium1|itanium2]\n\
+                         tune for a specific CPU (default -mtune=itanium2)\n\
   -munwind-check=[warning|error]\n\
                          unwind directive check (default -munwind-check=warning)\n\
   -mhint.b=[ok|warning|error]\n\
@@ -7115,11 +7149,30 @@ match (int templ, int type, int slot)
 static inline int
 extra_goodness (int templ, int slot)
 {
-  if (slot == 1 && match (templ, IA64_TYPE_F, slot))
-    return 2;
-  if (slot == 2 && match (templ, IA64_TYPE_B, slot))
-    return 1;
-  return 0;
+  switch (md.tune)
+    {
+    case itanium1:
+      if (slot == 1 && match (templ, IA64_TYPE_F, slot))
+       return 2;
+      else if (slot == 2 && match (templ, IA64_TYPE_B, slot))
+       return 1;
+      else
+       return 0;
+      break;
+    case itanium2:
+      if (match (templ, IA64_TYPE_M, slot)
+         || match (templ, IA64_TYPE_I, slot))
+       /* Favor M- and I-unit NOPs.  We definitely want to avoid
+          F-unit and B-unit may cause split-issue or less-than-optimal
+          branch-prediction.  */
+       return 2;
+      else
+       return 0;
+      break;
+    default:
+      abort ();
+      return 0;
+    }
 }
 
 /* This function is called once, at assembler startup time.  It sets
@@ -7214,11 +7267,17 @@ md_begin ()
     symbol_new (".<iplt>", undefined_section, FUNC_IPLT_RELOC,
                &zero_address_frag);
 
+ if (md.tune != itanium1)
+   {
+     /* Convert MFI NOPs bundles into MMI NOPs bundles.  */
+     le_nop[0] = 0x8;
+     le_nop_stop[0] = 0x9;
+   }
+
   /* Compute the table of best templates.  We compute goodness as a
-     base 4 value, in which each match counts for 3, each F counts
-     for 2, each B counts for 1.  This should maximize the number of
-     F and B nops in the chosen bundles, which is good because these
-     pipelines are least likely to be overcommitted.  */
+     base 4 value, in which each match counts for 3.  Match-failures
+     result in NOPs and we use extra_goodness() to pick the execution
+     units that are best suited for issuing the NOP.  */
   for (i = 0; i < IA64_NUM_TYPES; ++i)
     for (j = 0; j < IA64_NUM_TYPES; ++j)
       for (k = 0; k < IA64_NUM_TYPES; ++k)
@@ -7419,6 +7478,7 @@ ia64_init (argc, argv)
   /* FIXME: We should change it to unwind_check_error someday.  */
   md.unwind_check = unwind_check_warning;
   md.hint_b = hint_b_error;
+  md.tune = itanium2;
 }
 
 /* Return a string for the target object file format.  */
@@ -7962,8 +8022,6 @@ ia64_canonicalize_symbol_name (name)
     {
       if (full > 0)
        as_bad ("Standalone `#' is illegal");
-      else
-       as_bad ("Zero-length symbol is illegal");
     }
   else if (len < full - 1)
     as_warn ("Redundant `#' suffix operators");
@@ -11471,14 +11529,6 @@ void
 ia64_handle_align (fragp)
      fragS *fragp;
 {
-  /* Use mfi bundle of nops with no stop bits.  */
-  static const unsigned char le_nop[]
-    = { 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
-  static const unsigned char le_nop_stop[]
-    = { 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00};
-
   int bytes;
   char *p;
   const unsigned char *nop;
This page took 0.03004 seconds and 4 git commands to generate.