21:46

RCA1802

тролль - это не только ценный жир, но и 3-4 легкоусвояемых коммента ежедневно
Чего только не выдумают на белом свете...

Есть такое чудо без перьев - процессор (микроконтроллер, по-современному) RCA1802
у него нет стандартных команд CALL / RET для вызова подпрограмм, вместо этого есть команда "назначить любой регистр (а их там 16) счётчиком инструкций"
Назначая другой регистр счётчиком инструкций, мы автоматически прыгаем на адрес, содержащийся в нём сейчас, и этот регистр дальше начинает автоматически инкрементироваться, указывая на текущую инструкцию.
Вызов процедуры и возврат производились этой самой инструкцией, так чтобы внешний код (вызывающий процедуру) работал с одним регистром в качестве счётчика инструкций, а внутренний код (тело процедуры) - с другим регистром.
Чтобы вызвать ту же процедуру повторно, её код должен быть зациклен (нам же нужно попасть на его начало).

А как же быть со вложенными вызовами и нормальными (незацикленными) процедурами?
Для этого обычные CALL и RET эмулировались программно.
Т.е, была подпрограмма, эмулирующая CALL, которая вызывалась описанным выше способом (через переключение на её счётчик инструкций), смотрела на следующие 2 байта во внешнем коде, интерпретировала их как адрес нужной процедуры, сохраняла в (программно эмулируемый) стек адрес возврата, переключалась на нужную подпрограмму.
И была подпрограмма, аналогично эмулирующая RET.

Итого по регистрам:
Для подпрограмм CALL и RET резервировались (программно) два регистра, указывающие на их код.
Плюс ещё регистр для эмуляции стека.
Плюс ещё регистр для счётчика инструкций (который работал вне процедур CALL и RET).
Итого накладные расходы в 4 регистра, которыми нельзя пользоваться для других целей (из них 2 - это указатель инструкций и указатель стека, т.е., накладные расходы, неизбежные в любой архитектуре).

Мне кажется, это красивое архитектурное решение.
"Микрокод" (грубо говоря, требуемое количество транзисторов) получается проще некуда. Для сравнения, аппаратное выполнение обычного CALL довольно сложное.
Для вызова нерекурсивных процедур стек не нужен (и аппаратно стек не поддерживается).
Вызов часто использующихся простых процедур производится проще и быстрее за счёт отсутствия сложной логики обычного CALL, просто роль счётчика инструкций передаётся другому регистру.

@темы: там, на неведомых дорожках припаян неведомый микроконтроллер, архитектура

Комментарии
14.06.2015 в 22:29

В MIPS тоже нет CALL`ов. Там используются jalr`ы, прыжок по адресу из регистра (в функцию, из функции).
В ARM для переходов в функцию используются бранчи, а обратно из функции может использоваться явная запись в регистр PC.
14.06.2015 в 23:21

тролль - это не только ценный жир, но и 3-4 легкоусвояемых коммента ежедневно
Trotil, да, некоторые микроконтроллерные архитектуры заточены под отсутствие стека
да, в некоторых архитектурах вместо CALL используется бранч, аппаратно запоминающий адрес возврата в каком-то регистре, и RET, аппаратно копирующий этот адрес обратно в PC, получается быстро и без стека, но при этом используются две разные инструкции.
в случае, когда используется прыжок по адресу из регистра (или прямое копирование в PC), нужно как-то где-то вручную запоминать адрес возврата, а это ещё инструкция
а в RCA вход в подпрограмму и выход из неё - это одна и та же инструкция, больше ничего не нужно. процессор устроен проще!
мне вот этот минимализм и понравился