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

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

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

Добавлен: 24.12.2021

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

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

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

3 5 8 Глава 5. Уровень архитектуры команд

Это значит, что код операции 15 содержится в битах с 8 по 15, а не с 12 по15.

Биты с 0 по 3 и с 4 по 7, как и раньше, формируют два адреса. Все 14 двухадрес-
ных команд содержат число 1111 в старших четырех битах и числа от 0000 до 1101
в битах с 8 по 11. Команды с числом 1111 в старших четырех битах и числом 1110
или 1111 в битах с 8 по 11 будут рассматриваться особо. Они будут трактоваться

таким образом, как будто их коды операций находятся в битах с 4 по 15. В резуль-
тате получаем 32 новых кода операций. А поскольку требуется всего 31 код, то код

111111111111 означает, что действительный код операции находится в битах с О

по 15, что дает 16 безадресных команд.

Как видим, код операции становится все длиннее и длиннее: трехадресные ко-

манды имеют 4-битный код операции, двухадресные команды — 8-битный код опе-
рации, одноадресные команды — 12-битный код операции, а безадресные коман-

ды — 16-битный код операции.

Идея расширения кода операций наглядно демонстрирует компромисс между

пространством для кодов операций и пространством для другой информации.

Однако на практике все не так просто и понятно, как в нашем примере. Есть толь-

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

 средний

 размер команды, если

выбрать самые короткие коды операций для часто используемых команд и самые

длинные — для редко используемых команд.

Если довести эту идею до конца, можно свести к минимуму среднюю длину

команды, закодировав каждую команду, чтобы максимально уменьшить число тре-
буемых битов. К сожалению, это приведет к наличию команд разных размеров,

которые не будут выровнены в границах байтов. Пока существуют архитектуры
команд с таким свойством (например Intel 432), выравнивание будет иметь боль-
шое значение для быстрого декодирования команд. Тем не менее эта идея часто
применяется на уровне байтов. Ниже мы рассмотрим архитектуру команд JVM,

чтобы показать, как можно менять форматы команд, чтобы максимально умень-

шить размер программы.

Форматы команд процессора Pentium II

Форматы команд процессора Pentium II очень сложны и нерегулярны. Они содер-

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

дель показана на рис. 5.9. Эта ситуация сложилась из-за того, что архитектура раз-

вивалась на протяжении нескольких поколений и ранее в нее были включены не
очень удачно выбранные характеристики. Из-за требования обратной совместимос-
ти позднее их нельзя было изменить. Например, если один из операндов команды

находится в памяти, то другой может и не находиться в памяти. Следовательно,

существуют команды сложения двух регистров, команды прибавления регистра к

слову из памяти и команды прибавления слова из памяти к регистру, но не суще-
ствует команд для прибавления одного слова памяти к другому слову памяти.

В первых архитектурах Intel все коды операций были размером 1 байт, хотя для

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


background image

Форматы команд

359

байт. Префиксный байт — это дополнительный код операции, который ставится
перед командой, чтобы изменить ее действие. Примером префиксного байта может
служить команда WIDE в машинах IJVM и JVM. К сожалению, в какой-то момент
компания Intel вышла за пределы кодов операций, и один код операции, OxFF,

определялся как

 код смены алфавита

 и использовался для разрешения второго

байта команды.

Отдельные биты в кодах операций процессора Pentium II дают довольно мало

информации о команде. Единственной структурой такого рода в поле кода опера-

ции является младший бит в некоторых командах, который указывает, что именно
вызывается — слово или байт, а также соседний бит, который указывает, является

ли адрес памяти (если он вообще есть) источником или пунктом назначения. Таким
образом, в большинстве случаев код операции должен быть полностью декодиро-

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

того, как будет определено, где начинается следующая команда.

Байты

0 - 5

Префикс

1 -2

Код

операции

0 - 1

Состояние

0 - 1

SIB

0 - 4

Смещение

0 - 4

Непосредственный

операнд

Биты

1 1

Команда

Какой операнд исходный

Байт/слово

Биты 2

SCALE

(масштаб)

3

INDEX

(индекс)

3

BASE

(база)

Биты

Состояние

REG

R/M

Рис. 5.9. Форматы команд процессора Pentium II

В большинстве команд вслед за байтом кода операции, который указывает ме-

стонахождение операнда в памяти, следует второй байт, который сообщает всю
информацию об операнде. Эти 8 битов распределены в 2-битном поле MOD и двух
3-битных регистровых полях REG и R/M. Иногда первые три бита этого байта
используются в качестве расширения для кода операции, давая в сумме 11 битов
для кода операции. Тем не менее 2-битное поле означает, что существует только
4 способа обращения к операндам, и один из операндов всегда должен быть регис-
тром. Логически должен быть определяем любой из регистров ЕАХ, ЕВХ, ЕСХ,

EDX, ESI, EDI, EBP, ESP, но правила кодирования команд запрещают некоторые

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

 SIB (Scale,

Index,

 Base — масштаб, индекс, база), который дает дополнительную специфи-

кацию. Эта схема не идеальна, но она является компромиссом между требованием


background image

3 6 0 Глава 5. Уровень архитектуры команд

обратной совместимости и желанием добавлять новые особенности, которые не

были предусмотрены изначально.

Добавим еще, что некоторые команды имеют 1, 2 или 4 дополнительных байта

для определения адреса команды (смещение), а иногда еще 1,2 или 4 байта, содер-

жащих константу (непосредственный операнд).

Форматы команд процессора UltraSPARC II

Архитектура команд процессора UltraSPARC II состоит из 32-битных команд,
выровненных в памяти. Команды очень просты. Каждая из них определяет только
одно действие. Типичная команда указывает два регистра, из которых поступают
входные операнды, и один выходной регистр. Вместо одного из регистров коман-

да может использовать константу со знаком. При выполнении команды LOAD два
регистра (или один регистр и 13-битная константа) складываются вместе для
определения адреса памяти, который нужно считать. Данные оттуда записыва-
ются в другой указанный регистр.

Изначально машина SPARC имела ограниченное число форматов команд. Они

показаны на рис. 5.10. Со временем добавлялись новые форматы. Когда писалась
эта книга, число форматов уже было равно 31. Большинство новых вариантов были
получены путем отнимания нескольких битов из какого-нибудь поля. Например,
изначально для команд перехода использовался формат 3 с 22-битным смещени-
ем. Когда были добавлены прогнозируемые переходы, 3 из 22 битов убирались:
один из них стал использоваться для прогнозирования (совершать или не совер-

шать переход), а два оставшихся определяли, какой набор битов условного кода

нужно использовать. В результате получилось 19-битное смещение. Приведем

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

в другой (целые числа в числа с плавающей точкой и т. д.). Для большинства этих

команд используется вариант формата lb, в котором поле непосредственной кон-
станты разбито на 5-битное поле, указывающее входной регистр, и 8-битное поле,
которое обеспечивает дополнительные биты кода операции. Однако в большин-
стве команд все еще используются форматы, показанные на рисунке.

Первые два бита каждой команды помогают определить формат команды и со-

общают аппаратному обеспечению, где найти оставшуюся часть кода операции,
если она есть. В формате 1а оба источника операндов представляют собой регист-
ры; в формате lb один источник — регистр, а второй — константа в промежутке от

-4096 до +4095. Бит 13 определяет один из этих двух форматов. (Биты нумеруют-

ся с 0.) В обоих случаях местом сохранения результатов всегда является регистр.

Достаточный объем пространства обеспечен для 64 команд, некоторые из которых

сохранены на будущее.

Поскольку все команды 32-битные, включить в команду 32-битную константу

невозможно. Команда SETHI устанавливает 22 бита, оставляя пространство для
другой команды, чтобы установить оставшиеся 10 битов. Это единственная команда,

которая использует данный формат.

Для непрогнозируемых условных переходов используется формат 3, в котором

поле УСЛОВИЕ определяет, какое условие нужно проверить. Бит А нужен для


background image

Форматы команд

361

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

было сказано выше.

Формат

2

Выходной

регистр

Выходной

регистр

Код

операции

Код

операции

Входной

регистр 1

Входной

регистр 1

0

1

Операция

с плавающей

точкой

Входной

регистр 2

Непосредственная

константа

22

Выходной

регистр

Код

операции

Непосредственная

константа

3 регистра

Непосредственный

операнд

SETHI

2 1

22

А Условие

Код

операции

Смещение относительно

счетчика команд

BRANCH

(команда

перехода)

30

Смещение относительно

счетчика команд

CALL

(команда вызова

процедуры)

Рис. 5.10. Изначальные форматы команд процессора SPARC

Последний формат используется для команды вызова процедуры (CALL). Эта

команда особая, поскольку только в ней для определения адреса требуется 30 би-
тов. В данной архитектуре существует один 2-битный код операции. Требуемый
адрес — это целевой адрес, разделенный на четыре.

Форматы команд JVM

Большинство форматов команд машины JVM чрезвычайно просты. Все форматы

показаны на рис. 5.11. Их простота объясняется тем, что машина JVM сравнитель-
но новая. Но подождите 10 лет. Все команды начинаются с кода операции в 1 байт.

В некоторых командах за кодом операции следует второй байт. Это может быть

индекс (как в команде ILOAD), константа (как в команде BIPUSH) или указатель
типа данных (как в команде NEWARRAY, которая создает одномерный массив указан-

ного типа в «куче»). Третий формат по сути такой же, как и второй, только вместо
8-битной константы там присутствует 16-битная константа (как, например, у ко-
манд WIDE ILOAD или GOTO). Формат 4 используется только для команды IINC. Фор-

мат 5 используется только для команды MULTINEWARRAY, которая создает многомер-

ный массив «в куче». Формат 6 нужен только для команды INVOKEINTERFACE, которая
вызывает процедуру при определенных обстоятельствах. Формат 7 предназначен

только для команды WIDE IINC, чтобы обеспечить 16-битный индекс и 16-битную


background image

362

Глава 5. Уровень архитектуры команд

константу, которая прибавляется к выбранной переменной. Формат 8 применяется

только для команд WIDE GOTO и WIDE JSR, чтобы осуществлять переходы на большие
расстояния в памяти и вызовы определенных процедур. Последний формат ис-

пользуется только двумя командами, и обе эти команды нужны для реализации
оператора языка Java switch. Таким образом, все команды JVM, за исключением

восьми особых команд, используют простые и короткие форматы 1, 2 и 3.

Биты

Формат

1 Код операции

2 Код операции

Байт Байт=индекс, константа или тип

3 Код операции

SHORT

SH0RT=HHfl6KC, константа

или смещение

4 Код операции

Индекс

Константа

5

6

7

8

9

Код операции

Код операции

Код операции

Код операции

Код операции

Индекс

Индекс

Индекс

Размерность массива

#Параметры 0

Константа

32-битное смещение перехода

Длина переменной

Рис.  5 . 1 1 .

 Форматы команд JVM

В действительности дела обстоят гораздо лучше, чем может показаться. Коман-

ды виртуальной машины Java кодируются таким образом, чтобы большинство

наиболее распространенных команд кодировались в одном байте. Большинство из

256 возможных команд, кодируемых в одном байте, представляют собой особые

случаи общей формы команд IJVM.

Давайте, например, рассмотрим, как в машине Java происходит загрузка локаль-

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

ременной. Самый короткий вариант покрывает самые распространенные случаи,