This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Track STO_MIPS16 flags per segment


Hello All,

I applied the appended patch, the STO_MIPS16 flag is now kept track of
in per-segment lists instead of a global one, this makes the results
of section switching in mips16 code more predictable.


Thiemo

2006-06-23  Thiemo Seufer  <ths@mips.com>
            David Ung  <davidu@mips.com>

	* config/tc-mips.h (TC_SEGMENT_INFO_TYPE): Declare per-segment
	label_list.
	* config/tc-mips.c (label_list): Define per-segment label_list.
	(mips_clear_insn_labels, mips_move_labels, mips16_mark_labels,
	append_insn, s_align, s_cons, s_float_cons, s_gpword, s_gpdword,
	mips_from_file_after_relocs, mips_define_label): Use per-segment
	label_list.


Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.344
diff -u -p -r1.344 tc-mips.c
--- gas/config/tc-mips.c	22 Jun 2006 14:09:40 -0000	1.344
+++ gas/config/tc-mips.c	23 Jun 2006 15:58:50 -0000
@@ -1168,8 +1168,8 @@ struct insn_label_list
   symbolS *label;
 };
 
-static struct insn_label_list *insn_labels;
 static struct insn_label_list *free_insn_labels;
+#define label_list tc_segment_info_data
 
 static void mips_clear_insn_labels (void);
 
@@ -1177,12 +1177,19 @@ static inline void
 mips_clear_insn_labels (void)
 {
   register struct insn_label_list **pl;
+  segment_info_type *si;
 
-  for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
-    ;
-  *pl = insn_labels;
-  insn_labels = NULL;
+  if (now_seg)
+    {
+      for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next)
+	;
+      
+      si = seg_info (now_seg);
+      *pl = si->label_list;
+      si->label_list = NULL;
+    }
 }
+
 
 static char *expr_end;
 
@@ -2115,10 +2122,11 @@ reg_needs_delay (unsigned int reg)
 static void
 mips_move_labels (void)
 {
+  segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l;
   valueT val;
 
-  for (l = insn_labels; l != NULL; l = l->next)
+  for (l = si->label_list; l != NULL; l = l->next)
     {
       assert (S_GET_SEGMENT (l->label) == now_seg);
       symbol_set_frag (l->label, frag_now);
@@ -2141,21 +2149,22 @@ mips_move_labels (void)
 static void
 mips16_mark_labels (void)
 {
-  if (mips_opts.mips16)
-    {
-      struct insn_label_list *l;
-      valueT val;
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l;
 
-      for (l = insn_labels; l != NULL; l = l->next)
-	{
-#ifdef OBJ_ELF
-	  if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
-	    S_SET_OTHER (l->label, STO_MIPS16);
+  if (!mips_opts.mips16)
+    return;
+
+  for (l = si->label_list; l != NULL; l = l->next)
+   {
+      symbolS *label = l->label;
+
+#if defined(OBJ_ELF) || defined(OBJ_MAYBE_ELF)
+      if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
+	S_SET_OTHER (label, STO_MIPS16);
 #endif
-	  val = S_GET_VALUE (l->label);
-	  if ((val & 1) == 0)
-	    S_SET_VALUE (l->label, val + 1);
-	}
+      if ((S_GET_VALUE (label) & 1) == 0)
+	S_SET_VALUE (label, S_GET_VALUE (label) | 1);
     }
 }
 
@@ -2483,6 +2492,7 @@ append_insn (struct mips_cl_insn *ip, ex
   unsigned long prev_pinfo, pinfo;
   relax_stateT prev_insn_frag_type = 0;
   bfd_boolean relaxed_branch = FALSE;
+  segment_info_type *si = seg_info (now_seg);
 
   /* Mark instruction labels in mips16 mode.  */
   mips16_mark_labels ();
@@ -2899,7 +2909,7 @@ append_insn (struct mips_cl_insn *ip, ex
 		 whether there is a label on this instruction.  If
 		 there are any branches to anything other than a
 		 label, users must use .set noreorder.  */
-	      || insn_labels != NULL
+	      || si->label_list != NULL
 	      /* If the previous instruction is in a variant frag
 		 other than this branch's one, we cannot do the swap.
 		 This does not apply to the mips16, which uses variant
@@ -11966,9 +11976,11 @@ s_align (int x ATTRIBUTE_UNUSED)
     temp_fill = 0;
   if (temp)
     {
+      segment_info_type *si = seg_info (now_seg);
+      struct insn_label_list *l = si->label_list;
+      /* Auto alignment should be switched on by next section change */
       auto_align = 1;
-      mips_align (temp, (int) temp_fill,
-		  insn_labels != NULL ? insn_labels->label : NULL);
+      mips_align (temp, (int) temp_fill, l != NULL ? l->label : NULL);
     }
   else
     {
@@ -12121,9 +12133,11 @@ mips_enable_auto_align (void)
 static void
 s_cons (int log_size)
 {
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l = si->label_list;
   symbolS *label;
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (log_size > 0 && auto_align)
     mips_align (log_size, 0, label);
@@ -12134,9 +12148,11 @@ s_cons (int log_size)
 static void
 s_float_cons (int type)
 {
+  segment_info_type *si = seg_info (now_seg);
+  struct insn_label_list *l = si->label_list;
   symbolS *label;
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  label = l != NULL ? l->label : NULL;
 
   mips_emit_delays ();
 
@@ -12811,6 +12827,8 @@ s_gpvalue (int ignore ATTRIBUTE_UNUSED)
 static void
 s_gpword (int ignore ATTRIBUTE_UNUSED)
 {
+  segment_info_type *si;
+  struct insn_label_list *l;
   symbolS *label;
   expressionS ex;
   char *p;
@@ -12822,7 +12840,9 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  si = seg_info (now_seg);
+  l = si->label_list;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
     mips_align (2, 0, label);
@@ -12847,6 +12867,8 @@ s_gpword (int ignore ATTRIBUTE_UNUSED)
 static void
 s_gpdword (int ignore ATTRIBUTE_UNUSED)
 {
+  segment_info_type *si;
+  struct insn_label_list *l;
   symbolS *label;
   expressionS ex;
   char *p;
@@ -12858,7 +12880,9 @@ s_gpdword (int ignore ATTRIBUTE_UNUSED)
       return;
     }
 
-  label = insn_labels != NULL ? insn_labels->label : NULL;
+  si = seg_info (now_seg);
+  l = si->label_list;
+  label = l != NULL ? l->label : NULL;
   mips_emit_delays ();
   if (auto_align)
     mips_align (3, 0, label);
@@ -13997,6 +14021,7 @@ mips_frob_file_after_relocs (void)
 void
 mips_define_label (symbolS *sym)
 {
+  segment_info_type *si = seg_info (now_seg);
   struct insn_label_list *l;
 
   if (free_insn_labels == NULL)
@@ -14008,8 +14033,8 @@ mips_define_label (symbolS *sym)
     }
 
   l->label = sym;
-  l->next = insn_labels;
-  insn_labels = l;
+  l->next = si->label_list;
+  si->label_list = l;
 
 #ifdef OBJ_ELF
   dwarf2_emit_label (sym);
Index: gas/config/tc-mips.h
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.h,v
retrieving revision 1.44
diff -u -p -r1.44 tc-mips.h
--- gas/config/tc-mips.h	19 May 2006 12:34:09 -0000	1.44
+++ gas/config/tc-mips.h	23 Jun 2006 15:58:50 -0000
@@ -58,6 +58,9 @@ extern void mips_handle_align (struct fr
 
 #define MAX_MEM_FOR_RS_ALIGN_CODE  (1 + 2)
 
+struct insn_label_list;
+#define TC_SEGMENT_INFO_TYPE struct insn_label_list *
+
 /* Tell assembler that we have an itbl_mips.h header file to include.  */
 #define HAVE_ITBL_CPU
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]