DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
};
-/* Thumb -> Thumb long branch stub. Used on architectures which
- support only this mode, or on V4T where it is expensive to switch
- to ARM. */
+/* Thumb -> Thumb long branch stub. Used on M-profile architectures. */
static const insn_sequence elf32_arm_stub_long_branch_thumb_only[] =
{
THUMB16_INSN(0xb401), /* push {r0} */
DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
};
+/* V4T Thumb -> Thumb long branch stub. Using the stack is not
+ allowed. */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
+ {
+ THUMB16_INSN(0x4778), /* bx pc */
+ THUMB16_INSN(0x46c0), /* nop */
+ ARM_INSN(0xe59fc000), /* ldr ip, [pc, #0] */
+ ARM_INSN(0xe12fff1c), /* bx ip */
+ DATA_WORD(0, R_ARM_ABS32, 0), /* dcd R_ARM_ABS32(X) */
+ };
+
/* V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
available. */
static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_arm[] =
DATA_WORD(0, R_ARM_REL32, -4), /* dcd R_ARM_REL32(X) */
};
-/* Thumb -> Thumb long branch stub, PIC. Used on architectures which
- support only this mode, or on V4T where it is expensive to switch
- to ARM. */
+/* Thumb -> Thumb long branch stub, PIC. Used on M-profile
+ architectures. */
static const insn_sequence elf32_arm_stub_long_branch_thumb_only_pic[] =
{
THUMB16_INSN(0xb401), /* push {r0} */
DATA_WORD(0, R_ARM_REL32, 4), /* dcd R_ARM_REL32(X) */
};
+/* V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not
+ allowed. */
+static const insn_sequence elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
+ {
+ THUMB16_INSN(0x4778), /* bx pc */
+ THUMB16_INSN(0x46c0), /* nop */
+ ARM_INSN(0xe59fc004), /* ldr ip, [pc, #4] */
+ ARM_INSN(0xe08fc00c), /* add ip, pc, ip */
+ ARM_INSN(0xe12fff1c), /* bx ip */
+ DATA_WORD(0, R_ARM_REL32, 0), /* dcd R_ARM_REL32(X) */
+ };
+
/* Section name for stubs is the associated section name plus this
string. */
#define STUB_SUFFIX ".stub"
arm_stub_long_branch_any_any,
arm_stub_long_branch_v4t_arm_thumb,
arm_stub_long_branch_thumb_only,
+ arm_stub_long_branch_v4t_thumb_thumb,
arm_stub_long_branch_v4t_thumb_arm,
arm_stub_short_branch_v4t_thumb_arm,
arm_stub_long_branch_any_arm_pic,
arm_stub_long_branch_v4t_arm_thumb_pic,
arm_stub_long_branch_v4t_thumb_arm_pic,
arm_stub_long_branch_thumb_only_pic,
+ arm_stub_long_branch_v4t_thumb_thumb_pic,
};
struct elf32_arm_stub_hash_entry
/* V5T and above. */
? arm_stub_long_branch_any_thumb_pic
/* On V4T, use Thumb code only. */
- : arm_stub_long_branch_thumb_only_pic)
+ : arm_stub_long_branch_v4t_thumb_thumb_pic)
/* non-PIC stubs. */
: ((globals->use_blx)
/* V5T and above. */
? arm_stub_long_branch_any_any
/* V4T. */
- : arm_stub_long_branch_thumb_only);
+ : arm_stub_long_branch_v4t_thumb_thumb);
}
else
{
template = elf32_arm_stub_long_branch_thumb_only;
template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only);
break;
+ case arm_stub_long_branch_v4t_thumb_thumb:
+ template = elf32_arm_stub_long_branch_v4t_thumb_thumb;
+ template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_thumb);
+ break;
case arm_stub_long_branch_v4t_thumb_arm:
template = elf32_arm_stub_long_branch_v4t_thumb_arm;
template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_arm);
template = elf32_arm_stub_long_branch_thumb_only_pic;
template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_thumb_only_pic);
break;
+ case arm_stub_long_branch_v4t_thumb_thumb_pic:
+ template = elf32_arm_stub_long_branch_v4t_thumb_thumb_pic;
+ template_size = ARRAY_SIZE (elf32_arm_stub_long_branch_v4t_thumb_thumb_pic);
+ break;
default:
BFD_FAIL ();
return FALSE;