Скачиваний:
98
Добавлен:
03.06.2014
Размер:
5.64 Mб
Скачать

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

353

Целые числа без знака в языке Java не присутствуют и не поддерживаются JVM, как и двоично-десятичные числа.

Таблица 5.4. Числовые типы данных для JVM

Тип

8 битов 16 битов 32 бита 64 бита 128 битов

Целые числа со знаком Целые числа без знака

Двоично-десятичныецелыечисла Числа с плавающей точкой

JVM поддерживает символы, но не традиционные 8-битные символы ASCII, a 16-битные символы UNICODE. Указатели поддерживаются главным образом для внутреннего использования компилятора и системы обслуживания. Пользовательские программы не могут непосредственно обращаться к указателям. Указатели используются в основном для ссылок на объекты.

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

Команда состоит из кода операции и некоторой дополнительной информации, например, откуда поступают операнды и куда должны отправляться результаты. Процесс определения, где находятся операнды (то есть их адреса), называется адресацией.

На рисунке 5.5 показано несколько возможных форматов для команд второго уровня. Команды всегда содержат код операции, который сообщает, какие действия выполняет команда. В команде может присутствовать ноль, один, два или три адреса.

КОД ОПЕРАЦИИ

КОД

АДРЕС

ОПЕРАЦИИ

 

 

КОД

 

код

ОПЕРАЦИИ

АДРЕС1 АДРЕС 2

ОПЕРАЦИИ АДРЕС 1 АДРЕС 2 АДРЕС 3

Рис.5.5. Четыреформатакоманд: безадресная команда (а); одноадресная команда(б); двухадресная команда(в);трехадреснаякоманда(г)

В одних машинах все команды имеют одинаковую длину; в других команды могут быть разной длины. Команды могут быть короче слова, длиннее слова или быть равными слову по длине. Если все команды одной длины, то это упрощает декодирование, но часто требует большего пространства, поскольку все команды должны быть такой же длины, как самая длинная. На рис. 5.6 показано несколько возможных соотношений между длиной команды и длиной слова.

354

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

 

 

•1 слово

1 слово

1 слово

 

Команда

Команда

Команда

Команда

 

Команда

Команда

Команда

Команда Команда Команда

 

Команда

Команда

Команда

Команда

 

Команда

Команда

Команда

 

 

 

в

б

 

в

Рис. 5.6. Некоторые возможные отношения междудлиной команды и длиной слова

Критерии разработки для форматов команд

Если разработчикам нужно выбрать форматы команд для их машины, они должны рассмотреть ряд факторов. Нельзя недооценивать сложность этого решения. Если компьютер получился удачным с коммерческой точки зрения, то набор команд может продолжать существовать 20 лет и более. Имеет огромное значение способность добавлять новые команды и использовать другие возможности, которые появляются на протяжении определенного периода времени, но только в том случае, если архитектура и компания, создавшая эту архитектуру, существуют достаточно долго.

Эффективность конкретной архитектуры команд зависит от технологии, которая применялась при разработке компьютера. За длительный период времени эта технология будет подвергнута значительным изменениям, и некоторые характеристики архитектуры команд окажутся неудачными (если оглянуться на прошлое). Например, если доступ к памяти осуществляется быстро, то подойдет стековая архитектура (как в JVM), но если достун к памяти медленный, тогда желательно иметь много регистров (как в UltraSPARC II). Тем читателям, которые считают, что этот выбор сделать просто, мы предлагаем взять лист бумаги и записать следующие предположения: 1) какова будет типичная скорость тактового генератора через 20 лет и 2) каково будет типичное время доступа к ОЗУ через 20 лет. Аккуратно сложите этот лист бумаги и спрячьте его в надежном месте, а через 20 лет разверните и прочитайте, что на нем написано. Те из вас, кто принял этот вызов, могут не использовать лист бумаги, а просто отправить свои предсказания в Интернет.

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

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

Более того, минимизация размера команд может усложнить их декодирование и перекрытие. Следовательно, достижение минимального размера команды должно уравниваться со временем, затрачиваемым надекодирование и выполнение команд.

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

355

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

Если пропускная способность кэш-памяти команд составляет t бит/с, а средняя длина команды г битов, то кэш-память способна передавать самое большее t/r команд в секунду. Отметим, что это верхний предел скорости, с которой процессор может выполнять команды, хотя в настоящее время предпринимаются попытки преодолеть этот барьер. Ясно, что скорость, с которой могут выполняться команды (то есть скорость работы процессора), может ограничиваться длиной команд. Чем короче команды, тем быстрее работает процессор. Поскольку современные процессоры способны выполнять несколько командза один цикл, то вызов нескольких команд за цикл обязателен. Этот аспект кэш-памяти команд делает размер команд важным критерием, который нужно учитывать при разработке.

Второй критерий разработки — достаточный объем пространства в формате команды для выражения всех требуемых операндов. Машина с 2" операциями и со всеми командами менее п битов невозможна. В этом случае в коде операции не было бы достаточно места для того, чтобы указать, какая нужна команда. И история снова и снова доказывает, что обязательно нужно оставлять большое количество свободных кодов операций для будущих дополнений к набору команд.

Третий критерий связан с числом битов в адресном поле. Рассмотрим проект машины с 8-битными символами и основной памятью, которая должна содержать 232 символов. Разработчики вольны были приписать последовательные адреса блокам по 8, 16, 24 или 32 бита.

Представим, что бы случилось, если бы команда разработчиков разбилась на две воюющие группы, одна из которых утверждает, что основной единицей памяти должен быть 8-битный байт, а другая требует, чтобы основной единицей памяти было 32-битное слово. Первая группа предложила бы память из 232 байтов с номерами О, 1,2,3, ...,4 294 967 295. Вторая группа предложила бы память из 230 слов с номерами 0,1,2,3, ...,1073 741823.

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

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

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

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

Вкачестве альтернативы они могут сохранить 32-битный адрес для обращения

кпамяти в 16 Гбайт вместо каких-то там 4 Гбайт.

Этот пример демонстрирует, что для получения оптимальной дискретности памяти требуются более длинные адреса и, следовательно, более длинные команды. Одна крайность — это организация памяти, при которой адресуется каждый бит (например, Burroughs B1700). Другая крайность — это память, состоящая из очень длинных слов (например, серия CDC Cyber содержала 60-битные слова).

Современные компьютерные системы пришли к компромиссу, который, в ка- ком-то смысле, объединил в себе худшие качества обоих вариантов. Они требуют, чтобы адреса были у отдельных байтов, но при обращении к памяти всегда считывается одно, два, а иногда даже четыре слова сразу. В результате считывания одного байта из памяти на машине UltraSPARC II вызывается сразу минимум 16 байтов (см. рис. 3.44), а иногда и вся строка кэш-памяти в 64 байта.

Расширение кода операций

В предыдущем разделе мы увидели, что короткие адреса противостоят удачной дискретности памяти. В этом разделе мы рассмотрим компромиссы, связанные с кодами операций и адресами. Рассмотрим команду размером (n+k) битов с кодом операции в к битов и одним адресом в п битов. Такая команда допускает 2к различных операций и 2" адресуемых ячеек памяти. В качестве альтернативы те же (n+k) битов можно разбить на код операции в (к-1) битов и адрес в (п+1) битов. При этом будет либо в два раза меньше команд, но в два раза больше памяти, либо то же количество памяти, но дискретность вдвое выше. Код операции на (к+1) битов и адрес в (п-1) битов дает большее количество операций, но ценой этого преимуществаявляется либо меньшее количествоячеек памяти, либо неочень удачная дискретность при том же объеме памяти. Наряду с простыми компромиссами между битами кода операции и битами адреса, которые были только что описаны, возможны и более сложные. Схема, которая будет обсуждаться в следующих разделах, называется расширением кода операций.

Понятие расширения кода операций можно пояснить на примере. Рассмотрим машину, в которой длина команд составляет 16 битов, а длина адресов — 4 бита, как показано на рис. 5.7. Эта ситуация вполне разумна для машины, содержащей 16 регистров (а следовательно, 4-битный адрес регистра), над которыми совершаются все арифметические операции. Один из возможных вариантов — наличие в каждой команде 4-битного кода операции и трех адресов, что дает 16 трехадресных команд.

1Ь 14

i v

12

1 10 У ti

I 6 5

4 3 г 1

Кодоперации

 

Адрес 1

Адрес 2

Адрес 3

Рис. 5.7. Командас4-битным кодом операции и тремя 4-битными адресными полями

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

357

Если разработчикам нужно 15 трехадресных команд, 14 двухадресных команд, 31 одноадресная команда и 16 безадресных команд, они могут использовать коды операций от 0 до 14 в качестве трехадресных команд, а код операции 15 уже интерпретировать по-другому (рис. 5.8).

4-битный код операции

8-битный __ код операции

12-битный кодоперации

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

16 битов

-(5ооо)

хххх

УУУУ

7771.

 

0001

хххх

УУУУ

7222.

15 трехадресных команд

0010

хххх

УУУУ

7222.

 

1100

хххх

УУУУ

2222.

 

1101

хххх

УУУУ

7222.

 

1110

хххх

УУУУ

7222

 

• ( 1 1 1 1

0000)

УУУУ

7777

14 двухадресных команд

1111

0001

УУУУ

7222

1111

0010

УУУУ

2222.

 

1111

1011

УУУУ

ZZZZ

 

1111

1100

УУУУ

7222

 

1111

1101

УУУУ

2222

 

<1111

1110

0000)

Z777

31 одноадресная команда

1111

1110

0001

7222.

 

1111

1110

1110

ZZ22

 

1111

1110

1111

7222.

 

1111

1111

0000

ZZZZ

 

1111

1111

0001

2222.

 

1111

1111

1101

7222

 

1111

1111

1110

7222.

 

-{1111

1111

1111

0000)

 

1111

1111

1111

0001

16 безадресных команд

1111

1111

1111

0010

 

1111

1111

1111

1101

 

1111

1111

1111

1110

 

1111

1111

1111

1111

 

15 12 11

8

7

4

3

0

 

Номер бита

Рис. 5.8. Расширение кода операции допускает 15 трехадресных команд, 14 двухадресных

команд, 31 одноадресную команду и 16 безадресных команд. Поля хххх, уууу

и zzz2 — это 4-битные адресные поля

3 58 Глава 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 байт, хотя для изменения некоторых команд часто использовался так называемый префиксный

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

359

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

Отдельные биты в кодах операций процессора Pentium II дают довольно мало информации о команде. Единственной структурой такого рода в поле кода операции является младший бит в некоторых командах, который указывает, что именно вызывается — слово или байт, а также соседний бит, который указывает, является ли адрес памяти (если он вообще есть) источником или пунктом назначения. Таким образом, в большинстве случаев код операции должен быть полностью декодирован, чтобы установить, к какому классу относится операция, которую нужно выполнить, и, следовательно, какова длина этой команды. Это очень сильно снижает производительность, поскольку необходимо производить декодирование еще до того, как будет определено, где начинается следующая команда.

Байты

0 - 5

1 -2

0 - 1

 

0 - 1

0-4

0 - 4

 

Префикс

Код

Состояние

SIB

Смещение

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

 

 

операции

 

 

 

 

операнд

Биты

 

1 1

 

 

Биты 2

3

3

Команда

 

 

 

SCALE

INDEX

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 — масштаб, индекс, база), который дает дополнительную спецификацию. Эта схема не идеальна, но она является компромиссом между требованием

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, в котором поле УСЛОВИЕ определяет, какое условие нужно проверить. Бит А нужен для

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

361

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

Формат

2

 

 

 

 

 

 

 

 

Выходной

Код

Входной

 

Операция

Входной

3 регистра

0

с плавающей

регистр

операции

регистр 1

регистр 2

 

 

 

 

 

точкой

 

 

Выходной

Код

Входной

1

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

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

регистр

операции

регистр 1

константа

операнд

 

 

 

 

 

22

 

 

 

Выходной

Код

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

 

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-битную

362

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

константу, которая прибавляется к выбранной переменной. Формат 8 применяется только для команд WIDE GOTO и WIDE JSR, чтобы осуществлять переходы на большие расстояния в памяти и вызовы определенных процедур. Последний формат используется только двумя командами, и обе эти команды нужны для реализации оператора языка Java switch. Таким образом, все команды JVM, за исключением восьми особых команд, используют простые и короткие форматы 1, 2 и 3.

Биты

 

 

 

 

 

Формат

 

 

 

 

1

Код операции

 

 

 

 

2

Код операции

Байт

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

 

3

Код операции

 

SHORT

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

 

илисмещение

 

 

 

 

 

 

4

Код операции

Индекс

 

Константа

 

5

Код операции

 

Индекс

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

 

6

Кодоперации

 

Индекс

#Параметры

0

7

Код операции

 

Индекс

Константа

 

8

Код операции

 

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

 

9

Код операции

 

 

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

 

Рис. 5.11. Форматы команд JVM

В действительности дела обстоят гораздо лучше, чем может показаться. Команды виртуальной машины Java кодируются таким образом, чтобы большинство наиболее распространенных команд кодировались в одном байте. Большинство из 256 возможных команд, кодируемых в одном байте, представляют собой особые случаи общей формы команд IJVM.

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