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]

CBZ to the next instruction on ARM


Here's an ugly one I've had knocking around for a while.

It's actually illegal for a CBZ instruction on ARM to jump to the
next instruction.  This can cause problems because gcc's
branch length adjustment algorithm (as far as I can tell) does not
cope with branch instructions that actually have a _minimum_ range
as this one does.  In certain very unusual circumstances it is possible
for the compiler to emit code that has a CBZ to the next instruction,
which currently causes a failure.

I propose the application of the attached patch that rewrites
such bogus CBZ instructions to no-ops.  This isn't particularly
elegant, but does make this robust.  OK?

Mark

--


2007-03-23 Mark Shinwell <shinwell@codesourcery.com>


	gas/
	* config/tc-arm.c (md_apply_fix): Turn CZB instructions that
	attempt to jump to the next instruction into NOPs.


Index: gas/config/tc-arm.c =================================================================== RCS file: /cvs/src/src/gas/config/tc-arm.c,v retrieving revision 1.315 diff -U3 -p -r1.315 tc-arm.c --- gas/config/tc-arm.c 18 Mar 2007 16:21:27 -0000 1.315 +++ gas/config/tc-arm.c 22 Mar 2007 14:44:22 -0000 @@ -18101,16 +18101,29 @@ md_apply_fix (fixS * fixP,

     case BFD_RELOC_THUMB_PCREL_BRANCH7: /* CBZ */
       /* CBZ can only branch forward.  */
-      if (value & ~0x7e)
-       as_bad_where (fixP->fx_file, fixP->fx_line,
-                     _("branch out of range"));

-      if (fixP->fx_done || !seg->use_rela_p)
+      /* Attempts to use CBZ to branch to the next instruction
+         (which, strictly speaking, are prohibited) will be turned into
+         no-ops.  */
+      if (value == -2)
        {
          newval = md_chars_to_number (buf, THUMB_SIZE);
-         newval |= ((value & 0x3e) << 2) | ((value & 0x40) << 3);
+         newval = 0xbf00; /* NOP encoding T1 */
          md_number_to_chars (buf, newval, THUMB_SIZE);
        }
+      else
+       {
+         if (value & ~0x7e)
+           as_bad_where (fixP->fx_file, fixP->fx_line,
+                         _("branch out of range"));
+
+          if (fixP->fx_done || !seg->use_rela_p)
+           {
+             newval = md_chars_to_number (buf, THUMB_SIZE);
+             newval |= ((value & 0x3e) << 2) | ((value & 0x40) << 3);
+             md_number_to_chars (buf, newval, THUMB_SIZE);
+           }
+       }
       break;

case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch. */


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