/* Instruction printing code for the ARM
- Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
Modification by James G. Smith (jsmith@cygnus.co.uk)
}
break;
+ case 'B':
+ /* Print ARM V5 BLX(1) address: pc+25 bits. */
+ {
+ bfd_vma address;
+ bfd_vma offset = 0;
+
+ if (given & 0x00800000)
+ /* Is signed, hi bits should be ones. */
+ offset = (-1) ^ 0x00ffffff;
+
+ /* Offset is (SignExtend(offset field)<<2). */
+ offset += given & 0x00ffffff;
+ offset <<= 2;
+ address = offset + pc + 8;
+
+ if (given & 0x01000000)
+ /* H bit allows addressing to 2-byte boundaries. */
+ address += 2;
+
+ info->print_address_func (address, info);
+ }
+ break;
+
case 'C':
func (stream, "_");
if (given & 0x80000)
/* 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);
- func (stream, "bl\t");
-
- info->print_address_func (BDISP23 (given) * 2 + pc + 4, info);
+ if ((given & 0x10000000) == 0)
+ {
+ 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 (offset * 2 + pc + 4, info);
return 4;
}
else
given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
}
+ if (info->flags & INSN_HAS_RELOC)
+ /* If the instruction has a reloc associated with it, then
+ the offset field in the instruction will actually be the
+ addend for the reloc. (We are using REL type relocs).
+ In such cases, we can ignore the pc when computing
+ addresses, since the addend is not currently pc-relative. */
+ pc = 0;
+
if (is_thumb)
status = print_insn_thumb (pc, info, given);
else