Ветки PowerPC имеют только 24 бита, доступные для целевого смещения, поэтому, если текстовая часть станет слишком большой, ветви на одном конце не смогут достичь целей на другом. Существует более длинная последовательность инструкций, которая может достигать целей, находящихся дальше (смещение составляет 32 бита вместо 24), но GCC не использует ее по умолчанию, если только вы не передадите ей параметр -mlongcall
. Однако даже при включенной этой опции GCC по-прежнему генерирует короткие вызовы определенных функций, а именно operator new
и operator delete
.
Например, учитывая этот код:
extern void foo();
int main(int argc, char** argv) {
foo();
new char;
}
Обычный запуск GCC сгенерирует сборку:
bl _Z3foov // void foo()
bl _Znwj // operator new(unsigned int)
Запуск GCC с параметром -mlongcall
генерирует:
lis r9, _Z3foov@ha
addi r9, r9, _Z3foov@l
mtctr r9
bctrl
bl _Znwj
Первые четыре инструкции представляют собой длинный вызов foo()
, как и ожидалось, но вызов operator new
не изменился. Все вызовы случайных функций libc и libstdc++ преобразуются в длинные вызовы, как и ожидалось. Почему вызовы operator new
и operator delete
по-прежнему заканчиваются инструкциями bl
? Есть ли способ заставить GCC делать им длинные звонки? Я использую GCC 4.7.2 на 64-битной машине PowerPC Fedora (хотя я собираю 32-битную)
void* operator new(std::size_t);
? - person aschepler   schedule 12.03.2013new char
не является прямым вызовомoperator new(1)
, что произойдет, если вы вызовете его напрямую? - person MSalters   schedule 12.03.2013bl
, потому что он видит, что значение, которое ему нужно будет вставить в поле смещения, слишком велико, поэтому он просто выдает ошибку - person Michael Mrozek   schedule 12.03.2013