имеется MIPS бинарник, исходный код на C, компилятор GNU C 2.9-что-то (версия где-то 96-98 года), платформа PSX.
В коде определена функция — декомпрессор LZ77 формата, состоящий из следующих блоков:
1. Аллокация памяти для несжатых данных
2. Помещение в регистры указателей на начало выделеной памяти и на начало сжатых данных
3. Собственно декомпрессия
В большинстве мест эта функция вызывается нормально, JAL'ом в начало пролога, но в одном месте в адресе вызова указано не начало, а адрес п.3, т.е. вызов происходит по следующему сценарию:
1. В регистры помещается адрес статического буффера и сжатых данных (т.е. пропускается этап аллокации внутри функции которая будет вызвана)
2. Вызов функции декомпрессии, но адрес вызова не в начало, а п.3
Я совершенно не понимаю, что такое могли написать оригинальные авторы кода, чтобы компилятор создал такой переход, тем более что во всех мануалах по MIPS которые я встречал чётко прописано что JAL должен быть совершён в начало пролога функции(хотя конечно никто не запрещает прописать любой адрес).
Что я попробовал:
1. Простое goto естественно не работает по причине области видимости меток.
2. longjmp/setjmp генерирует другой код, с явным вызовом этих функций.
3. Извращение со специфичным для GCC взятием указателя на метку создаёт похожий код, но всё-же вычисляет адрес куда прыгать, а не знает его уже заранее. Возможно, это я что-то делаю не так, но из-за особенности областей видимости сделать константный указатель на метку у меня не получается.
Что у меня пока не получается точно проверить такие теории:
1. Это какой-то очень хитрый инлайнинг.
2. Часть функции декомпрессии определена как макрос(например, но это пальцем в небо) и компилятор понял что этот код вставлен в два места и положил в бинарник его только один раз.
3. Ручками написанный asm в сишном исходнике, специально для этого случая.
Может быть кто-то встречал такое или может предложить что в C коде теоретически может к такому привести? Мне кажется, что в условиях сурового эмбеда авторы кода меньше всего хотели писать какие-то хитрые хаки ради вполне стандартной задачи, которую можно было решить просто разнесением функции декомпрессии на две, и это скорее всего оптимизация компилятора...