Модель машины
При изложении алгоритмов генерации кода мы будем следовать некоторой модели машины, в основу которой положена система команд микропроцессора Motorola MC68020. В микропроцессоре имеется регистр - счетчик команд PC, 8 регистров данных и 8 адресных регистров.
В системе команд используются следующие способы адресации:
ABS - абсолютная: исполнительным адресом является значение адресного выражения.
IMM - непосредственный операнд: операндом команды
является константа, заданная в адресном выражении.
D - прямая адресация через регистр данных, записывается как Хn, операнд находится в регистре Хn.
А - прямая адресация через адресный регистр, записывается как An, операнд находится в регистре An.
INDIRECT - записывается как (An), адрес операнда находится в адресном регистре An.
POST - пост-инкрементная адресация, записывается как (Аn)+, исполнительный адрес есть значение адресного регистра An и после исполнения команды значение
этого регистра увеличивается на длину операнда.
PRE - пре-инкрементная адресация, записывается как -(Аn): перед исполнением операции содержимое адресного регистра An уменьшается на длину операнда, исполнительный адрес равен новому содержимому адресного регистра.
INDISP - косвенная адресация со смещением, записывается как (bd,An), исполнительный адрес вычисляется как (An)+d - содержимое An плюс d.
INDEX - косвенная адресация с индексом, записывается как (bd,An,Xn*sc), исполнительный адрес вычисляется как (An)+bd+(Xn)*sc - содержимое адресного
регистра + адресное смещение + содержимое индексного регистра, умноженное на sc.
INDIRPC - косвенная через PC (счетчик команд), записывается как (bd,PC), исполнительный адрес определяется выражением (PC)+bd.
INDEXPC - косвенная через PC со смещением, записывается как (bd,PC,Xn*sc), исполнительный адрес определяется выражением (PC)+bd+(Xn)*sc.
INDPRE - пре-косвенная через память, записывается как ([bd,An,sc*Xn],od) (схема вычисления адресов для этого и трех последующих способов адресации приведена ниже).
INDPOST - пост-косвенная через
память: ([bd,An],sc*Xn,od).
INDPREPC - пре-косвенная через PC: ([bd,PC,sc*Xn],od).
INDPOSTPC - пост-косвенная через PC: ([bd,PC],Xn,od).
Здесь bd - это 16- или 32- битная константа, называемая смещением, od - 16- или 32-битная литеральная константа, называемая внешним смещением. Эти способы адресации могут использоваться в упрощенных формах без смещений bd и/или od и без регистров An или Xn. Следующие примеры иллюстрируют косвенную постиндексную адресацию:
MOVE D0, ([A0]) MOVE D0, ([4,A0]) MOVE D0, ([A0],6) MOVE D0, ([A0],D3) MOVE D0, ([A0],D4,12) MOVE D0, ([$12345678,A0],D4,$FF000000) |
Эти способы адресации работают следующим образом. Каждый исполнительный адрес содержит пару квадратных скобок [...] внутри пары круглых скобок, т.е. ([...], ... ). Сначала вычисляется содержимое квадратных
скобок, в результате чего получается 32-битный указатель. Например, если используется постиндексная форма [20,A2], то исполнительный адрес - это 20 + [A2]. Аналогично, для преиндексной формы [12,A4,D5] исполнительный адрес - это 12 + [A4] + [D5].
Указатель, сформированный содержимым квадратных скобок, используется для доступа в память, чтобы получить новый указатель (отсюда термин косвенная адресация через память). К этому новому указателю добавляется содержимое внешних круглых
скобок и таким образом формируется исполнительный адрес операнда.
В дальнейшем изложении будут использованы следующие команды (в частности, рассматриваются только арифметические команды с целыми операндами, но не с плавающими):
MOVEA ИА, А - загрузить содержимое по исполнительному адресу ИА на адресный регистр А.
MOVE ИА1, ИА2 - содержимое по исполнительному адресу ИА1 переписать по исполнительному адресу ИА2.
MOVEM список_регистров, ИА - сохранить указанные регистры в памяти, начиная с адреса ИА (регистры указываются
маской в самой команде).
MOVEM ИА, список_регистров - восстановить указанные регистры из памяти, начиная с адреса ИА (регистры указываются маской в самой команде).
LEA ИА, А - загрузить исполнительный адрес ИА на адресный регистр А.
MUL ИА, D - умножить содержимое по исполнительному адресу ИА на содержимое регистра данных D и результат разместить в D (на самом деле в системе команд имеются две различные команды MULS и MULU для чисел со знаком и чисел без знака соответственно; для упрощения
мы не будем принимать во внимание это различие).
DIV ИА, D - разделить содержимое регистра данных D на содержимое по исполнительному адресу ИА и результат разместить в D.
ADD ИА, D - сложить содержимое по исполнительному адресу ИА с содержимым регистра данных D и результат разместить в D.
SUB ИА, D - вычесть содержимое по исполнительному адресу ИА из содержимого регистра данных D и результат разместить в D.
Команды CMP и TST формируют разряды регистра состояний. Всего имеется 4 разряда: Z
- признак нулевого результата, N - признак отрицательного результата, V - признак переполнения, C - признак переноса.
CMP ИА, D - из содержимого регистра данных D вычитается содержимое по исполнительному адресу ИА, при этом формируется все разряды регистра состояний, но содержимое регистра D не меняется.
TST ИА - выработать разряд Z регистра состояний по значению, находящемуся по исполнительному адресу ИА.
BNE ИА - условный переход по признаку Z = 1 (не равно) по исполнительному адресу ИА.
BEQ ИА - условный переход по признаку
Z = 0 (равно) по исполнительному адресу ИА.
BLE ИА - условный переход по признаку N or Z (меньше или равно) по исполнительному адресу ИА.
BGT ИА - условный переход по признаку not N (больше) по исполнительному адресу ИА.
BLT ИА - условный переход по признаку N (меньше) по исполнительному адресу ИА.
BRA ИА - безусловный переход по адресу ИА.
JMP ИА - безусловный переход по исполнительному адресу.
RTD размер_локальных - возврат из подпрограммы с указанием размера локальных.
LINK A, размер_локальных - в стеке сохраняется значение регистра А,
в регистр А заносится указатель на это место в стеке и указатель стека продвигается на размер локальных.
UNLK A - стек сокращается на размер локальных и регистр А восстанавливается из стека.