2dxp:Спасибо за советы.
Всё-таки не удержусь от такого комментария:
Цитата
Это откуда ему "ТОЧНО известно" это? Вот представьте, что вы компилятор, вам дали обработчик прерывания, в нем есть вызов функции, но кроме вызова ничего нет - самой функции вы не видите, ее исходного кода у вас нет, есть только прототип, чтобы вы могли ее правильно вызвать. Все.
В приведённом мною выше примере вызываемая функция расположена прямо в том же модуле, что и процедура прерывания, а результат тот же. Одно дело, если компилятору в качестве одного из модулей проекта предоставляется уже скомпилированный объектный файл и заголовочный - в этом случае трудно делать какие-то предположения об используемых в каждой функции регистрах. Во многих случаях компилятору известен исходный код подключаемых модулей проекта. Почему бы не сделать дополнительную оптимизацию, тем более, что для прерываний это весьма актуально?
Мне кажется, это происходит из-за того, что компилятор и линкер - это две разные программы. Если бы был некий компилятор+линкер, оптимизировать было бы легче. Хотя для исключения сохранения лишних регистров в прерывании достаточно было бы передать из компилятора в линкер список используемых в функции регистров, а также список подфункций, вызываемых из функции.
А насчёт замечания про "call": мне кажется, что задача превращения части инструкций "call" в "rcall" для коротких переходов вполне решаемая для компилятора. Это позволило бы немного сократить код и увеличить скорость. И, кстати, проверил, в CodeVisionAVR в данном случае функция из прерывания вызывается по команде "rcall".
2Сергей Борщ:Цитата
Объявляйте их static (static inline, если компилятор позволяет) и выносите в заголовочный файл соответствующего модуля.
Если я правильно понял, Вы предлагаете в заголовочный файл вынести реализацию функции?
Я уже так и сделал, например, с функцией spi(). Однако, если данная функция должна иметь доступ к внутренним переменным модуля, возникают проблемы.