OSDev Wiki
Advertisement

Краткая история[]

С момента появления архитектуры ARM и до 2011 года появилось семь «больших» версий архитектуры — до ARMv7 включительно. Кроме того, если не у всех, то у многих версий имеются разновидности. Несмотря на все различия, все эти версии и разновидности являются 32-разрядными, используют одинаковый с точки зрения прикладного программиста набор регистров общего назначения и функционально одинаковый базовый набор команд (хотя каждая последующая версия добавляет новые команды и иногда расширяет возможности уже имевшихся).

Ранние процессоры архитектуры ARM использовали 26-разрядные адреса памяти. Первой версией с 32-разрядной адресацией и одновременно последней с 26-разрядной стала ARMv3. Все эти версии к 2010 году практически полностью исчезли, поэтому в дальнейшем они обсуждаться не будут.

Первой по времени появления из пока ещё досаточно широко используемых архитектур стала ARMv4. В ней впервые отказались от поддержки 26-разрядных адресов, но зато в дополнение к командам обработки слов (32 бита) и байтов ввели команды обработки полуслов (16 бит).

Вскоре появилась разновидность ARMv4T, в которой впервые был реализован набор команд Thumb. Команды этого набора функционально являлись подмножеством основного набора команд (с этого момента обозначаемого как набор команд ARM), причём в них отсутствовали команды системного назначения. По этой причине ни для этой, ни для основной массы последующих архитектур вплоть до версии 7 невозможно создать ОС или системно-независимую программу (т. е. программу, работающую на «голом железе» без использования ОС), использующую только систему команд Thumb: начальные участки обработчиков прерываний, а также некоторые действия по управлению процессором можно выполнить только с помощью команд набора ARM. Поскольку каждая команда Thumb кодируется полусловом (16 бит), а команда ARM всегда занимает целое слово (32 бита), программа, написанная с использованием системы команд Thumb, почти всегда занимает существенно меньше памяти, чем программа на ARM (конечно, при условии ручного её кодирования на языке ассемблера или при использовании компилятора, обеспечивающего нормальную поддержку Thumb, чего нет, например, в GCC).

Помимо ARMv4 и ARMv4T, четвёртая версия архитектуры ARM имела ещё две разновидности — ARMv4xM и ARMv4TxM, отличавшиеся от первых двух отсутствием команды длинного умножения (сомножители по 32 разряда, результат — 64 разряда). К началу 2010 года все эти разновидности, кроме ARMv4T, уже утратили актуальность и исчезли с рынка.

Пятая версия архитектуры в «чистом» виде — ARMv5, а также её разновидность без длинного умножения ARMv5xM тоже уже не употребляются. От предыдущей архитектуры они отличаются несколько расширенной системой команд. В частности, именно в ARMv5 появились первые команды набора ARM, не имеющие возможности условного выполнения.

Thumb-разновидность ARMv5T отличается от ARMv4T наличием нескольких дополнительных команд, улучшенными возможностями взаимодействия ARM- и Thumb-кода и некоторыми другими усовершенствованиями; она ещё иногда встречается. Её разновидность с «обрезанными» возможностями умножения, ARMv5TxM, из употребления вышла.

Вскоре после появления процессоров семейства ARMv5T архитектура была вновь весьма существенно расширена: появилась целая группа команд, намного упростившая реализацию алгоритмов цифровой обработки сигналов (так называемые DSP-команды). Новое семейство получило обозначение ARMv5TE и весьма широко используется до сих пор. Некоторые ранние реализации этого семейства имели лишь часть новых команд; эта разновидность получила обозначение ARMv5TExP и уже почти не применяется.

Венцом развития пятой версии архитектуры стало включение специальных средств, предназначенных для упрощения реализации виртуальной машины Java (технология Jazelle; в отличие от большинства других аспектов архитектуры ARM, она не документирована). Такие процессоры получили обозначение ARMv5TEJ и, вероятно, стали самыми распространёнными для пятой версии архитектуры.

Очередная версия архитектуры, ARMv6, изначально не имела разновидностей и включала все возможности ARMv5TEJ, но с рядом улучшений. Так, в ней были расширены обе системы команд, пересмотрена архитектура подсистемы памяти (ставшая намного более унифицированной; до появления ARMv6 очень многие важные решения отдавались «на откуп» производителям, из-за чего при переносе ОС с одного процессора на другой зачастую требовалось выполнить очень много доработок), обеспечен нормальный доступ к невыровненным данным в памяти и др.

Через некоторое время появилась разновидность ARMv6T2, в которой система команд Thumb была существенно расширена и получила наименование Thumb-2. Помимо нескольких новых 16-разрядных команд, в Thumb-2 появилось большое число 32-разрядных команд, покрывающих почти все возможности системы команд ARM. Особого распространения эта разновидность, однако, не получила.

Ещё одной разновидностью шестой версии архитектуры является ARMv6K, включающая некоторые расширения для упрощения реализации ядер операционных систем и тому подобного ПО. Некоторые процессоры этой разновидности поддерживают расширения безопасности, призванные упростить реализацию высоконадёжных систем, а также создание систем виртуальных машин. Эта подверсия иногда обозначается ARMv6Z или ARMv6KZ. Заметим, что версии ARMv6K/KZ не поддерживают систему команд Thumb-2, а версия ARMv6T2 не включает улучшения, реализованные в ARMv6K, т. е. эти две подверсии совместимы между собой только на уровне базовой версии ARMv6.

Повсеместную распространённость, особенно в потребительских мобильных устройствах (телефонах и планшетах) получила следующая версия архитектуры, ARMv7, более известная под именем Cortex (по общему имени реализующих её процессорных ядер). В ней фирма ARM впервые явным образом разделила свои разработки по сферам применения, или по «профилям», как это именуется в документации.

Процессоры A-профиля (версия ARMv7-A, ядра семейства Cortex-A) являются прямыми потомками предыдущих версий архитектуры, сохраняя с ними практически полную программную совместимость «снизу вверх». Они реализуют три системы команд: ARM, Thumb/Thumb-2 и ThumbEE (специфическая разновидность Thumb, предназначенная для использования компиляторами времени выполнения), могут поддерживать технологию Jazelle, а также иметь расширения безопасности и поддерживать виртуализацию. Система команд Thumb/Thumb-2 по сравнению с версией ARMv6T2 была расширена, благодаря чему, сохраняя намного более высокую плотность кода (а значит, потребляя меньше памяти), чем система команд ARM, Thumb/Thumb-2 обеспечивает практически равную с ней производительность. Все процессоры Cortex-A в обязательном порядке оснащены устройством управления памятью (MMU); часто на одном кристалле размещаются несколько процессорных ядер, дополненных графическим процессором. Такие микросхемы предназначены для использования в мощных мобильных устройствах. Нередко производители расширяют их возможности, добавляя специализированные узлы. Например, фирма nVidia выпускает семейство процессоров Tegra, у которых, помимо процессорных ядер ARM, имеется графическое ядро самой nVidia, архитектурно близкое к графическим процессорам, используемым на ПК, и обеспечивающее намного более высокую производительность, чем графическое ядро самой ARM (Mali).

Кристаллы R-профиля (версия ARMv7-R, ядра семейства Cortex-R) в целом аналогичны процессорам A-профиля (хотя поддержка ThumbEE и ряда других «продвинутых» возможностей не является обязательной), но оснащены не устройством управления памятью, а значительно более простым устройством защиты памяти (MPU). Они предназначены в первую очередь для использования в высоконадёжных промышленных контроллерах и тому подобных устройствах, работающих в реальном времени (отсюда буква R в обозначении), не нуждающихся в виртуальной памяти (её использование прямо противоречит целям работы в реальном времени), однако имеющих достаточно высокие требования к производительности.

Наконец, M-профиль (версии ARMv6-M и ARMv7-M, ядра семейства Cortex-M), строго говоря, не относится к «настоящим» ARM-процессорам. Во-первых, он кардинальным образом отличается по системной архитектуре от всех прочих разработок фирмы ARM, а соответственно, на системном уровне не совместим ни с более ранними процессорами, ни с другими профилями 7-й версии архитектуры. Во-вторых, в этих кристаллах реализована только система команд Thumb (ARMv6-M, ядра Cortex-M0 и -M1) или Thumb-2 (ARMv7-M, все прочие ядра Cortex-M), а команды набора ARM не поддерживаются. Предназначена эта серия для использования в качестве микроконтроллеров малой и средней производительности. Благодаря низкой стоимости и энергопотреблению они могут успешно конкурировать с намного более слабыми по вычислительными возможностям 8- и 16-разрядными микроконтроллерами. Заметим, что принадлежность ядер Cortex-M0 и -M1 к 6-й версии архитектуры является чисто формальной и показывает, что по своим возможностям (системе команд) они находятся ниже «настоящей» архитектуры ARMv7-M.

Первые 64-разрядные процессоры (версия архитектуры ARMv8) появились в 2012 году. Здесь сохранилось разделение по профилям, причём, если A-профиль стал действительно новым, то R- и M-профили остались 32-разрядными и являются, по существу, несколько расширенными вариантами этих же профилей 7-й версии архитектуры.

У процессорных ядер, разработанных ARM, существует своя система нумерации, не связанная с номером версии архитектуры. Так, ядра ARM7TDMI и ARM920T реализуют версию ARMv4T, большинство других ядер семейства ARM9 — различные разновидности версии ARMv5 (например, ядро ARM926EJ-S реализует архитектуру ARMv5TEJ). Все ядра семейства Cortex, за исключением Cortex-M0 и -М1, относятся к разновидностям 7-й или 8-й версии архитектуры (ядрам Cortex-M0 и -М1, как уже говорилось, соответствует версия ARMv6-M). Между собой ядра одной и той же версии и разновидности архитектуры могут отличаться конструкцией и объёмом кэш-памяти, наличием MMU, MPU, FPU и т. д.

Некоторые расширения, предпринятые фирмой ARM в своих разработках, оказались невостребованными или недостаточно эффективными. К ним в первую очередь относятся технология Jazelle и система команд ThumbEE, которые уже объявлены устаревшими и могут отсутствовать в новейших ядрах.

Главные особенности[]

Несмотря на то, что аббревиатура ARM расшифровывается как «Advanced RISC Machine» («передовая RISC-машина»), с самого начала это была не совсем типичная RISC-архитектура. С одной стороны, для RISC'а она имела не очень много регистров общего назначения (сейчас с формальной точки зрения у большинства разновидностей архитектуры их 31 штука, однако программисту доступны лишь 16 из них, причём три регистра имеют специальные функции; таким образом, «настоящих» регистров общего назначения с точки зрения программиста всего 13, в то время как целый ряд «настоящих» RISC-процессоров имеют их больше сотни). С другой стороны, уникальной особенностью этой архитектуры являлась возможнось исполнения любой команды при соблюдении заданного условия, отсутствующая не только у других RISC'ов, но и у CISC'ов (первые безусловно выполняемые команды в наборе ARM появились лишь в версии ARMv5). Кроме того, в командах обработки данных в ряде случаев возможно совмещение выполнения основной операции (например, сложения) со сдвигом. Наконец, команды чтения и записи памяти у ARM располагают развитым набором видов адресации, который превосходит по своим возможностям не только RISC'и, но и основную массу CISC-процессоров (среди последних единственными конкурентами в этом плане могли бы служить лишь появившиеся в 1970-х годах миниЭВМ PDP-11 и VAX-11 фирмы DEC, а из достаточно современных архитектур — довольно близкие по основным чертам к PDP-11 16-разрядные микроконтроллеры MSP430 фирмы Texas Instruments).

Однако время показало ошибочность идеи, на которой базировались «настоящие» RISC-архитектуры: достижение высокой производительности через быстрое выполнение простых команд в противовес медленному выполнению сложных команд у CISC-процессоров (предполагалось, что, пока CISC выполнит одну свою сложную команду, RISC успеет выполнить несколько простых и в итоге обгонит CISC по производительности, хотя каждая команда индивидуально выполнит меньший объём действий, чем одна команда CISC'а). На практике оказалось, что даже очень неудачные с архитектурной точки зрения системы команд, например, Intel IA-32, можно выбирать из памяти, декодировать и исполнять чрезвычайно быстро (это наглядно демонстрирует пример самой Intel: несмотря на всю громоздкость и неэффективность её системы команд, именно её процессоры на сегодняшний день по производительности обгоняют почти любые другие кристаллы — правда, ценой чрезвычайно сложной внутренней организации, ставшей возможной лишь благодаря использованию очень совершенной технологии производства). Неудивительно, что в своём развитии архитектура ARM постепенно эволюционировала в сторону CISC-процессоров.

На сегодняшний день у ARMа от RISCа у неё остались только две вещи: невозможность прямой работы с операндами в памяти и название. Некоторые имеющиеся у современных процессоров ARM команды (в частности, деление) недопустимы в «настоящих» RISC'ах в связи с их сложностью и переменным временем выполнения. Внедрение же системы команд Thumb-2 похоронило и другую важнейшую черту RISC-процессоров: одинаковую длину кода команды, призванную упростить её выборку из памяти и декодирование.

Современные 32-разрядные процессоры архитектуры ARM способны обрабатывать 8-, 16- и 32-разрядные целые числа, а процессоры архитектуры ARMv8-A — и 64-разрядные. Возможность обработки вещественных чисел является необязательной и достигается с помощью сопроцессоров (которые, если присутствуют, выполняются на одном кристалле с собственно центральным процессором и с точки зрения прикладного программиста неотличимы от него). Старшие модели способны работать с виртуальной памятью, поскольку имеют необходимое для этого устройство управления памятью (MMU). Более простые изделия не располагают MMU, но в некоторых случаях имеют устройство защиты памяти (MPU), не позволяющее реализовать виртуальную память, но обеспечивающее необходимую поддержку аппаратной защиты одних выполняющихся процессором задач от других.

Терминология и язык ассемблера[]

Компания ARM не всегда последовательна в выборе терминов для обозначения различных понятий и механизмов, описываемых в документации. Особенно это касается ранних версий архитектуры. Например, она использует термины interrupt, fault, abort, exception, trap без чёткого, недвусмысленного и неукоснительного их разграничения. В документации на последние версии архитектуры применение этих слов стало более строгим и упорядоченным, и именно оно положено в основу статей, посвящённых архитектуре ARM. Так, для обозначения произвольного вида прерывания текущего выполняемого кода применяется термин «исключение» (exception). Когда источником прерывания является внешнее устройство, применяется термин «прерывание» (interrupt — внешние и быстрые прерывания IRQ и FIQ). Термин «отказ» (abort для A- и R-профилей, fault для M-профиля) применяется к прерываниям, возникающим в результате неудачной попытки обращения к памяти для выборки команды (отказ предвыборки — prefetch abort) или считывания/записи данных (отказ данных — data abort), а также в других случаях, прямо связанных с действиями программы.

С появлением системы команд Thumb-2 (версия архитектуры ARMv6T2) компания ARM унифицировала язык ассемблера для наборов команд ARM и Thumb, назвав получившийся гибрид аббревиатурой UAL (Unified Assembler Language). Упоминаемые и описываемые в статьях команды приводятся в соответствии с нотацией UAL, которая, особенно для команд набора Thumb, может заметно отличаться от ранее применявшихся обозначений.

Advertisement