This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
CBZ to the next instruction on ARM
- From: Mark Shinwell <shinwell at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 22 Mar 2007 15:43:14 +0000
- Subject: 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. */