Fix BLX(1) for Thumb
This commit is contained in:
parent
f8f3c6cc37
commit
4f3c3dbb37
9 changed files with 105 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue