(*~\Глагол\приложкемяLink\МПГ2009 (компилируется, но НЕ раб.?)\~~~~~~~~~~~~~~~*)
(**)                                                     ОТДЕЛ Рег;
(****************************************************************************** 
 * НАЗНАЧЕНИЕ: распределение машинных регистров
 *   R0..первыйРОН-1 - стог регистровых переменных (растёт от R0)
 *   первыйРОН..R10  - стог регистров общего назначения (растёт от R10)
 ******************************************************************************)

ИСПОЛЬЗУЕТ
  Ошибка;

ПОСТ
  последнийРОН=10; (* последний доступный РОН *)
  (* назначение особых регистров, которые не участвуют в общем распределении *)
  FP-=11; (* указатель окна   *)
  IP =12; (* не используется  *)
  SP-=13; (* указатель стога  *)
  LR-=14; (* адрес возврата   *)
  PC-=15; (* счётчик команд   *)

ПЕР
  первыйРОН:ЦЕЛ;(* первый доступный РОН после регистровых переменных *)
  заняты:МНОЖ;  (* множество занятых регистров *)
  нужен:ЦЕЛ;    (* регистр, который требуется выдать в следующий раз *)

(******************************************************************************)
ЗАДАЧА Нужен-(нужен:ЦЕЛ);
(* выставляет нужный регистр *)
УКАЗ
  Рег.нужен:=нужен
КОН Нужен;

(******************************************************************************)
ЗАДАЧА ЗанятьРОН-(р+:ЦЕЛ);
(* занимает нужный или свободный РОН и записывает его номер в <р> *)
УКАЗ
  ЕСЛИ нужен # -1 ТО
    ЕСЛИ (нужен >= первыйРОН) И (нужен <= последнийРОН) ТО
      ЕСЛИ нужен В заняты ТО
        Ошибка.Отметить(Ошибка.НЕТ_РЕГИСТРОВ)
      КОН;
      заняты:=заняты+{нужен}
    КОН;
    р:=нужен;
    нужен:=-1;
    ВОЗВРАТ
  КОН;
  (* перебираем свободные РОНы *)
  ОТ р:=последнийРОН ДО первыйРОН ПО -1 ВЫП
    ЕСЛИ НЕ (р В заняты) ТО
      заняты:=заняты+{р};
      ВОЗВРАТ
    КОН
  КОН;
  Ошибка.Отметить(Ошибка.НЕТ_РЕГИСТРОВ)
КОН ЗанятьРОН;

(******************************************************************************)
ЗАДАЧА Заняты-():МНОЖ;
(* возвращает множество занятых регистров *)
УКАЗ
  ВОЗВРАТ заняты
КОН Заняты;

(******************************************************************************)
ЗАДАЧА ОсвободитьРОН-(р:ЦЕЛ);
(* освобождает РОН *)
УКАЗ
  ЕСЛИ (р >= первыйРОН) И (р <= последнийРОН) ТО
    заняты:=заняты-{р}
  КОН;
КОН ОсвободитьРОН;

(******************************************************************************)
ЗАДАЧА ОсвободитьВсеРОНы-;
(* освобождает все РОНы *)
УКАЗ
  заняты:=заняты-{первыйРОН..последнийРОН}
КОН ОсвободитьВсеРОНы;

(******************************************************************************)
ЗАДАЧА БудутЗаняты-(заняты:МНОЖ);
(* выставляет заняты регистры *)
УКАЗ
  Рег.заняты:=заняты
КОН БудутЗаняты;

(******************************************************************************)
ЗАДАЧА ЗанятьСледПер-():ЦЕЛ;
(* занимает 1 регистр под регистровую переменную *)
ПЕР
  р:ЦЕЛ;
УКАЗ
  р:=первыйРОН;
  ЕСЛИ (р В заняты) ИЛИ (р > последнийРОН) ТО
    Ошибка.Отметить(Ошибка.НЕТ_РЕГИСТРОВ_БЫСТРОЙ)
  КОН;
  УВЕЛИЧИТЬ(первыйРОН);
  заняты:=заняты+{р};
  ВОЗВРАТ р
КОН ЗанятьСледПер;

(******************************************************************************)
ЗАДАЧА ЗанятьПер-(п:ЦЕЛ);
(* занимает <п> регистров под регистровые переменные *)
ПЕР
  р:ЦЕЛ;
УКАЗ
  ПОКА п > 0 ВЫП
    р:=ЗанятьСледПер();
    УМЕНЬШИТЬ(п)
  КОН
КОН ЗанятьПер;

(******************************************************************************)
ЗАДАЧА ОсвободитьПредПер-;
(* освобождает предыдущий, занятый под регистровую переменную, регистр *)
УКАЗ
  УМЕНЬШИТЬ(первыйРОН);
  ПРОВЕРИТЬ(первыйРОН >= 0);
  заняты:=заняты-{первыйРОН}
КОН ОсвободитьПредПер;

(******************************************************************************)
ЗАДАЧА ОсвободитьПер-(п:ЦЕЛ);
(* освобождает <п> регистров, занятых под регистровые переменные *)
УКАЗ
  ПОКА п > 0 ВЫП
    ОсвободитьПредПер();
    УМЕНЬШИТЬ(п)
  КОН
КОН ОсвободитьПер;

(******************************************************************************)
ЗАДАЧА ОсвободитьВсеПер-;
(* освобождает все регистры, заняты под регистровые переменные *)
УКАЗ
  ОсвободитьПер(первыйРОН)
КОН ОсвободитьВсеПер;

(******************************************************************************)
ЗАДАЧА Обновить-;
УКАЗ
  заняты:={};
  нужен:=-1;
  первыйРОН:=0
КОН Обновить;

КОН Рег.
