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]

[Xtensa] Correct relax a very unusual instruction sequence


On Xtensa, it is hard to imagine two consecutive zero-overhead-loop instructions as an actually useful construct, but it is legal according to the ISA, and therefore the assembler should handle relaxing them correctly. The attached patch, which I have committed, does that.

Sterling

2010-02-09 Sterling Augustine <sterling@tensilica.com>

	* config/tc-xtensa.c (RELAXED_LOOP_INSN_BYTES): New.
	(next_frag_pre_opcode_bytes): Use RELAXED_LOOP_INSN_BYTES.
	(xtensa_mark_zcl_first_insns): Rewrite to handle corner case.
Index: config/tc-xtensa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.c,v
retrieving revision 1.120
diff -u -p -r1.120 tc-xtensa.c
--- config/tc-xtensa.c	8 Feb 2010 18:45:05 -0000	1.120
+++ config/tc-xtensa.c	9 Feb 2010 19:26:22 -0000
@@ -4649,6 +4649,12 @@ next_frag_is_loop_target (const fragS *f
 }
 
 
+/* As specified in the relaxation table, when a loop instruction is
+   relaxed, there are 24 bytes between the loop instruction itself and
+   the first instruction in the loop.  */
+
+#define RELAXED_LOOP_INSN_BYTES 24
+
 static addressT
 next_frag_pre_opcode_bytes (const fragS *fragp)
 {
@@ -4671,7 +4677,7 @@ next_frag_pre_opcode_bytes (const fragS 
      been relaxed.  Note that we can assume that the LOOP
      instruction is in slot 0 because loops aren't bundleable.  */
   if (next_fragp->tc_frag_data.slot_subtypes[0] > RELAX_IMMED)
-      return get_expanded_loop_offset (next_opcode);
+      return get_expanded_loop_offset (next_opcode) + RELAXED_LOOP_INSN_BYTES;
 
   return 0;
 }
@@ -7401,9 +7407,36 @@ xtensa_mark_zcl_first_insns (void)
 		    || fragP->fr_subtype == RELAX_CHECK_ALIGN_NEXT_OPCODE))
 	      {
 		/* Find the loop frag.  */
-		fragS *targ_frag = next_non_empty_frag (fragP);
+		fragS *loop_frag = next_non_empty_frag (fragP);
 		/* Find the first insn frag.  */
-		targ_frag = next_non_empty_frag (targ_frag);
+		fragS *targ_frag = next_non_empty_frag (loop_frag);
+
+	      /* Handle a corner case that comes up in hardware
+		 diagnostics.  The original assembly looks like this:
+		 
+		 loop aX, LabelA
+		 <empty_frag>--not found by next_non_empty_frag
+		 loop aY, LabelB
+
+		 Depending on the start address, the assembler may or
+		 may not change it to look something like this:
+
+		 loop aX, LabelA
+		 nop--frag isn't empty anymore
+		 loop aY, LabelB
+
+		 So set up to check the alignment of the nop if it
+		 exists  */
+		while (loop_frag != targ_frag)
+		  {
+		    if (loop_frag->fr_type == rs_machine_dependent
+			&& (loop_frag->fr_subtype == RELAX_ALIGN_NEXT_OPCODE
+			    || loop_frag->fr_subtype 
+			    == RELAX_CHECK_ALIGN_NEXT_OPCODE))
+		      targ_frag = loop_frag;
+		    else
+		      loop_frag = loop_frag->fr_next;
+		  }
 
 		/* Of course, sometimes (mostly for toy test cases) a
 		   zero-cost loop instruction is the last in a section.  */

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