Fix BLX(1) for Thumb

This commit is contained in:
Nick Clifton 2001-03-06 22:33:47 +00:00
parent f8f3c6cc37
commit 4f3c3dbb37
9 changed files with 105 additions and 31 deletions

View file

@ -1,3 +1,11 @@
2001-03-06 Nick Clifton <nickc@redhat.com>
* elf32-arm.h (elf32_arm_final_link_relocate): Clear bit zero
of offset in BLX(1) instruction.
* coff-arm.c (coff_arm_relocate_section): Clear bit zero of
offset in BLX(1) instruction.
Fix formatting.
2001-03-06 Nick Clifton <nickc@redhat.com>
* coff-arm.c (coff_arm_reloc_type_lookup): Add

View file

@ -1588,18 +1588,18 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
BFD_ASSERT (size == 4);
/* howto->pc_relative should be TRUE for type 14 BRANCH23 */
/* howto->pc_relative should be TRUE for type 14 BRANCH23. */
relocation -= (input_section->output_section->vma
+ input_section->output_offset);
/* howto->pcrel_offset should be TRUE for type 14 BRANCH23 */
/* howto->pcrel_offset should be TRUE for type 14 BRANCH23. */
relocation -= address;
/* No need to negate the relocation with BRANCH23. */
/* howto->complain_on_overflow == complain_overflow_signed for BRANCH23. */
/* howto->rightshift == 1 */
/* Drop unwanted bits from the value we are relocating to. */
/* Drop unwanted bits from the value we are relocating to. */
check = relocation >> howto->rightshift;
/* If this is a signed value, the rightshift just dropped
@ -1613,13 +1613,9 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
/* Get the value from the object file. */
if (bfd_big_endian (input_bfd))
{
add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
}
add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
else
{
add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
}
add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
/* Get the value from the object file with an appropriate sign.
The expression involving howto->src_mask isolates the upper
@ -1629,18 +1625,16 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
can not get the upper bit, but that does not matter since
signed_add needs no adjustment to become negative in that
case. */
signed_add = add;
if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
/* howto->bitpos == 0 */
/* Add the value from the object file, shifted so that it is a
straight number. */
/* howto->bitpos == 0 */
signed_check += signed_add;
relocation += signed_add;
relocation += signed_add;
BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
@ -1649,21 +1643,26 @@ coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
|| signed_check < reloc_signed_min)
overflow = true;
/* Put RELOCATION into the correct bits: */
/* For the BLX(1) instruction remove bit 0 of the adjusted offset.
Bit 0 can only be set if the upper insn is at a half-word boundary,
since the destination address, an ARM instruction, must always be
on a word boundary. The semantics of the BLX (1) instruction,
however, are that bit 0 in the offset must always be 0, and the
corresponding bit 1 in the target address will be set from bit
1 of the source address. */
if ((x & 0x18000000) == 0x08000000)
relocation &= ~0x2;
/* Put the relocation into the correct bits. */
if (bfd_big_endian (input_bfd))
{
relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
}
relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
else
{
relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
}
relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
/* Add RELOCATION to the correct bits of X: */
/* Add the relocation to the correct bits of X. */
x = ((x & ~howto->dst_mask) | relocation);
/* Put the relocated value back in the object file: */
/* Put the relocated value back in the object file. */
bfd_put_32 (input_bfd, x, location);
rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;

View file

@ -1434,6 +1434,17 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff);
lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff);
if (r_type == R_ARM_THM_XPC22
&& ((lower_insn & 0x1800) == 0x0800))
/* Remove bit zero of the adjusted offset. Bit zero can only be
set if the upper insn is at a half-word boundary, since the
destination address, an ARM instruction, must always be on a
word boundary. The semantics of the BLX (1) instruction, however,
are that bit zero in the offset must always be zero, and the
corresponding bit one in the target address will be set from bit
one of the source address. */
lower_insn &= ~1;
/* Put the relocated value back in the object file: */
bfd_put_16 (input_bfd, upper_insn, hit_data);
bfd_put_16 (input_bfd, lower_insn, hit_data + 2);

View file

@ -1,3 +1,8 @@
2001-03-06 Nick Clifton <nickc@redhat.com>
* config/tc-arm.c (md_apply_fix3): Clear bit zero of offset in
BLX(1) instruction.
2001-03-06 Igor Shevlyakov <igor@windriver.com>
* config/tc-m68k.c : Add 5407 to archs[] table.

View file

@ -7149,6 +7149,15 @@ md_apply_fix3 (fixP, val, seg)
newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
/* Remove bit zero of the adjusted offset. Bit zero can only be
set if the upper insn is at a half-word boundary, since the
destination address, an ARM instruction, must always be on a
word boundary. The semantics of the BLX (1) instruction, however,
are that bit zero in the offset must always be zero, and the
corresponding bit one in the target address will be set from bit
one of the source address. */
newval2 &= ~1;
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
}

View file

@ -1,3 +1,9 @@
2001-03-06 Nick Clifton <nickc@redhat.com>
* arm-dis.c (print_insn_thumb): Compute destination address
of BLX(1) instruction by taking bit 1 from PC and not from bit
0 of the offset.
2001-03-06 Igor Shevlyakov <igor@windriver.com>
* m68k-dis.c (print_insn_m68k): Recognize Coldfire CPUs

View file

@ -668,15 +668,32 @@ print_insn_thumb (pc, info, given)
/* Special processing for Thumb 2 instruction BL sequence: */
if (!*c) /* Check for empty (not NULL) assembler string. */
{
long offset;
info->bytes_per_chunk = 4;
info->bytes_per_line = 4;
offset = BDISP23 (given);
if ((given & 0x10000000) == 0)
func (stream, "blx\t");
{
func (stream, "blx\t");
/* The spec says that bit 1 of the branch's destination
address comes from bit 1 of the instruction's
address and not from the offset in the instruction. */
if (offset & 0x1)
{
/* func (stream, "*malformed!* "); */
offset &= ~ 0x1;
}
offset |= ((pc & 0x2) >> 1);
}
else
func (stream, "bl\t");
info->print_address_func (BDISP23 (given) * 2 + pc + 4, info);
func (stream, "bl\t");
info->print_address_func (offset * 2 + pc + 4, info);
return 4;
}
else

View file

@ -1,3 +1,9 @@
2001-03-06 Nick Clifton <nickc@redhat.com>
* thumbemu.c (ARMul_ThumbDecode): Delete label bo_blx2.
Compute destination address of BLX(1) instruction by
taking bit 1 from PC and not from bit 0 of the offset.
2001-02-27 Nick Clifton <nickc@redhat.com>
* armvirt.c (GetWord): Add new parameter - check - to enable or

View file

@ -481,7 +481,6 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
}
/* Drop through. */
do_blx2: /* BLX instruction 2 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this
instruction. Also, it should only ever be matched with the
@ -514,17 +513,31 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
|((tinstr & (1 << 10)) ? 0xFF800000 : 0));
valid = t_branch; /* in-case we don't have the 2nd half */
tinstr = next_instr; /* move the instruction down */
pc += 2; /* point the pc at the 2nd half */
if (((tinstr & 0xF800) >> 11) != 31)
{
if (((tinstr & 0xF800) >> 11) == 29)
{
pc += 2;
goto do_blx2;
ARMword tmp = (pc + 2);
/* Bit one of the destination address comes from bit one of the
address of the first (H == 10) half of the instruction, not
from the offset in the instruction. */
state->Reg[15] = ((state->Reg[14]
+ ((tinstr & 0x07FE) << 1)
+ ((pc - 2) & 2))
& 0xFFFFFFFC);
CLEART;
state->Reg[14] = (tmp | 1);
valid = t_branch;
FLUSHPIPE;
}
break; /* exit, since not correct instruction */
else
/* Exit, since not correct instruction. */
pc -= 2;
break;
}
/* else we fall through to process the second half of the BL */
pc += 2; /* point the pc at the 2nd half */
case 31: /* BL instruction 2 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this