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]

Re: [PATCH] MIPS/GAS: Correct ISA bit handling in backreferences


Richard Sandiford <rdsandiford@googlemail.com> writes:
> "Maciej W. Rozycki" <macro@codesourcery.com> writes:
>> 2012-09-21  Maciej W. Rozycki  <macro@codesourcery.com>
>>
>> 	gas/
>> 	* config/tc-mips.c (md_assemble): Add a call to mips_mark_labels.
>
> OK as far as it goes, but...
>
>> 	gas/testsuite/
>> 	* gas/mips/branch-swap-2.s: Make sure the ISA bit is clear in
>> 	the label used for calculation.
>
> ...not OK.  "." ought to evaluate to the same thing as a label
> on the current instruction.

Here's what I installed.  Adding a global like mips_assembling_insn
isn't pretty, but I think it's correct.

Richard


gas/
2012-09-23  Richard Sandiford  <rdsandiford@googlemail.com>
	    Maciej W. Rozycki  <macro@codesourcery.com>

	* config/tc-mips.h (mips_record_label): Delete.
	(mips_add_dot_label): Declare.
	(tc_new_dot_label): Use it.
	* config/tc-mips.c (mips_assembling_insn): New variable.
	(md_assemble): Call mips_mark_labels.  Set mips_assembling_insn
	while the main part of the function is executing.
	(mips_compressed_mark_label): New function, split out from...
	(mips_compressed_mark_labels): ...here.
	(append_insn): Don't call mips_mark_labels here.
	(mips_record_label): Make local.
	(mips_add_dot_label): New function.

gas/testsuite/
	* gas/mips/dot-1.s, gas/mips/dot-1.d, gas/mips/micromips@dot-1.d,
	gas/mips/mips16@dot-1.d: New test.
	* gas/mips/mips.exp: Run it.

Index: gas/config/tc-mips.h
===================================================================
--- gas/config/tc-mips.h	2012-09-23 11:14:52.323200330 +0100
+++ gas/config/tc-mips.h	2012-09-23 11:35:28.792164378 +0100
@@ -113,8 +113,8 @@ extern int mips_parse_long_option (const
 #define tc_frob_label(sym) mips_define_label (sym)
 extern void mips_define_label (symbolS *);
 
-#define tc_new_dot_label(sym) mips_record_label (sym)
-extern void mips_record_label (symbolS *);
+#define tc_new_dot_label(sym) mips_add_dot_label (sym)
+extern void mips_add_dot_label (symbolS *);
 
 #define tc_frob_file_before_adjust() mips_frob_file_before_adjust ()
 extern void mips_frob_file_before_adjust (void);
Index: gas/config/tc-mips.c
===================================================================
--- gas/config/tc-mips.c	2012-09-23 11:14:52.323200330 +0100
+++ gas/config/tc-mips.c	2012-09-23 11:36:41.927162251 +0100
@@ -1574,6 +1574,11 @@ mips_mark_labels (void)
 
 static unsigned int forced_insn_length;
 
+/* True if we are assembling an instruction.  All dot symbols defined during
+   this time should be treated as code labels.  */
+
+static bfd_boolean mips_assembling_insn;
+
 #ifdef OBJ_ELF
 /* The pdr segment for per procedure frame/regmask info.  Not used for
    ECOFF debugging.  */
@@ -2592,6 +2597,9 @@ md_assemble (char *str)
   offset_reloc[1] = BFD_RELOC_UNUSED;
   offset_reloc[2] = BFD_RELOC_UNUSED;
 
+  mips_mark_labels ();
+  mips_assembling_insn = TRUE;
+
   if (mips_opts.mips16)
     mips16_ip (str, &insn);
   else
@@ -2602,12 +2610,8 @@ md_assemble (char *str)
     }
 
   if (insn_error)
-    {
-      as_bad ("%s `%s'", insn_error, str);
-      return;
-    }
-
-  if (insn.insn_mo->pinfo == INSN_MACRO)
+    as_bad ("%s `%s'", insn_error, str);
+  else if (insn.insn_mo->pinfo == INSN_MACRO)
     {
       macro_start ();
       if (mips_opts.mips16)
@@ -2625,6 +2629,8 @@ md_assemble (char *str)
       else
 	append_insn (&insn, NULL, unused_reloc, FALSE);
     }
+
+  mips_assembling_insn = FALSE;
 }
 
 /* Convenience functions for abstracting away the differences between
@@ -2832,7 +2838,7 @@ s_is_linkonce (symbolS *sym, segT from_s
   return linkonce;
 }
 
-/* Mark instruction labels in MIPS16/microMIPS mode.  This permits the
+/* Mark MIPS16 or microMIPS instruction label LABEL.  This permits the
    linker to handle them specially, such as generating jalx instructions
    when needed.  We also make them odd for the duration of the assembly,
    in order to generate the right sort of code.  We will make them even
@@ -2841,36 +2847,39 @@ s_is_linkonce (symbolS *sym, segT from_s
    to make them odd again.  */
 
 static void
-mips_compressed_mark_labels (void)
+mips_compressed_mark_label (symbolS *label)
 {
-  segment_info_type *si = seg_info (now_seg);
-  struct insn_label_list *l;
-
   gas_assert (HAVE_CODE_COMPRESSION);
 
-  for (l = si->label_list; l != NULL; l = l->next)
-   {
-      symbolS *label = l->label;
-
 #if defined(OBJ_ELF) || defined(OBJ_MAYBE_ELF)
-      if (IS_ELF)
-	{
-	  if (mips_opts.mips16)
-	    S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
-	  else
-	    S_SET_OTHER (label, ELF_ST_SET_MICROMIPS (S_GET_OTHER (label)));
-	}
-#endif
-      if ((S_GET_VALUE (label) & 1) == 0
-	/* Don't adjust the address if the label is global or weak, or
-	   in a link-once section, since we'll be emitting symbol reloc
-	   references to it which will be patched up by the linker, and
-	   the final value of the symbol may or may not be MIPS16/microMIPS.  */
-	  && ! S_IS_WEAK (label)
-	  && ! S_IS_EXTERNAL (label)
-	  && ! s_is_linkonce (label, now_seg))
-	S_SET_VALUE (label, S_GET_VALUE (label) | 1);
+  if (IS_ELF)
+    {
+      if (mips_opts.mips16)
+	S_SET_OTHER (label, ELF_ST_SET_MIPS16 (S_GET_OTHER (label)));
+      else
+	S_SET_OTHER (label, ELF_ST_SET_MICROMIPS (S_GET_OTHER (label)));
     }
+#endif
+  if ((S_GET_VALUE (label) & 1) == 0
+      /* Don't adjust the address if the label is global or weak, or
+	 in a link-once section, since we'll be emitting symbol reloc
+	 references to it which will be patched up by the linker, and
+	 the final value of the symbol may or may not be MIPS16/microMIPS.  */
+      && !S_IS_WEAK (label)
+      && !S_IS_EXTERNAL (label)
+      && !s_is_linkonce (label, now_seg))
+    S_SET_VALUE (label, S_GET_VALUE (label) | 1);
+}
+
+/* Mark preceding MIPS16 or microMIPS instruction labels.  */
+
+static void
+mips_compressed_mark_labels (void)
+{
+  struct insn_label_list *l;
+
+  for (l = seg_info (now_seg)->label_list; l != NULL; l = l->next)
+    mips_compressed_mark_label (l->label);
 }
 
 /* End the current frag.  Make it a variant frag and record the
@@ -4031,8 +4040,6 @@ append_insn (struct mips_cl_insn *ip, ex
   if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION)
     fix_loongson2f (ip);
 
-  mips_mark_labels ();
-
   file_ase_mips16 |= mips_opts.mips16;
   file_ase_micromips |= mips_opts.micromips;
 
@@ -18405,7 +18412,7 @@ mips_frob_file_after_relocs (void)
    move it.  This also bumps the value of the symbol by 1 in compressed
    code.  */
 
-void
+static void
 mips_record_label (symbolS *sym)
 {
   segment_info_type *si = seg_info (now_seg);
@@ -18435,6 +18442,17 @@ mips_define_label (symbolS *sym)
   dwarf2_emit_label (sym);
 #endif
 }
+
+/* This function is called by tc_new_dot_label whenever a new dot symbol
+   is defined.  */
+
+void
+mips_add_dot_label (symbolS *sym)
+{
+  mips_record_label (sym);
+  if (mips_assembling_insn && HAVE_CODE_COMPRESSION)
+    mips_compressed_mark_label (sym);
+}
 
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
 
Index: gas/testsuite/gas/mips/dot-1.s
===================================================================
--- /dev/null	2012-08-19 20:42:12.842999468 +0100
+++ gas/testsuite/gas/mips/dot-1.s	2012-09-23 11:14:54.144200276 +0100
@@ -0,0 +1,18 @@
+	.ent	foo
+foo:
+	addiu	$4,.-foo
+	nop
+.L1:
+	nop
+	addiu	$4,.L2 - .
+	addiu	$4,. - .L1
+	addiu	$4,. - foo
+.L2:
+	addiu	$4,%lo(.L2 - .)
+	addiu	$4,%lo(.L3 - .)
+	addiu	$4,%lo(. - .L1)
+	addiu	$4,%lo(. - foo)
+	nop
+.L3:
+	nop
+	.end	foo
Index: gas/testsuite/gas/mips/dot-1.d
===================================================================
--- /dev/null	2012-08-19 20:42:12.842999468 +0100
+++ gas/testsuite/gas/mips/dot-1.d	2012-09-23 11:14:54.144200276 +0100
@@ -0,0 +1,20 @@
+#objdump: -dr --show-raw-insn
+#as: -32
+#name: MIPS dot-1
+#source: dot-1.s
+
+.*file format.*
+
+Disassembly .*
+
+0+0 <foo>:
+.*:	24840000 	addiu	a0,a0,0
+	\.\.\.
+.*:	2484000c 	addiu	a0,a0,12
+.*:	24840008 	addiu	a0,a0,8
+.*:	24840014 	addiu	a0,a0,20
+.*:	24840000 	addiu	a0,a0,0
+.*:	24840010 	addiu	a0,a0,16
+.*:	24840018 	addiu	a0,a0,24
+.*:	24840024 	addiu	a0,a0,36
+#pass
Index: gas/testsuite/gas/mips/micromips@dot-1.d
===================================================================
--- /dev/null	2012-08-19 20:42:12.842999468 +0100
+++ gas/testsuite/gas/mips/micromips@dot-1.d	2012-09-23 11:14:54.145200277 +0100
@@ -0,0 +1,21 @@
+#objdump: -dr --show-raw-insn
+#as: -32
+#name: MIPS dot-1
+#source: dot-1.s
+
+.*file format.*
+
+Disassembly .*
+
+0+0 <foo>:
+.*:	4c80      	addiu	a0,a0,0
+.*:	0c00      	nop
+.*:	0c00      	nop
+.*:	3084 0008 	addiu	a0,a0,8
+.*:	4c8c      	addiu	a0,a0,6
+.*:	6e46      	addiu	a0,a0,12
+.*:	3084 0000 	addiu	a0,a0,0
+.*:	3084 000e 	addiu	a0,a0,14
+.*:	3084 0012 	addiu	a0,a0,18
+.*:	3084 001a 	addiu	a0,a0,26
+#pass
Index: gas/testsuite/gas/mips/mips16@dot-1.d
===================================================================
--- /dev/null	2012-08-19 20:42:12.842999468 +0100
+++ gas/testsuite/gas/mips/mips16@dot-1.d	2012-09-23 11:14:54.146200277 +0100
@@ -0,0 +1,21 @@
+#objdump: -dr --show-raw-insn
+#as: -32
+#name: MIPS dot-1
+#source: dot-1.s
+
+.*file format.*
+
+Disassembly .*
+
+0+0 <foo>:
+.*:	4c00      	addiu	a0,0
+.*:	6500      	nop
+.*:	6500      	nop
+.*:	4c06      	addiu	a0,6
+.*:	4c04      	addiu	a0,4
+.*:	4c0a      	addiu	a0,10
+.*:	4c00      	addiu	a0,0
+.*:	f000 4c0e 	addiu	a0,14
+.*:	f000 4c0e 	addiu	a0,14
+.*:	f000 4c16 	addiu	a0,22
+#pass
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
--- gas/testsuite/gas/mips/mips.exp	2012-09-23 11:14:52.322200330 +0100
+++ gas/testsuite/gas/mips/mips.exp	2012-09-23 11:35:28.791164379 +0100
@@ -478,7 +478,8 @@ if { [istarget mips*-*-vxworks*] } {
     if { $no_micromips } {
 	mips_arch_destroy micromips
     }
-    
+
+    run_dump_test_arches "dot-1"	[mips_arch_list_matching mips1]
     run_dump_test_arches "abs"		[mips_arch_list_matching mips1]
     run_dump_test_arches "add"		[mips_arch_list_matching mips1]
     run_dump_test_arches "and"		[mips_arch_list_matching mips1]


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