[МУЗЫКА]
[МУЗЫКА] Ну и как обещал,
я расскажу про самую массовую архитектуру ARM.
Почему я думаю, что она самая массовая?
Потому что она, прежде всего, используется в мобильных телефонах.
У каждого из вас в кармане есть мобильный телефон, так вот я вас уверяю,
что с вероятностью четыре девятки там сидит процессор ARM.
Во всех мобильных телефонах самых разных компаний.
Ну и в планшетах, вообще это довольно популярная архитектура.
Что такое ARM?
Расшифровывается Advanced RISC Machine.
Разработчик компания ARM Holdings.
Это довольно забавная компания, потому что, с одной стороны, я сказал,
что самая массовая архитектура, с другой стороны,
у этой компании нет своей фабрики, своего завода по производству чипов.
Эта компания производит так называемые IP-ядра,
IP — intellectual property, интеллектуальная собственность.
То есть они разработали довольно интересную архитектуру, систему команд,
реализовали ее в виде языков программирования кристаллов HDL,
high definition language.
Отладили и провели какие-то
работы по разводке кристаллов, по проверке электромагнитной совместимости,
то есть сделали всю подготовительную работу, а потом продают дискетки,
передают на фабрики, передают файлы с готовыми программами
для автоматов project на фабрики, которые производят кристаллы.
И уже там дальше производят чипы,
камешки, которые потом ставятся в телефоны и везде, где хотите.
Такой сорт компаний называется fabless company — компания,
которая производит чипы без фабрики.
То есть они производят IP-ядра, а потом эти IP-ядра продают.
Давайте поразбираем эту ситуацию поподробнее.
Много взаимозаменяемых регистров, глубокий конвейер из однотактных операций.
Если операция такова, что занимает четыре-пять тактов,
то она выстраивается в конвейер из простых однотактных действий, то есть есть много
аппаратных узлов, вот первый аппаратный узел взял первую команду,
выбранный первый такт из нее, передал результат в другой аппаратный узел,
а сам в это же время начинает этот узел делать, второй.
А этот узел уже берет следующую команду и выполняется первый такт для нее.
И так дальше они двигаются, в результате с некой latency, задержкой,
в конце концов получается так, что каждый такт выдается результат команды.
То есть здесь применяется глубокая конвейеризация.
Это не так просто сделать, но сумели сделать.
ARM выпускается в нескольких видах.
Во-первых, самый классический ARM, 32-битный, то, что мы сейчас и разбираем.
Есть и другой вариант Thumb-1, это набор 16-битовых команд.
То есть они чуть-чуть урезали систему команд, но упаковали все так,
что обычно выполняется в 32-разрядной команде,
теперь пакуется в 16-разрядную команду.
Помните, я говорил вам критику IBM-360, что много нулей?
Видимо, эти товарищи тоже осознали,
что 32-разрядные команды были слишком много, и сделали вариант 16-битовый.
Для меня, когда я стал это читать, было очень приятно,
то есть мы тоже были на правильном пути еще в 1987 году,
когда мы разработали свою машину, теперь идея получила продолжение.
Thumb-2 — это смешанный формат, там есть много 16-битовых команд,
и есть вариант 32-битовых команды тоже.
Но еще раз повторяю, если встроенное применение,
вам надо экономить всё — память, время, особенно память.
И вариант Thumb очень хорош для таких встроенных применений, потому что длина
кода получается, в среднем, в два раза меньше, чем в стандартном ARM.
Ну и наконец есть такой вариант Jazelle, 8 бит,
это аппаратная реализация Java байт-кода.
Если вы хотя бы чуть-чуть знаете теорию языков программирования и практику
их трансляции, вы знаете, что Java изначально проектировался как язык,
ориентированный не на компиляцию, а на интерпретацию, и для нее придумали
специальную виртуальную машину, она называется Java code,
и обычно делается программа-интерпретатор на обычных машинах Java байт-кода.
А вот фирма ARM взяла и сделала аппаратную реализация Java байт-код.
Есть вариант ARM-процессор, у которых система команд — это просто коды,
байт-коды Java, и поэтому он решает,
что Java получила такое чисто аппаратное воплощение, чисто аппаратную реализацию.
В архитектуре ARM есть 16 обычных регистров 32-разрядных.
Некоторые из них имеют выделенное значение,
но их можно использовать для других целей.
Ну, например, program counter, счетчик программ, 15-й регистр,
или link register, 14-й регистр.
Опять-таки ничего не пропадает,
когда-то давно в этом курсе я вам рассказывал про команды,
чуть ли не в самом первом модуле, и говорил, что есть такая команда Branch and
Link, и говорил, что передается управление под метку под программы,
а адрес следующей команды записывается в регистр, указанный в этой команде.
Так вот, в IBM было принято, просто это было не обязательно,
так было принято, и все делали возврат по 14-му регистру.
Прошло много лет, и что мы видим?
Что регистр возврата в ARM тоже 14-й регистр.
Я считаю, правильно делают.
Единственное — создавать и поддерживать,
как говорил один профессор у нас на матмехе.
И наконец, 13-й регистр —это указатель Stack.
ARM — это в каком-то смысле стековая машина,
в ней аппаратно поддержаны основные операции со стеком.
Push — запихнуть в стек или положить что-то на верхушку стека.
И Pop — снять с верхушки стека, и указатель стека при этом R13.
Точно так же, как в IBM-360 есть PSW (Program status word),
здесь тоже есть такое же слово,
оно здесь называется Current Program Status Register — CPSR.
В этом специальном регистре выделены
флаги условия, флаги запрещения и разрешения прерываний,
адрес следующего разряда, адрес следующей команды.
И вот как обозначаются признаки, которые вырабатывают определенные команды.
V oVerflow — переполнение знаковое, C Carry — перенос бита знаковый,
Z Zero — нулевой результат, или он же обозначает равенство,
и N Negative — отрицательное значение, то есть бит 31 установлен.
Отрицательные числа хранятся в дополнительном коде,
и признак отрицательности — это как раз единичка в старшем 31-м бите.
Почти все команды ориентированы на спекулятивное исполнение.
Помните, в одном из предыдущих разделов я вам рассказывал,
что такое спекулятивное исполнение.
Для ускорения работы некоторые команды исполняются впрок, хотя еще не известно,
можно ли записать в регистр их результат.
Так вот, в ARM практически все команды ориентированы на спекулятивное исполнение.
Условие приписано примерно во все команды, в ассемблере,
ну и соответственно есть соответствующие биты в двоичном коде.
Вот, например, addge, вот смотрите r1, r1,
r1, я должен сложить r1 сам с собой и записать в r1?
Сложится, но запись произойдет только в том случае, если предыдущая команда
выработала код условия больше или равно, greater or equal.
А так, если условия такого не было выработано, то сложится,
а записи в регистре не будет.
То есть это классическое спекулятивное исполнение,
и практически все команды имеют суффикс, который позволяет им указать,
при каком условии команду можно успешно завершить.
А если условие не выполнено, то команда выполнится, но записи никуда не будет.
А установкой флага тоже можно управлять, есть другой суффикс S.
Если S-суффикс в команде установлен, то флаги будут установлены,
а S если не написан, то флаги не будут меняться.
Это тоже удобно, потому что если вам надо делать какую-то команду,
зависит от условий не предыдущей команды, а две-три команды назад.
Вот эта команда выработала какие-то условия, потом вы ставите одну-две команды
без суффикса S, чтобы не было изменений флага установки,
а потом вы ставите команду, которая зависит от условий вот этой команды.
То есть вы выработали условие, потом пару команд это условие не трогали,
а потом дальше вы по этому условию использовали команды.
Это тоже очень удобно.
Ну вот это тут написано subs, это subtraction, то есть выполнить вычитание.
Из r2 вычесть непосредственно единичку,
ее записать в r1 и установить флаги – ноль, меньше, больше ноля.
Хорошая, интересная особенность ARM,
что операнды можно модифицировать прямо в команде.
Прежде всего можно сдвинуть операнд перед исполнением.
То есть вот смотрите пример, аргумент второй может быть регистр,
потом операция сдвига, влево, вправо, циклический, арифметический,
логический, все они тут перечислены.
И можно сдвинуть на B разрядов, B — просто непосредственный операнд.
А есть и другой вариант такой же команды, что то, на сколько надо сдвигать,
это младший байт регистра, то есть можно величину сдвига вычислить.
То есть взять какой-то регистр, а в следующей команде использовать этот
регистр в качестве операнда, указав, что shift register,
то есть величина сдвига берется не из константы, не из команды, а из регистра.
И вы знаете, я сначала, когда знакомился с этой архитектурой, думал какая-то странная
команда, а потом стал думать и попробовал программировать сам.
Удивительно часто эта операция используется, то есть это правило хорошо.
Аналогичная вещь применяется для констант,
они на константы в команде отводят только 12 битов, зато эту константу
можно сдвинуть на несколько битов,
количество сдвигов указано в этой же команде.
То есть непосредственный операнд константа, и указано,
на сколько перед исполнением сдвинуть сюда влево.
Тоже удобное действие.
Есть команда работы с памятью, но тут и говорить нечего — загрузка,
выгрузка и вот, как обычно из регистра в регистр.
Можно указывать адрес в регистре,
а можно указать адрес еще непосредственно смещения — 5-битовое или 12-битовое.
То есть они пошли на все это.
Наконец, вызов функций.
Команда Branch with Link.
Помните, в IBM была Branch and Link, а тут Branch with Link,
но работает абсолютно так же.
Текущее значение pc program counter запоминается в регистре lr,
который является операндом этой команды, а дальше функция начинает с того,
что делает команду push, запоминает этот регистр в стеке,
а перед возвратом делает pop, снимает со стека,
в pc пишет и переходит по регистру обратно.
Опять-таки ничего не ново под луной.
Когда я говорил про обычные команды Branch and Link в традиционных архитектурах, я
говорил, что поскольку внутри подпрограммы могут быть вызовы других подпрограмм,
то необходимо все регистры прятать в память, а перед возвратом останавливать.
Здесь же все происходит довольно экономно, аккуратно,
регистр возврата прячется в стек, и только он, остальные регистры не трогают.
А перед возвратом стек восстанавливается, и потом у него происходит переход.
Я думаю, что это очень удачное решение.
Таким образом, я не могу сказать, что я вам рассказал все команды ARM,
там их огромное количество, с огромным количеством модификаций.
Но основы я вам рассказал, и мне кажется, что вы получили представление,
что это современная, довольно оптимальная архитектура, и очень многие вещи,
о которых я рассказывал, как мы экономили там, чтобы было поменьше
нулевых битиков, здесь все эти оптимизации активно применяются.
Вообще надо сказать, что ARM — это хороший пример для заключительной лекции.
Я вам рассказывал, что такое спекулятивное исполнение.
Здесь практически все команды спекулятивно исполняются.
Я вам рассказывал соглашение о связях, что такое регистр [НЕРАЗБОРЧИВО],
почему его надо запоминать в памяти.
Здесь все это делается через стек.
То есть очень многие современные находки, то есть ARM, можно сказать,
действительно современная архитектура, которая вобрала в себя все лучшие находки,
идеи, придуманные в разные времена для разных машин,
ARM в эту архитектуру удачно собрала.