* config/tc-xtensa.c (xtensa_switch_section_emit_state): Use subseg_set.
[deliverable/binutils-gdb.git] / gas / config / tc-xtensa.c
index faac466b3374bf123b8f35a031a321781d3602e7..1df3c0b1b9aed2b014a522154a8bd75027c331c5 100644 (file)
@@ -308,29 +308,6 @@ typedef struct emit_state_struct
 } emit_state;
 
 
-/* A map that keeps information on a per-subsegment basis.  This is
-   maintained during initial assembly, but is invalid once the
-   subsegments are smashed together.  I.E., it cannot be used during
-   the relaxation.  */
-
-typedef struct subseg_map_struct
-{
-  /* the key */
-  segT seg;
-  subsegT subseg;
-
-  /* the data */
-  unsigned flags;
-  /* the fall-through frequency + the branch target frequency
-     typically used for the instruction after a call */
-  float cur_total_freq;
-  /* the branch target frequency alone */
-  float cur_target_freq;
-
-  struct subseg_map_struct *next;
-} subseg_map;
-
-
 /* Opcode placement information */
 
 typedef unsigned long long bitfield;
@@ -465,6 +442,7 @@ static void set_literal_pool_location (segT, fragS *);
 static void xtensa_set_frag_assembly_state (fragS *);
 static void finish_vinsn (vliw_insn *);
 static bfd_boolean emit_single_op (TInsn *);
+static int total_frag_text_expansion (fragS *);
 
 /* Alignment Functions.  */
 
@@ -475,11 +453,13 @@ static addressT get_text_align_max_fill_size (int, bfd_boolean, bfd_boolean);
 
 static long relax_frag_add_nop (fragS *);
 
-/* Flags for the Last Instruction in Each Subsegment.  */
+/* Accessors for additional per-subsegment information.  */
 
-static subseg_map *get_subseg_info (segT, subsegT);
 static unsigned get_last_insn_flags (segT, subsegT);
 static void set_last_insn_flags (segT, subsegT, unsigned, bfd_boolean);
+static float get_subseg_total_freq (segT, subsegT);
+static float get_subseg_target_freq (segT, subsegT);
+static void set_subseg_freq (segT, subsegT, float, float);
 
 /* Segment list functions.  */
 
@@ -492,14 +472,6 @@ static void xtensa_restore_emit_state (emit_state *);
 static void cache_literal_section
   (seg_list *, const char *, segT *, bfd_boolean);
 
-/* Property flags on fragments and conversion to object file flags.  */
-
-static bfd_boolean get_frag_is_literal (const fragS *);
-static bfd_boolean get_frag_is_insn (const fragS *);
-static bfd_boolean get_frag_is_no_transform (fragS *);
-static void set_frag_is_specific_opcode (fragS *, bfd_boolean);
-static void set_frag_is_no_transform (fragS *, bfd_boolean);
-
 /* Import from elf32-xtensa.c in BFD library.  */
 
 extern char *xtensa_get_property_section_name (asection *, const char *);
@@ -546,10 +518,9 @@ static void set_expr_symbol_offset_diff
 bfd_boolean expr_is_equal (expressionS *, expressionS *);
 static void copy_expr (expressionS *, const expressionS *);
 
-#ifdef XTENSA_SECTION_RENAME
+/* Section renaming.  */
+
 static void build_section_rename (const char *);
-static void add_section_rename (char *, char *);
-#endif
 
 
 /* ISA imported from bfd.  */
@@ -676,9 +647,7 @@ enum
 
   option_no_workarounds,
 
-#ifdef XTENSA_SECTION_RENAME
   option_rename_section_name,
-#endif
 
   option_prefer_l32r,
   option_prefer_const16,
@@ -745,9 +714,7 @@ struct option md_longopts[] =
   { "workaround-close-loop-end", no_argument, NULL,
     option_workaround_close_loop_end },
 
-#ifdef XTENSA_SECTION_RENAME
   { "rename-section", required_argument, NULL, option_rename_section_name },
-#endif /* XTENSA_SECTION_RENAME */
 
   { "link-relax", no_argument, NULL, option_link_relax },
   { "no-link-relax", no_argument, NULL, option_no_link_relax },
@@ -866,11 +833,9 @@ md_parse_option (int c, char *arg)
       warn_unaligned_branch_targets = TRUE;
       return 1;
 
-#ifdef XTENSA_SECTION_RENAME
     case option_rename_section_name:
       build_section_rename (arg);
       return 1;
-#endif /* XTENSA_SECTION_RENAME */
 
     case 'Q':
       /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
@@ -938,18 +903,14 @@ md_show_usage (FILE *stream)
 {
   fputs ("\n\
 Xtensa options:\n\
---[no-]text-section-literals\n\
-                        [Do not] put literals in the text section\n\
---[no-]absolute-literals\n\
-                        [Do not] default to use non-PC-relative literals\n\
---[no-]target-align     [Do not] try to align branch targets\n\
---[no-]longcalls        [Do not] emit 32-bit call sequences\n\
---[no-]transform        [Do not] transform instructions\n"
-#ifdef XTENSA_SECTION_RENAME
-"--rename-section old=new(:old1=new1)*\n\
-                        Rename section 'old' to 'new'\n"
-#endif /* XTENSA_SECTION_RENAME */
-        , stream);
+  --[no-]text-section-literals\n\
+                          [Do not] put literals in the text section\n\
+  --[no-]absolute-literals\n\
+                          [Do not] default to use non-PC-relative literals\n\
+  --[no-]target-align     [Do not] try to align branch targets\n\
+  --[no-]longcalls        [Do not] emit 32-bit call sequences\n\
+  --[no-]transform        [Do not] transform instructions\n\
+  --rename-section old=new Rename section 'old' to 'new'\n", stream);
 }
 
 \f
@@ -1585,7 +1546,7 @@ xtensa_literal_prefix (char const *start, int len)
       strcpy (newname4 + suffix_pos, ".lit4");
     }
 
-  /* Note that retrieve_literal_seg does not create a segment if
+  /* Note that cache_literal_section does not create a segment if
      it already exists.  */
   default_lit_sections.lit_seg = NULL;
   default_lit_sections.lit4_seg = NULL;
@@ -1605,7 +1566,6 @@ static void
 xtensa_frequency_pseudo (int ignored ATTRIBUTE_UNUSED)
 {
   float fall_through_f, target_f;
-  subseg_map *seginfo;
 
   fall_through_f = (float) strtod (input_line_pointer, &input_line_pointer);
   if (fall_through_f < 0)
@@ -1623,9 +1583,7 @@ xtensa_frequency_pseudo (int ignored ATTRIBUTE_UNUSED)
       return;
     }
 
-  seginfo = get_subseg_info (now_seg, now_subseg);
-  seginfo->cur_target_freq = target_f;
-  seginfo->cur_total_freq = target_f + fall_through_f;
+  set_subseg_freq (now_seg, now_subseg, target_f + fall_through_f, target_f);
 
   demand_empty_rest_of_line ();
 }
@@ -2686,67 +2644,6 @@ is_direct_call_opcode (xtensa_opcode opcode)
 }
 
 
-/* Return TRUE if the opcode is an entry opcode.  This is used because
-   "entry" adds an implicit ".align 4" and also the entry instruction
-   has an extra check for an operand value.  */
-
-static bfd_boolean
-is_entry_opcode (xtensa_opcode opcode)
-{
-  if (opcode == XTENSA_UNDEFINED)
-    return FALSE;
-
-  return (opcode == xtensa_entry_opcode);
-}
-
-
-/* Return TRUE if the opcode is a movi or movi.n opcode.  This is 
-   so we can relax "movi aX, foo" in the front end.  */
-
-static bfd_boolean
-is_movi_opcode (xtensa_opcode opcode)
-{
-  if (opcode == XTENSA_UNDEFINED)
-    return FALSE;
-
-  return (opcode == xtensa_movi_opcode) 
-    || (opcode == xtensa_movi_n_opcode);
-}
-
-
-static bfd_boolean
-is_the_loop_opcode (xtensa_opcode opcode)
-{
-  if (opcode == XTENSA_UNDEFINED)
-    return FALSE;
-
-  return (opcode == xtensa_loop_opcode);
-}
-
-
-static bfd_boolean
-is_jx_opcode (xtensa_opcode opcode)
-{
-  if (opcode == XTENSA_UNDEFINED)
-    return FALSE;
-
-  return (opcode == xtensa_jx_opcode);
-}
-
-
-/* Return TRUE if the opcode is a retw or retw.n.
-   Needed to add nops to avoid a hardware interlock issue.  */
-
-static bfd_boolean
-is_windowed_return_opcode (xtensa_opcode opcode)
-{
-  if (opcode == XTENSA_UNDEFINED)
-    return FALSE;
-
-  return (opcode == xtensa_retw_opcode || opcode == xtensa_retw_n_opcode);
-}
-
-
 /* Convert from BFD relocation type code to slot and operand number.
    Returns non-zero on failure.  */
 
@@ -4369,6 +4266,7 @@ xg_add_opcode_fix (TInsn *tinsn,
   fmt_length = xtensa_format_length (xtensa_default_isa, fmt);
   the_fix = fix_new_exp (fragP, offset, fmt_length, expr,
                         howto->pc_relative, reloc);
+  the_fix->fx_no_overflow = 1;
 
   if (expr->X_add_symbol
       && (S_IS_EXTERNAL (expr->X_add_symbol)
@@ -4638,7 +4536,7 @@ next_frag_format_size (const fragS *fragP)
    switch its state so it will instantiate a NOP.  */
 
 static void
-update_next_frag_state (fragS *fragP, bfd_boolean unreachable)
+update_next_frag_state (fragS *fragP)
 {
   fragS *next_fragP = fragP->fr_next;
   fragS *new_target = NULL;
@@ -4666,36 +4564,17 @@ update_next_frag_state (fragS *fragP, bfd_boolean unreachable)
              && (new_target->fr_subtype == RELAX_MAYBE_DESIRE_ALIGN
                  || new_target->fr_subtype == RELAX_DESIRE_ALIGN));
     }
-  if (unreachable)
-    {
-      if (align_targets)
-       {
-         next_fragP->fr_subtype = RELAX_UNREACHABLE;
-         next_fragP->tc_frag_data.is_unreachable = TRUE;
-         new_target->fr_subtype = RELAX_DESIRE_ALIGN;
-         new_target->tc_frag_data.is_branch_target = TRUE;
-       }
-      while (next_fragP && next_fragP->fr_fix == 0)
-       {
-         if (next_fragP->fr_type == rs_machine_dependent
-             && next_fragP->fr_subtype == RELAX_LOOP_END)
-           {
-             next_fragP->fr_subtype = RELAX_LOOP_END_ADD_NOP;
-             return;
-           }
 
-         next_fragP = next_fragP->fr_next;
-       }
-    }
-  else
+  while (next_fragP && next_fragP->fr_fix == 0)
     {
-      if (align_targets)
+      if (next_fragP->fr_type == rs_machine_dependent
+         && next_fragP->fr_subtype == RELAX_LOOP_END)
        {
-         next_fragP->fr_subtype = RELAX_MAYBE_UNREACHABLE;
-         next_fragP->tc_frag_data.is_unreachable = FALSE;
-         new_target->fr_subtype = RELAX_MAYBE_DESIRE_ALIGN;
-         new_target->tc_frag_data.is_branch_target = FALSE;
+         next_fragP->fr_subtype = RELAX_LOOP_END_ADD_NOP;
+         return;
        }
+
+      next_fragP = next_fragP->fr_next;
     }
 }
 
@@ -5231,7 +5110,7 @@ xtensa_frob_label (symbolS *sym)
       && !is_unaligned_label (sym)
       && !generating_literals)
     {
-      float freq = get_subseg_info (now_seg, now_subseg)->cur_target_freq;
+      float freq = get_subseg_target_freq (now_seg, now_subseg);
       xtensa_set_frag_assembly_state (frag_now);
 
       /* The only time this type of frag grows is when there is a
@@ -5459,7 +5338,7 @@ md_assemble (char *str)
   xg_add_branch_and_loop_targets (&orig_insn);
 
   /* Special-case for "entry" instruction.  */
-  if (is_entry_opcode (orig_insn.opcode))
+  if (orig_insn.opcode == xtensa_entry_opcode)
     {
       /* Check that the third opcode (#2) is >= 16.  */
       if (orig_insn.ntok >= 3)
@@ -5511,7 +5390,7 @@ void
 xtensa_handle_align (fragS *fragP)
 {
   if (linkrelax
-      && !get_frag_is_literal (fragP)
+      && ! fragP->tc_frag_data.is_literal
       && (fragP->fr_type == rs_align
          || fragP->fr_type == rs_align_code)
       && fragP->fr_address + fragP->fr_fix > 0
@@ -5810,7 +5689,7 @@ md_atof (int type, char *litP, int *sizeP)
 int
 md_estimate_size_before_relax (fragS *fragP, segT seg ATTRIBUTE_UNUSED)
 {
-  return fragP->tc_frag_data.text_expansion[0];
+  return total_frag_text_expansion (fragP);
 }
 
 
@@ -6135,7 +6014,7 @@ opcode_funcUnit_use_stage (void *data, xtensa_opcode opcode, int idx)
    solely whether the hardware is available to execute the given
    instructions together.  It also doesn't check if the tinsns 
    write the same state, or access the same tieports.  That is
-   checked by check_t1_t2_read_write.  */
+   checked by check_t1_t2_reads_and_writes.  */
 
 static bfd_boolean
 resources_conflict (vliw_insn *vinsn)
@@ -6191,7 +6070,10 @@ finish_vinsn (vliw_insn *vinsn)
   int line;
 
   if (find_vinsn_conflicts (vinsn))
-    return;
+    {
+      xg_clear_vinsn (vinsn);
+      return;
+    }
 
   /* First, find a format that works.  */
   if (vinsn->format == XTENSA_UNDEFINED)
@@ -6448,7 +6330,7 @@ find_vinsn_conflicts (vliw_insn *vinsn)
 }
 
 
-/* Check how the result registers of t1 and t2 relate.
+/* Check how the state used by t1 and t2 relate.
    Cases found are:
 
    case A: t1 reads a register t2 writes (an antidependency within a bundle)
@@ -6458,7 +6340,7 @@ find_vinsn_conflicts (vliw_insn *vinsn)
            bundle)
    case D: t1 writes a state that t2 also writes
    case E: t1 writes a tie queue that t2 also writes
-   case F: two volatile queue writes
+   case F: two volatile queue accesses
 */
 
 static char
@@ -6581,18 +6463,24 @@ check_t1_t2_reads_and_writes (TInsn *t1, TInsn *t2)
     {
       xtensa_interface t2_int
        = xtensa_interfaceOperand_interface (isa, t2->opcode, j);
+      int t2_class = xtensa_interface_class_id (isa, t2_int);
+
       t2_inout = xtensa_interface_inout (isa, j);
-      if (xtensa_interface_has_side_effect (isa, t2_int) == 1 
-         && t2_inout != 'i')
+      if (xtensa_interface_has_side_effect (isa, t2_int) == 1)
        t2_volatile = TRUE;
+
       for (i = 0; i < t1_interfaces; i++)
        {
          xtensa_interface t1_int
            = xtensa_interfaceOperand_interface (isa, t1->opcode, j);
+         int t1_class = xtensa_interface_class_id (isa, t2_int);
+
          t1_inout = xtensa_interface_inout (isa, i);
-         if (xtensa_interface_has_side_effect (isa, t1_int) == 1 
-             && t1_inout != 'i')
+         if (xtensa_interface_has_side_effect (isa, t1_int) == 1)
            t1_volatile = TRUE;
+
+         if (t1_volatile && t2_volatile && (t1_class == t2_class))
+           return 'f';
          
          if (t1_int != t2_int)
            continue;
@@ -6613,9 +6501,6 @@ check_t1_t2_reads_and_writes (TInsn *t1, TInsn *t2)
            return 'e';
        }
     }
-
-  if (t1_volatile && t2_volatile)
-    return 'f';
   
   return conflict;
 }
@@ -6733,7 +6618,8 @@ relaxation_requirements (vliw_insn *vinsn)
        }
       else
        {
-         if (workaround_b_j_loop_end && is_jx_opcode (tinsn->opcode) 
+         if (workaround_b_j_loop_end
+             && tinsn->opcode == xtensa_jx_opcode
              && use_transform ())
            {
              /* Add 2 of these.  */
@@ -6818,7 +6704,9 @@ emit_single_op (TInsn *orig_insn)
      Because the scheduling and bundling characteristics of movi and 
      l32r or const16 are so different, we can do much better if we relax 
      it prior to scheduling and bundling, rather than after.  */
-  if (is_movi_opcode (orig_insn->opcode) && !cur_vinsn.inside_bundle
+  if ((orig_insn->opcode == xtensa_movi_opcode 
+       || orig_insn->opcode == xtensa_movi_n_opcode)
+      && !cur_vinsn.inside_bundle
       && (orig_insn->tok[1].X_op == O_symbol
          || orig_insn->tok[1].X_op == O_pltrel))
     xg_assembly_relax (&istack, orig_insn, now_seg, frag_now, 0, 1, 0);
@@ -6863,6 +6751,19 @@ emit_single_op (TInsn *orig_insn)
 }
 
 
+static int
+total_frag_text_expansion (fragS *fragP)
+{
+  int slot;
+  int total_expansion = 0;
+
+  for (slot = 0; slot < MAX_SLOTS; slot++)
+    total_expansion += fragP->tc_frag_data.text_expansion[slot];
+
+  return total_expansion;
+}
+
+
 /* Emit a vliw instruction to the current fragment.  */
 
 static void
@@ -6894,9 +6795,9 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
     }
 
   if (frag_now_fix () != 0
-      && (!get_frag_is_insn (frag_now)
+      && (! frag_now->tc_frag_data.is_insn
          || (vinsn_has_specific_opcodes (vinsn) && use_transform ())
-         || !use_transform () != get_frag_is_no_transform (frag_now)
+         || !use_transform () != frag_now->tc_frag_data.is_no_transform
          || (directive_state[directive_absolute_literals]
              != frag_now->tc_frag_data.use_absolute_literals)))
     {
@@ -6970,7 +6871,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
       xtensa_move_labels (frag_now, 0, FALSE);
     }
 
-  if (is_entry_opcode (vinsn->slots[0].opcode) 
+  if (vinsn->slots[0].opcode == xtensa_entry_opcode
       && !vinsn->slots[0].is_specific_opcode)
     {
       xtensa_mark_literal_pool_location ();
@@ -7034,7 +6935,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
     }
 
   if (vinsn_has_specific_opcodes (vinsn) && use_transform ())
-    set_frag_is_specific_opcode (frag_now, TRUE);
+    frag_now->tc_frag_data.is_specific_opcode = TRUE;
 
   if (finish_frag)
     {
@@ -7109,7 +7010,7 @@ xg_assemble_vliw_tokens (vliw_insn *vinsn)
   if (do_align_targets ()
       && xtensa_opcode_is_call (isa, vinsn->slots[0].opcode) == 1)
     {
-      float freq = get_subseg_info (now_seg, now_subseg)->cur_total_freq;
+      float freq = get_subseg_total_freq (now_seg, now_subseg);
       frag_now->tc_frag_data.is_insn = TRUE;
       frag_var (rs_machine_dependent, 4, (int) freq, RELAX_DESIRE_ALIGN,
                frag_now->fr_symbol, frag_now->fr_offset, NULL);
@@ -7348,8 +7249,11 @@ xtensa_mark_narrow_branches (void)
    use for alignment narrow branches that definitely will not expand to a
    jump and a branch.  These functions find and mark these cases.  */
 
-/* the range in bytes of a bnez.n and beqz.n */
-#define MAX_IMMED6 68
+/* The range in bytes of BNEZ.N and BEQZ.N.  The target operand is encoded
+   as PC + 4 + imm6, where imm6 is a 6-bit immediate ranging from 0 to 63.
+   We start counting beginning with the frag after the 2-byte branch, so the
+   maximum offset is (4 - 2) + 63 = 65.  */
+#define MAX_IMMED6 65
 
 static size_t unrelaxed_frag_max_size (fragS *);
 
@@ -7438,7 +7342,7 @@ xtensa_fix_a0_b_retw_frags (void)
            {
              if (next_instrs_are_b_retw (fragP))
                {
-                 if (get_frag_is_no_transform (fragP))
+                 if (fragP->tc_frag_data.is_no_transform)
                    as_bad (_("instruction sequence (write a0, branch, retw) may trigger hardware errata"));
                  else
                    relax_frag_add_nop (fragP);
@@ -7513,7 +7417,7 @@ next_instrs_are_b_retw (fragS *fragP)
   xtensa_format_get_slot (isa, fmt, 0, insnbuf, slotbuf);
   opcode = xtensa_opcode_decode (isa, fmt, 0, slotbuf);
 
-  if (is_windowed_return_opcode (opcode))
+  if (opcode == xtensa_retw_opcode || opcode == xtensa_retw_n_opcode)
     return TRUE;
 
   return FALSE;
@@ -7546,7 +7450,7 @@ xtensa_fix_b_j_loop_end_frags (void)
            {
              if (next_instr_is_loop_end (fragP))
                {
-                 if (get_frag_is_no_transform (fragP))
+                 if (fragP->tc_frag_data.is_no_transform)
                    as_bad (_("branching or jumping to a loop end may trigger hardware errata"));
                  else
                    relax_frag_add_nop (fragP);
@@ -7644,7 +7548,7 @@ xtensa_fix_close_loop_end_frags (void)
 
              if (min_bytes < REQUIRED_LOOP_DIVIDING_BYTES)
                {
-                 if (get_frag_is_no_transform (fragP))
+                 if (fragP->tc_frag_data.is_no_transform)
                    as_bad (_("loop end too close to another loop end may trigger hardware errata"));
                  else
                    {
@@ -7824,9 +7728,9 @@ xtensa_fix_short_loop_frags (void)
                  && (branch_before_loop_end (fragP->fr_next)
                      || (workaround_all_short_loops
                          && current_opcode != XTENSA_UNDEFINED
-                         && !is_the_loop_opcode (current_opcode))))
+                         && current_opcode != xtensa_loop_opcode)))
                {
-                 if (get_frag_is_no_transform (fragP))
+                 if (fragP->tc_frag_data.is_no_transform)
                    as_bad (_("loop containing less than three instructions may trigger hardware errata"));
                  else
                    relax_frag_add_nop (fragP);
@@ -8742,8 +8646,7 @@ find_address_of_next_align_frag (fragS **fragPP,
                  (*widens)++;
                  break;
                }
-             /* FIXME: shouldn't this add the expansion of all slots?  */
-             address += fragP->tc_frag_data.text_expansion[0];
+             address += total_frag_text_expansion (fragP);;
              break;
 
            case RELAX_IMMED:
@@ -9116,7 +9019,7 @@ relax_frag_immed (segT segP,
   if (estimate_only && xtensa_opcode_is_loop (isa, tinsn.opcode))
     return 0;
 
-  if (workaround_b_j_loop_end && !get_frag_is_no_transform (fragP))
+  if (workaround_b_j_loop_end && ! fragP->tc_frag_data.is_no_transform)
     branch_jmp_to_next = is_branch_jmp_to_next (&tinsn, fragP);
 
   negatable_branch = (xtensa_opcode_is_branch (isa, tinsn.opcode) == 1);
@@ -9203,13 +9106,8 @@ relax_frag_immed (segT segP,
        }
     }
 
-  /* FIXME: When a negatable branch expands and then contracts in a
-     subsequent pass, update_next_frag_state correctly updates the
-     type of the frag to RELAX_MAYBE_UNREACHABLE, but it doesn't undo
-     any expansion relax_frag_for_align may have expected it to.  For
-     now, change back to only call it when the branch expands.  */
   if (negatable_branch && istack.ninsn > 1)
-    update_next_frag_state (fragP, FALSE /* istack.ninsn > 1 */);      
+    update_next_frag_state (fragP);
 
   return this_text_diff;
 }
@@ -9487,7 +9385,7 @@ convert_frag_immed (segT segP,
 
   is_loop = xtensa_opcode_is_loop (xtensa_default_isa, orig_tinsn.opcode) == 1;
 
-  if (workaround_b_j_loop_end && !get_frag_is_no_transform (fragP))
+  if (workaround_b_j_loop_end && ! fragP->tc_frag_data.is_no_transform)
     branch_jmp_to_next = is_branch_jmp_to_next (&orig_tinsn, fragP);
 
   if (branch_jmp_to_next && !next_frag_is_loop_target (fragP))
@@ -9796,8 +9694,6 @@ fix_new_exp_in_seg (segT new_seg,
           label:
 */
 
-static offsetT get_expression_value (segT, expressionS *);
-
 static void
 convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
 {
@@ -9831,7 +9727,21 @@ convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
   addmi_offset += loop_offset;
 
   assert (tinsn->ntok == 2);
-  target = get_expression_value (segP, &tinsn->tok[1]);
+  if (tinsn->tok[1].X_op == O_constant)
+    target = tinsn->tok[1].X_add_number;
+  else if (tinsn->tok[1].X_op == O_symbol)
+    {
+      /* Find the fragment.  */
+      symbolS *sym = tinsn->tok[1].X_add_symbol;
+      assert (S_GET_SEGMENT (sym) == segP
+             || S_GET_SEGMENT (sym) == absolute_section);
+      target = (S_GET_VALUE (sym) + tinsn->tok[1].X_add_number);
+    }
+  else
+    {
+      as_bad (_("invalid expression evaluation type %d"), tinsn->tok[1].X_op);
+      target = 0;
+    }
 
   know (symbolP);
   know (symbolP->sy_frag);
@@ -9878,7 +9788,7 @@ convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
   for (next_fragP = fragP; next_fragP != NULL;
        next_fragP = next_fragP->fr_next)
     {
-      set_frag_is_no_transform (next_fragP, TRUE);
+      next_fragP->tc_frag_data.is_no_transform = TRUE;
       if (next_fragP->tc_frag_data.is_loop_target)
        target_count++;
       if (target_count == 2)
@@ -9886,27 +9796,27 @@ convert_frag_immed_finish_loop (segT segP, fragS *fragP, TInsn *tinsn)
     }
 }
 
+\f
+/* A map that keeps information on a per-subsegment basis.  This is
+   maintained during initial assembly, but is invalid once the
+   subsegments are smashed together.  I.E., it cannot be used during
+   the relaxation.  */
 
-static offsetT
-get_expression_value (segT segP, expressionS *exp)
+typedef struct subseg_map_struct
 {
-  if (exp->X_op == O_constant)
-    return exp->X_add_number;
-  if (exp->X_op == O_symbol)
-    {
-      /* Find the fragment.  */
-      symbolS *sym = exp->X_add_symbol;
+  /* the key */
+  segT seg;
+  subsegT subseg;
 
-      assert (S_GET_SEGMENT (sym) == segP
-             || S_GET_SEGMENT (sym) == absolute_section);
+  /* the data */
+  unsigned flags;
+  float total_freq;    /* fall-through + branch target frequency */
+  float target_freq;   /* branch target frequency alone */
+
+  struct subseg_map_struct *next;
+} subseg_map;
 
-      return (S_GET_VALUE (sym) + exp->X_add_number);
-    }
-  as_bad (_("invalid expression evaluation type %d"), exp->X_op);
-  return 0;
-}
 
-\f
 static subseg_map *sseg_map = NULL;
 
 static subseg_map *
@@ -9917,20 +9827,25 @@ get_subseg_info (segT seg, subsegT subseg)
   for (subseg_e = sseg_map; subseg_e; subseg_e = subseg_e->next)
     {
       if (seg == subseg_e->seg && subseg == subseg_e->subseg)
-       return subseg_e;
+       break;
     }
-  
-  subseg_e = (subseg_map *) xmalloc (sizeof (subseg_map));
+  return subseg_e;
+}
+
+
+static subseg_map *
+add_subseg_info (segT seg, subsegT subseg)
+{
+  subseg_map *subseg_e = (subseg_map *) xmalloc (sizeof (subseg_map));
   memset (subseg_e, 0, sizeof (subseg_map));
   subseg_e->seg = seg;
   subseg_e->subseg = subseg;
   subseg_e->flags = 0;
   /* Start off considering every branch target very important.  */
-  subseg_e->cur_target_freq = 1.0;
-  subseg_e->cur_total_freq = 1.0;
+  subseg_e->target_freq = 1.0;
+  subseg_e->total_freq = 1.0;
   subseg_e->next = sseg_map;
   sseg_map = subseg_e;
-  
   return subseg_e;
 }
 
@@ -9939,7 +9854,9 @@ static unsigned
 get_last_insn_flags (segT seg, subsegT subseg)
 {
   subseg_map *subseg_e = get_subseg_info (seg, subseg);
-  return subseg_e->flags;
+  if (subseg_e)
+    return subseg_e->flags;
+  return 0;
 }
 
 
@@ -9950,12 +9867,45 @@ set_last_insn_flags (segT seg,
                     bfd_boolean val)
 {
   subseg_map *subseg_e = get_subseg_info (seg, subseg);
+  if (! subseg_e)
+    subseg_e = add_subseg_info (seg, subseg);
   if (val)
     subseg_e->flags |= fl;
   else
     subseg_e->flags &= ~fl;
 }
 
+
+static float
+get_subseg_total_freq (segT seg, subsegT subseg)
+{
+  subseg_map *subseg_e = get_subseg_info (seg, subseg);
+  if (subseg_e)
+    return subseg_e->total_freq;
+  return 1.0;
+}
+
+
+static float
+get_subseg_target_freq (segT seg, subsegT subseg)
+{
+  subseg_map *subseg_e = get_subseg_info (seg, subseg);
+  if (subseg_e)
+    return subseg_e->target_freq;
+  return 1.0;
+}
+
+
+static void
+set_subseg_freq (segT seg, subsegT subseg, float total_f, float target_f)
+{
+  subseg_map *subseg_e = get_subseg_info (seg, subseg);
+  if (! subseg_e)
+    subseg_e = add_subseg_info (seg, subseg);
+  subseg_e->total_freq = total_f;
+  subseg_e->target_freq = target_f;
+}
+
 \f
 /* Segment Lists and emit_state Stuff.  */
 
@@ -10182,22 +10132,22 @@ xtensa_reorder_seg_list (seg_list *head, segT after)
 
 /* Push all the literal segments to the end of the gnu list.  */
 
-static segT get_last_sec (void);
-
 static void
 xtensa_reorder_segments (void)
 {
   segT sec;
-  segT last_sec;
+  segT last_sec = 0;
   int old_count = 0;
   int new_count = 0;
 
   for (sec = stdoutput->sections; sec != NULL; sec = sec->next)
-    old_count++;
+    {
+      last_sec = sec;
+      old_count++;
+    }
 
   /* Now that we have the last section, push all the literal
      sections to the end.  */
-  last_sec = get_last_sec ();
   xtensa_reorder_seg_list (literal_head, last_sec);
   xtensa_reorder_seg_list (init_literal_head, last_sec);
   xtensa_reorder_seg_list (fini_literal_head, last_sec);
@@ -10209,17 +10159,6 @@ xtensa_reorder_segments (void)
 }
 
 
-static segT
-get_last_sec (void)
-{
-  segT last_sec = stdoutput->sections;
-  while (last_sec->next != NULL)
-    last_sec = last_sec->next;
-
-  return last_sec;
-}
-
-
 /* Change the emit state (seg, subseg, and frag related stuff) to the
    correct location.  Return a emit_state which can be passed to
    xtensa_restore_emit_state to return to current fragment.  */
@@ -10328,7 +10267,7 @@ xtensa_switch_section_emit_state (emit_state *state,
   state->now_subseg = now_subseg;
   state->generating_literals = generating_literals;
   generating_literals++;
-  subseg_new (segment_name (new_now_seg), new_now_subseg);
+  subseg_set (new_now_seg, new_now_subseg);
 }
 
 
@@ -10338,89 +10277,53 @@ static void
 xtensa_restore_emit_state (emit_state *state)
 {
   generating_literals = state->generating_literals;
-  subseg_new (state->name, state->now_subseg);
+  subseg_set (state->now_seg, state->now_subseg);
 }
 
 
 /* Get a segment of a given name.  If the segment is already
    present, return it; otherwise, create a new one.  */
 
-static segT retrieve_literal_seg (seg_list *, const char *, bfd_boolean);
-
 static void
 cache_literal_section (seg_list *head,
                       const char *name,
-                      segT *seg,
+                      segT *pseg,
                       bfd_boolean is_code)
 {
   segT current_section = now_seg;
   int current_subsec = now_subseg;
+  segT seg;
 
-  if (*seg != 0)
+  if (*pseg != 0)
     return;
-  *seg = retrieve_literal_seg (head, name, is_code);
-  subseg_set (current_section, current_subsec);
-}
-
-
-/* Get a segment of a given name.  If the segment is already
-   present, return it; otherwise, create a new one.  */
 
-static segT seg_present (const char *);
-static void add_seg_list (seg_list *, segT);
-
-static segT
-retrieve_literal_seg (seg_list *head, const char *name, bfd_boolean is_code)
-{
-  segT ret = 0;
+  /* Check if the named section exists.  */
+  for (seg = stdoutput->sections; seg; seg = seg->next)
+    {
+      if (!strcmp (segment_name (seg), name))
+       break;
+    }
 
-  ret = seg_present (name);
-  if (!ret)
+  if (!seg)
     {
-      ret = subseg_new (name, (subsegT) 0);
+      /* Create a new literal section.  */
+      seg = subseg_new (name, (subsegT) 0);
       if (head)
-       add_seg_list (head, ret);
-      bfd_set_section_flags (stdoutput, ret, SEC_HAS_CONTENTS |
+       {
+         /* Add the newly created literal segment to the specified list.  */
+         seg_list *n = (seg_list *) xmalloc (sizeof (seg_list));
+         n->seg = seg;
+         n->next = head->next;
+         head->next = n;
+       }
+      bfd_set_section_flags (stdoutput, seg, SEC_HAS_CONTENTS |
                             SEC_READONLY | SEC_ALLOC | SEC_LOAD
                             | (is_code ? SEC_CODE : SEC_DATA));
-      bfd_set_section_alignment (stdoutput, ret, 2);
+      bfd_set_section_alignment (stdoutput, seg, 2);
     }
 
-  return ret;
-}
-
-
-/* Return a segment of a given name if it is present.  */
-
-static segT
-seg_present (const char *name)
-{
-  segT seg;
-  seg = stdoutput->sections;
-
-  while (seg)
-    {
-      if (!strcmp (segment_name (seg), name))
-       return seg;
-      seg = seg->next;
-    }
-
-  return 0;
-}
-
-
-/* Add a segment to a segment list.  */
-
-static void
-add_seg_list (seg_list *head, segT seg)
-{
-  seg_list *n;
-  n = (seg_list *) xmalloc (sizeof (seg_list));
-  assert (n);
-
-  n->seg = seg;
-  n->next = head->next;
-  head->next = n;
+  *pseg = seg;
+  subseg_set (current_section, current_subsec);
 }
 
 \f
@@ -10433,6 +10336,7 @@ add_seg_list (seg_list *head, segT seg)
 typedef bfd_boolean (*frag_predicate) (const fragS *);
 typedef void (*frag_flags_fn) (const fragS *, frag_flags *);
 
+static bfd_boolean get_frag_is_literal (const fragS *);
 static void xtensa_create_property_segments
   (frag_predicate, frag_predicate, const char *, xt_section_type);
 static void xtensa_create_xproperty_segments
@@ -10486,35 +10390,6 @@ get_frag_is_literal (const fragS *fragP)
 }
 
 
-static bfd_boolean
-get_frag_is_insn (const fragS *fragP)
-{
-  assert (fragP != NULL);
-  return fragP->tc_frag_data.is_insn;
-}
-
-
-static bfd_boolean
-get_frag_is_no_transform (fragS *fragP)
-{
-  return fragP->tc_frag_data.is_no_transform;
-}
-
-
-static void
-set_frag_is_specific_opcode (fragS *fragP, bfd_boolean is_specific_opcode)
-{
-  fragP->tc_frag_data.is_specific_opcode = is_specific_opcode;
-}
-
-static void
-set_frag_is_no_transform (fragS *fragP, bfd_boolean is_no_transform)
-{
-  fragP->tc_frag_data.is_no_transform = is_no_transform;
-}
-
-
 static void
 xtensa_create_property_segments (frag_predicate property_function,
                                 frag_predicate end_property_function,
@@ -12109,9 +11984,7 @@ copy_expr (expressionS *dst, const expressionS *src)
 }
 
 \f
-/* Support for Tensilica's "--rename-section" option.  */
-
-#ifdef XTENSA_SECTION_RENAME
+/* Support for the "--rename-section" option.  */
 
 struct rename_section_struct
 {
@@ -12123,17 +11996,22 @@ struct rename_section_struct
 static struct rename_section_struct *section_rename;
 
 
-/* Parse the string oldname=new_name:oldname2=new_name2
-   and call add_section_rename.  */
+/* Parse the string "oldname=new_name(:oldname2=new_name2)*" and add
+   entries to the section_rename list.  Note: Specifying multiple
+   renamings separated by colons is not documented and is retained only
+   for backward compatibility.  */
 
 static void
 build_section_rename (const char *arg)
 {
+  struct rename_section_struct *r;
   char *this_arg = NULL;
   char *next_arg = NULL;
 
-  for (this_arg = strdup (arg); this_arg != NULL; this_arg = next_arg)
+  for (this_arg = xstrdup (arg); this_arg != NULL; this_arg = next_arg)
     {
+      char *old_name, *new_name;
+
       if (this_arg)
        {
          next_arg = strchr (this_arg, ':');
@@ -12143,56 +12021,47 @@ build_section_rename (const char *arg)
              next_arg++;
            }
        }
-      {
-       char *old_name = this_arg;
-       char *new_name = strchr (this_arg, '=');
 
-       if (*old_name == '\0')
-         {
-           as_warn (_("ignoring extra '-rename-section' delimiter ':'"));
-           continue;
-         }
-       if (!new_name || new_name[1] == '\0')
-         {
-           as_warn (_("ignoring invalid '-rename-section' "
-                      "specification: '%s'"), old_name);
-           continue;
-         }
-       *new_name = '\0';
-       new_name++;
-       add_section_rename (old_name, new_name);
-      }
-    }
-}
+      old_name = this_arg;
+      new_name = strchr (this_arg, '=');
 
+      if (*old_name == '\0')
+       {
+         as_warn (_("ignoring extra '-rename-section' delimiter ':'"));
+         continue;
+       }
+      if (!new_name || new_name[1] == '\0')
+       {
+         as_warn (_("ignoring invalid '-rename-section' specification: '%s'"),
+                  old_name);
+         continue;
+       }
+      *new_name = '\0';
+      new_name++;
 
-static void
-add_section_rename (char *old_name, char *new_name)
-{
-  struct rename_section_struct *r = section_rename;
+      /* Check for invalid section renaming.  */
+      for (r = section_rename; r != NULL; r = r->next)
+       {
+         if (strcmp (r->old_name, old_name) == 0)
+           as_bad (_("section %s renamed multiple times"), old_name);
+         if (strcmp (r->new_name, new_name) == 0)
+           as_bad (_("multiple sections remapped to output section %s"),
+                   new_name);
+       }
 
-  /* Check for invalid section renaming.  */
-  for (r = section_rename; r != NULL; r = r->next)
-    {
-      if (strcmp (r->old_name, old_name) == 0)
-       as_bad (_("section %s renamed multiple times"), old_name);
-      if (strcmp (r->new_name, new_name) == 0)
-       as_bad (_("multiple sections remapped to output section %s"),
-               new_name);
+      /* Now add it.  */
+      r = (struct rename_section_struct *)
+       xmalloc (sizeof (struct rename_section_struct));
+      r->old_name = xstrdup (old_name);
+      r->new_name = xstrdup (new_name);
+      r->next = section_rename;
+      section_rename = r;
     }
-
-  /* Now add it.  */
-  r = (struct rename_section_struct *)
-    xmalloc (sizeof (struct rename_section_struct));
-  r->old_name = strdup (old_name);
-  r->new_name = strdup (new_name);
-  r->next = section_rename;
-  section_rename = r;
 }
 
 
-const char *
-xtensa_section_rename (const char *name)
+char *
+xtensa_section_rename (char *name)
 {
   struct rename_section_struct *r = section_rename;
 
@@ -12204,5 +12073,3 @@ xtensa_section_rename (const char *name)
 
   return name;
 }
-
-#endif /* XTENSA_SECTION_RENAME */
This page took 0.038503 seconds and 4 git commands to generate.