ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 24.12.2021

Просмотров: 6739

Скачиваний: 8

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Пример реализации микроархитектуры

263

Микрокоманда Операции

Комментарий

if_icmpeq4
if_icmpeq5

if_icmpeq6

F
F2
F3
invoke virtual!

OPC=TOS

TOS=MDR
Z=OPC-H, if(Z)gotoT,

else goto F

OPOPC-1; fetch;
goto goto2

PC=PC+1
PC=PC+1; fetch

goto Mam1

PC=PC+1, fetch

invoke virtual H=MBRU«8

mvoke_virtual3
invoke_virtual4
mvoke_virtual5
invoke_virtual6

mvoke_virtual7
mvoke_virtual8

invoke_virtual9
invoke_ virtual! 0

invoke_virtual11
mvoke_virtual12

invoke virtual 13

H=MBRU ИЛИ Н
MAR=CPP+H, rd

OPC=PC+1

PC=MDR, fetch

PC=PC+1; fetch

H=MBRU«8

H=MBRU ИЛИ Н
PC=PC+1, fetch

TOS=SP-H
TOS=MAR=TOS+1

PC=PC+1, fetch

mvoke_virtual14 H=MBRU<<8

invoke_virtual15

mvoke_virtual16
invoke_virtual17

invoke_virtual18

invoke_virtual 19

mvoke_virtual20

invoke_virtual21

invoke_virtual22

ireturni

MDR=SP+H+1;wr
MAR=SP=MDR

MDR=OPC, wr

MAR=SP=SP+1

MDR=LV, wr

PC=PC+1, fetch
LV=TOS, gotoMami

MAR=SP=LV; rd

Временное сохранение TOS в ОРС

Помещение новой вершины стека в TOS
Если два верхних слова равны, осуществляется
переход к Т, если они не равны, осуществляется

переход к F

То же, что gotoi, нужно для адреса целевого

объекта

Пропуск первого байта смещения
PC указывает на следующий код операции

Ожидание вызова кода операции
MBR = первый байт индекса; увеличение PC на 1,
вызов второго байта

Сдвиг первого байта на 8 битов и сохранение
значения в регистре Н

Н = смещение указателя процедуры от регистра СРР

Вызов указателя процедуры из набора констант

Временное сохранение значения PC в регистре ОРС
Регистр PC указывает на новую процедуру, вызов
числа параметров
Вызов второго байта числа параметров

Сдвиг первого байта на 8 битов и сохранение
значения в регистре Н

Н = число параметров
Вызов первого байта размера области локальных

переменных

TOS = адрес OBJREF-1

TOS = адрес OBJREF {новое значение LV)

Вызов второго байта размера области локальных

переменных
Сдвиг первого байта на 8 битов и сохранение
значения в регистре Н
Н = размер области локальных переменных
Перезапись OBJREF со связующим указателем
Установка регистров SP и MAR на адрес ячейки,

в которой содержится старое значение PC

Сохранение старого значения PC над

локальными переменными

SP указывает на ячейку, в которой хранится
старое значение LV
Сохранение старого значения LV над
сохраненным значением PC

Вызов первого кода операции новой процедуры

Установка значения LV на первый адрес фрейма
локальных переменных

Переустановка регистров SP и MAR для вызова

связующего указателя

продолжение!


background image

264

 Глава 4. Микроархитектурный уровень

Таблица 4.4

 {продолжение}

Микрокоманда Операции Комментарий

ireturn2

ireturn3

ireturn4

ireturn5

ireturn6

ireturn7

ireturn8

LV=MAR=MDR; rd

MAR=LV+1

PC=MDR; rd; fetch

MAR=SP
LV=MDR
MDR=TOS; wr; goto Mainl

Процесс считывания

Установка регистра LV на связующий указатель;

вызов старого значения PC

Установка регистра MAR на чтение старого
значения LV
Восстановление PC; вызов следующего кода
операции

Установка MAR на запись TOS

Восстановление LV
Сохранение результата в изначальной вершине

стека

Если все разряды байта в регистре MBR равны 0 (это код операции для коман-

ды NOP), то следующей будет микрокоманда nopl, которая вызывается из ячейки 0.

Поскольку эта команда не производит никаких операций, она просто совершает

переход к началу основного цикла, где повторяется та же последовательность дей-

ствий, но уже с новым кодом операции в MBR.

Еще раз подчеркнем, что микрокоманды, приведенные в табл. 4.4, не располо-

жены в памяти последовательно и что микрокоманда Mainl находится вовсе не в
ячейке с адресом 0 (поскольку в этой ячейке должна находиться микрокоманда
nopl). Задача микроассемблера — поместить каждую команду в подходящую ячей-
ку и связать их в короткие последовательности, используя поле NEX1VADDRESS.

Каждая последовательность начинается с адреса, который соответствует номер-

ному значению кода операции (например, команда POP начинается с адреса 0x57),
но остальные части последовательности могут находиться в любых ячейках управ-
ляющей памяти, и эти ячейки не обязательно идут подряд.

А теперь рассмотрим команду IADD. Она начинается с микрокоманды iaddl.

Требуется выполнить следующие действия:

1. Значение регистра TOS уже есть, но из памяти нужно вызвать второе слово

стека.

2. Значение регистра TOS нужно прибавить ко второму слову стека, вызван-

ному из памяти.

3. Результат, который помещается в стек, должен быть сохранен в памяти и в

регистре TOS.

Для того чтобы вызвать операнд из памяти, необходимо уменьшить значение

указателя стека и записать его в регистр MAR. Отметим, что этот адрес будет ис-

пользоваться для последующей записи. Более того, поскольку эта ячейка памяти

будет новой вершиной стека, данное значение должно быть присвоено регистру SP.

Следовательно, определить новое значение SP и MAR, уменьшить значение SP на 1

и записать его в оба регистра можно за одну операцию.

Все эти действия выполняются в первом цикле (i addl). Здесь же инициируется

операция чтения. Кроме того, регистр МРС получает значение из поля NEXT
ADDRESS микрокоманды iaddl. Это адрес микрокоманды iadd2. Затем iadd2 счи-


background image

Пример реализации микроархитектуры 265

тывается из управляющей памяти. Во втором цикле, пока происходит считывание

операнда из памяти, мы копируем верхнее слово стека из TOS в Н, где оно будет

доступно для сложения, когда процесс считывания завершится

В начале третьего цикла (iadd3) MDR содержит второе слагаемое, вызванное

из памяти. В этом цикле оно прибавляется к значению регистра Н, а результат
сохраняется обратно в регистры MDR и TOS. Кроме того, начинается операция

записи, в процессе которой новое верхнее слово стека сохраняется в памяти. В этом

цикле команда goto приписывает адрес Mainl регистру МРС, таким образом, мы
возвращаемся к исходному пункту и можем начать выполнение следующей опе-
рации

Если следующий код операции, который содержится в данный момент в регис-

тре MBR, равен 0x64 (ISUB), то повторяется практически таже последовательность

действий После выполнения Mainl управление передается микрокоманде с адре-

сом 0x64 (1 subl) За этой микрокомандой следуют i sub2, i sub3, а затем снова Mai nl

Единственное различие между этой и предыдущей последовательностью состоит
в том, что в цикле isub3 содержание регистра Н не прибавляется к значению MDR,

а вычитается из него

Команда IAND идентична командам IADD и ISUB, только в данном случае два верх-

них слова стека подвергаются логическому умножению (операция И), а не скла-

дываются и не вычитаются Нечто подобное происходит и во время выполнения

команды I0R

Если код операции соответствует командам OUP, POP или SWAP, то нужно исполь-

зовать стек Команда DUP дублирует верхнее слово стека Поскольку значение это-

го слова уже находится в регистре TOS, нужно просто увеличить SP на 1 Теперь

регистр SP указывает на новый адрес В эту новую ячейку и записывается значе-
ние регистра TOS Команда POP тоже достаточно проста нужно только уменьшить
значение SP на 1, чтобы отбросить верхнее слово стека Однако теперь необходимо
считать новое верхнее слово стека из памяти и записать его в регистр TOS. Наконец,

команда SWAP меняет местами значения двух ячеек памяти, а именно два верхних
слова стека Регистр TOS уже содержит одно из этих значений, поэтому считывать его
(значение) из памяти не нужно Подробнее мы обсудим эту команду немного позже.

Команда BIPUSH сложнее предыдущих, поскольку за кодом операции следует

байт, как показано на рис 4 13 Этот байт представляет собой целое число со зна-
ком Этот байт, который уже был передан в регистр MBR во время микрокоманды
Mainl, нужно расширить до 32 битов (знаковое расширение) и скопировать его в

регистр MDR. Наконец, значение SP увеличивается на 1 и копируется в MAR, что

позволяет записать операнд на вершину стека. Этот операнд также должен копиро-
ваться в регистр TOS Отметим, что значение регистра PC должно увеличиваться
на 1, чтобы в микрокоманде Mainl следующий код операции уже имелся в наличии.

BIPUSH

(0x10)

  Б А И Т

Рис. 4.13. Формат команды BIPUSH

Теперь рассмотрим команду ILOAD В этой команде за кодом операции также

следует байт (рис. 4.14,

 а),

 но этот байт представляет собой индекс (без знака),


background image

2 6 6 Глава 4. Микроархитектурный уровень

используемый для того, чтобы найти в пространстве локальных переменных сло-
во, которое нужно поместить в стек. Поскольку здесь имеется всего 1 байт, можно
различать только 2

8

=256 слов, а именно первые 256 слов пространства локальных

переменных. Для выполнения команды ILOAD требуется и процесс чтения (чтобы
вызвать слово), и процесс записи (чтобы поместить его в стек). Чтобы определить
адрес для считывания, нужно прибавить смещение, которое хранится в регистре

MBR (буферном регистре памяти), к содержимому регистра LV. Доступ к регист-

рам MBR и LV можно получить только через шину В, поэтому сначала значение

LV копируется в регистр Н (в цикле iloadl), а затем прибавляется значение MBR.
Результат суммирования копируется в регистр MAR, и начинается процесс чте-
ния (в цикле iload2).

ILOAD

(0x15)

ИНДЕКС

WIDE

(0хС4)

ILOAD

(0x15)

ИНДЕКСНЫЙ

БАЙТ1

ИНДЕКСНЫЙ

БАЙТ 2

Рис.

 4.14.

 Команда ILOAD с однобайтным индексом (а);

команда WIDE ILOAD с двубайтным индексом (б)

Однако здесь регистр MBR используется не совсем так, как в команде BIPUSH,

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

 BIPUSH,

где байт представляет собой 8-битное целое число со знаком). Интерфейс между
регистром MBR и шиной В разработан таким образом, чтобы обе операции были
возможны. В случае с BIPUSH (где байт — 8-битное целое число со знаком) самый

левый бит значения MBR копируется в 24 старших бита шины В. В случае с ILOAD

(где байт — 8-битное целое число без знака) 24 старших бита шины В заполняются
нулями. Два специальных сигнала помогают определить, какую из этих двух опе-
раций нужно выполнить (см. рис. 4.5). В микропрограмме слово MBR указывает
на байт со знаком (как в команде bipush3), a MBRU — на байт без знака (как в

команде iload2).

Пока ожидается поступление операнда из памяти (во время iload3), значение

регистра SP увеличивается на 1 для записи новой вершины стека. Это значение

также копируется в регистр MAR (это требуется для записи операнда в стек). За-
тем значение PC снова увеличивается на 1, чтобы вызвать следующий код опера-
ции (микрокоманда iload4). Наконец, значение MDR копируется в регистр TOS,

чтобы показать новое верхнее слово стека (микрокоманда iload5).

Команда ISTORE противоположна команде ILOAD (из стека выталкивается верх-

нее слово и сохраняется в ячейке памяти, адрес которой равен сумме значения
регистра LV и индекса данной команды). В данном случае используется такой
же формат, как и в команде ILOAD (рис. 4.14, й), только здесь код операции не 0x15,
а 0x36. Поскольку верхнее слово стека уже известно (оно находится в регистре
TOS), его можно сразу сохранить в памяти. Однако новое верхнее слово стека все
же необходимо вызвать из памяти, поэтому требуется и операция чтения, и опера-

ция записи, хотя их можно выполнять в любом порядке (или даже одновременно,

если бы это было возможно).


background image

Пример реализации микроархитектуры 267

Команды ILOAD и ISTORE имеют доступ только к первым 256 локальным пере-

менным. Хотя для большинства программ этого пространства будет достаточно,

все же нужно иметь возможность обращаться к любой локальной переменной,
в какой бы части фрейма она не находилась. Чтобы обеспечить такую возможность,
машина IJVM использует то же средство, что и JVM: специальный код операции

WIDE (так называемый префиксный байт), за которым следует код операции ILOAD
или ISTORE. Когда встречается такая последовательность, формат команды ILOAD

или ISTORE меняется, и за кодом операции идет не 8-битный, а 16-битный индекс,
как показано на рис. 4,14,

 б.

Команда WIDE декодируется обычным способом. Сначала происходит переход к

микрокоманде widel, которая обрабатывает код операции WIDE. Хотя код операции,

который нужно расширить, уже присутствует в регистре MBR, микрокоманда widel

вызывает первый байт после кода операции, поскольку этого требует логика мик-
ропрограммы. Затем совершается еще один межуровневыи переход, но на этот раз

для перехода используется байт, который следует за WIDE. Но поскольку команда
WIDE ILOAD требует набора микрокоманд, отличного от ILOAD, а команда WIDE ISTORE

требует набора микрокоманд, отличного от ISTORE, и т. д., при осуществлении меж-
уровневого перехода нельзя использовать в качестве целевого адреса код операции.

Вместо этого микрокоманда wi del подвергает логическому сложению адрес Ох 100

и код операции, поместив его в регистр МРС. В результате интерпретация WIDE
LOAD начинается с адреса 0x115 (а не 0x15), интерпретация WIDE ISTORE — с адреса
0x136 (а не 0x36) и т. д. Таким образом, каждый код операции WIDE начинается с
адреса, который в управляющей памяти на 256 (то есть Ох 100) слов выше, чем соот-
ветствующий обычный код операции. Начальная последовательность микрокоманд

для ILOAD и WIDE ILOAD показана на рис. 4.15.

Команда WIDE ILOAD отличается от обычной команды ILOAD только тем, что ин-

декс в ней состоит из двух индексных байтов. Слияние и последующее суммиро-

вание этих байтов должно происходить по стадиям, при этом сначала первый ин-

дексный байт сдвигается влево на 8 битов и копируется в Н. Поскольку индекс —

целое число без знака, то здесь используется регистр MBRU (24 старших бита за-

полняются нулями). Затем прибавляется второй байт индекса (операция сложе-
ния идентична слиянию, поскольку младший байт регистра Н в данный момент
равен 0), при этом гарантируется, что между байтами не будет переноса. Результат
снова сохраняется в регистре Н. С этого момента происходят те же действия, что и
в стандартной команде ILOAD. Вместо того чтобы дублировать последние команды

ILOAD (от iload3 до iload5), мы просто совершили переход от wide_iload4 к iload3.

Отметим, что во время выполнения этой команды значение PC должно увеличи-
ваться на 1 дважды, чтобы в конце этот регистр указывал на следующий код опера-
ции. Команда ILOAD увеличивает значение один раз; последовательность команд

WIDE_ILOAD также увеличивает это значение один раз.

Такая же ситуация имеет место при выполнении WIDEISTORE. После выполне-

ния первых четырех микрокоманд (от wi de_i storel до wi de_i store4) последователь-
ность действий та же, что и в команде ISTORE после первых двух микрокоманд,

поэтому мы совершаем переход от wide_istore4 к istore3.

Далее мы рассмотрим команду LDC_W. Существует два отличия этой команды от

ILOAD. Во-первых, она содержит 16-битное смещение без знака (как и расширенная

версия ILOAD), а во-вторых, эта команда индексируется из регистра СРР, а не из