Fix Thumb2 bl range options.

2009-12-21  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
            Richard Earnshaw  <richard.earnshaw@arm.com>

        * config/tc-arm.c (encode_thumb2_b_bl_offset): New. Refactored
        from md_apply_fix.
        (md_apply_fix): Fixup range checks for Thumb2 version
        of unconditional calls. Call encode_thumb2_b_bl_offset for
        unconditional branches / function calls.
This commit is contained in:
Ramana Radhakrishnan 2009-12-21 12:56:41 +00:00
parent 1a7bd2debe
commit 4a42ebbc0e
2 changed files with 52 additions and 32 deletions

View File

@ -1,3 +1,12 @@
2009-12-21 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
Richard Earnshaw <richard.earnshaw@arm.com>
* config/tc-arm.c (encode_thumb2_b_bl_offset): New. Refactored
from md_apply_fix.
(md_apply_fix): Fixup range checks for Thumb2 version
of unconditional calls. Call encode_thumb2_b_bl_offset for
unconditional branches / function calls.
2009-12-19 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-i386.c (process_operands): Check vexvvvv instead

View File

@ -19536,6 +19536,31 @@ arm_optimize_expr (expressionS *l, operatorT op, expressionS *r)
return FALSE;
}
/* Encode Thumb2 unconditional branches and calls. The encoding
for the 2 are identical for the immediate values. */
static void
encode_thumb2_b_bl_offset (char * buf, offsetT value)
{
#define T2I1I2MASK ((1 << 13) | (1 << 11))
offsetT newval;
offsetT newval2;
addressT S, I1, I2, lo, hi;
S = (value >> 24) & 0x01;
I1 = (value >> 23) & 0x01;
I2 = (value >> 22) & 0x01;
hi = (value >> 12) & 0x3ff;
lo = (value >> 1) & 0x7ff;
newval = md_chars_to_number (buf, THUMB_SIZE);
newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
newval |= (S << 10) | hi;
newval2 &= ~T2I1I2MASK;
newval2 |= (((I1 ^ S) << 13) | ((I2 ^ S) << 11) | lo) ^ T2I1I2MASK;
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
}
void
md_apply_fix (fixS * fixP,
valueT * valP,
@ -20228,10 +20253,6 @@ md_apply_fix (fixS * fixP,
fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23;
#endif
if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch out of range"));
if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
@ -20239,17 +20260,25 @@ md_apply_fix (fixS * fixP,
1 of the base address. */
value = (value + 1) & ~ 1;
if (fixP->fx_done || !seg->use_rela_p)
{
offsetT newval2;
newval = md_chars_to_number (buf, THUMB_SIZE);
newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
newval |= (value & 0x7fffff) >> 12;
newval2 |= (value & 0xfff) >> 1;
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
{
if (!(ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2)))
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch out of range"));
}
else if ((value & ~0x1ffffff)
&& ((value & ~0x1ffffff) != ~0x1ffffff))
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("Thumb2 branch out of range"));
}
}
if (fixP->fx_done || !seg->use_rela_p)
encode_thumb2_b_bl_offset (buf, value);
break;
case BFD_RELOC_THUMB_PCREL_BRANCH25:
@ -20258,26 +20287,8 @@ md_apply_fix (fixS * fixP,
_("branch out of range"));
if (fixP->fx_done || !seg->use_rela_p)
{
offsetT newval2;
addressT S, I1, I2, lo, hi;
encode_thumb2_b_bl_offset (buf, value);
S = (value & 0x01000000) >> 24;
I1 = (value & 0x00800000) >> 23;
I2 = (value & 0x00400000) >> 22;
hi = (value & 0x003ff000) >> 12;
lo = (value & 0x00000ffe) >> 1;
I1 = !(I1 ^ S);
I2 = !(I2 ^ S);
newval = md_chars_to_number (buf, THUMB_SIZE);
newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
newval |= (S << 10) | hi;
newval2 |= (I1 << 13) | (I2 << 11) | lo;
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
}
break;
case BFD_RELOC_8: