PowerPC branches only have 24 bits available for the target offset, so if the text section gets too big, branches on one end won't be able to reach targets on the other. There's a longer sequence of instructions that can reach targets farther away (the offset is 32 bits instead of 24), but GCC doesn't use it by default unless you pass it the -mlongcall
option. However, even with this option on, GCC still generates short calls for certain functions, namely operator new
and operator delete
For example, given this code:
extern void foo();
int main(int argc, char** argv) {
foo();
new char;
}
A normal run of GCC will generate the assembly:
bl _Z3foov // void foo()
bl _Znwj // operator new(unsigned int)
Running GCC with the -mlongcall
option generates:
lis r9, _Z3foov@ha
addi r9, r9, _Z3foov@l
mtctr r9
bctrl
bl _Znwj
The first four instructions are a long call to foo()
, as expected, but the call to operator new
is unchanged. Calls to random libc and libstdc++ functions are all converted to long calls as expected. Why do operator new
and operator delete
calls still end up as bl
instructions? Is there any way to force GCC to make them long calls as well? I'm using GCC 4.7.2 on a 64-bit PowerPC Fedora machine (although I'm building 32-bit)