# HG changeset patch # User Michael Spacefalcon # Date 1376889394 0 # Node ID ebe258a858139faf487b10fef8f2e5d5bef27b67 # Parent dd13211c9f104c03ab18484990d7c2ab5ff2f4db toolchain: binutils patch to emit the "short" form of Thumb->ARM call veneers diff -r dd13211c9f10 -r ebe258a85813 toolchain/binutils-patches/elf32-arm.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolchain/binutils-patches/elf32-arm.patch Mon Aug 19 05:16:34 2013 +0000 @@ -0,0 +1,62 @@ +# The present patch to the ARM ELF linking code in binutils (made against +# binutils-2.21.1a) is a hack that affects the generation of Thumb->ARM +# call veneers. The binutils linker can make these veneers in two forms: +# +# "Short" "Long" +# (16-bit) bx pc (16-bit) bx pc +# (16-bit) nop (16-bit) nop +# (32-bit) b dest (32-bit) ldr pc, [pc, #-4] +# (32-bit) .long target +# +# For code that's going to run on the Calypso ARM7 processor, the +# "short" form is the one we want: because of the way the address space +# is laid out, the range of an ARM branch instruction will always be +# sufficient for us, whereas the long version is more costly in terms +# of the number of cycles required, especially when executing from +# external memory. +# +# Unfortunately, the code which decides between these two forms +# (located in the arm_type_of_stub() function in bfd/elf32-arm.c) +# is broken. The original code (which you can see below in the +# "before" part of the patch hunk) exhibits two problems: +# +# 1. The distance that matters here is not from the original +# call point to the destination, but from the stub to +# the destination - and in this function we don't know +# where the stub will end up. +# +# 2. Because it's an ARM branch, the limits should be +# ARM_MAX_[BF]WD_BRANCH_OFFSET, not the THM_ ones. +# +# The 2nd problem would be trivial to fix, but the 1st one +# much less so: this function doesn't know where the stub +# will end up, and considering that for the present purpose +# of the FreeCalypso project always emitting the "short" +# version would be perfect, there is no justification for +# expending the time and effort to restructure the linker +# to do the proper relaxation for the case at hand. +# +# Therefore, the patch we apply is a hack: we simply force the +# use of the "short" form unconditionally. + +*** elf32-arm.c Wed May 11 07:29:12 2011 +--- elf32-arm-patched.c Mon Aug 19 03:24:38 2013 +*************** +*** 3203,3211 **** + : arm_stub_long_branch_v4t_thumb_arm); + + /* Handle v4t short branches. */ +! if ((stub_type == arm_stub_long_branch_v4t_thumb_arm) +! && (branch_offset <= THM_MAX_FWD_BRANCH_OFFSET) +! && (branch_offset >= THM_MAX_BWD_BRANCH_OFFSET)) + stub_type = arm_stub_short_branch_v4t_thumb_arm; + } + } +--- 3203,3209 ---- + : arm_stub_long_branch_v4t_thumb_arm); + + /* Handle v4t short branches. */ +! if (stub_type == arm_stub_long_branch_v4t_thumb_arm) + stub_type = arm_stub_short_branch_v4t_thumb_arm; + } + } diff -r dd13211c9f10 -r ebe258a85813 toolchain/build+install.sh --- a/toolchain/build+install.sh Sat Aug 17 19:29:48 2013 +0000 +++ b/toolchain/build+install.sh Mon Aug 19 05:16:34 2013 +0000 @@ -33,6 +33,8 @@ # binutils come first tar xjf $1/binutils-2.21.1a.tar.bz2 +# apply patches +patch binutils-2.21.1/bfd/elf32-arm.c < binutils-patches/elf32-arm.patch mkdir -p binutils-build cd binutils-build ../binutils-2.21.1/configure --prefix=$2 ${target_args} --disable-nls