Адресное пространство[]
Архитектура ARM использует плоское адресное пространство размером 4 Гбайта. Адресами памяти являются беззнаковые целые числа длиной 32 бита. Физически на эти адреса отображается как собственно память (оперативная и постоянная), так и устройства ввода-вывода.
При вычислении адресов операндов, находящихся в памяти, используется 32-разрядная арифметика, а выход за пределы разрядной сетки игнорируется. Таким образом, при последовательном увеличении адресов после адреса FFFF_FFFF следует адрес 0000_0000, а при последовательном уменьшении — наоборот. Однако код программы не должен пересекать границу памяти: если при последовательном продвижении регистра PC произойдёт «свёртка» адреса, результат будет непредсказуем. Непредсказуемым окажется и результат выполнения инструкций чтения и записи данных, если используемая ими область данных пересекает границу адресов между FFFF_FFFF и 0000_0000.
Порядок следования байтов в многобайтовых величинах[]
Архитектуры до версии ARMv6 предусматривают два порядка следования байтов в полусловах и словах: «младший-старший» (little-endian, LE) и «старший-младший» с постоянным положением слов (big-endian word invariant, BE-32; подробнее эти порядки будут описаны в последующих подразделах). Производители процессоров были вольны сами выбирать, какой из возможных порядков следования байтов поддерживать. Допускалась и поддержка обоих порядков; в этом случае производитель определял, каким образом будет устанавливаться порядок, активный сразу после сброса процессора, и поддерживается ли возможность его программной смены. Теоретически могла возникнуть ситуация, когда процессор после сброса начинал работать с порядком «младший-старший», но был подключен к памяти, поддерживающей порядок «старший-младший»; в таком случае одним из первых действий программы было переключение процессора в режим «старший-младший» (это необходимо было сделать раньше, чем произойдёт первое обращение к байту или полуслову данных или же начнёт выполняться код Thumb).
В версии ARMv6 появилась поддержка смешанного порядка следования байтов (mixed endian), называемого также порядком «старший-младший» с постоянным положением байтов (big-endian byte invariant, BE-8). В отличие от BE-32, порядок BE-8 распространяется только на доступы к данным; при выборке команд при установленном режиме BE-8 используется порядок LE. Все процессоры ARMv6 обязаны поддерживать порядки LE и BE-8; поддержка порядка BE-32 является необязательной.
Порядок LE[]
При порядке LE младший байт полуслова, выровненного по границе полуслова и расположенного по адресу A (он будет кратен 2), находится по адресу A, а старший байт — по адресу A+1. Младший байт слова, выровненного на границу слова и расположенного по адресу A (он будет кратен 4), находится по адресу A, следующий за ним байт — по адресу A+1, третий байт — по адресу A+2 и четвёртый, самый старший байт — по адресу A+3.
Если осуществляется доступ к нескольким словам подряд (например, выполняется считывание двойного слова), то адрес младшего слова будет равен A, следующего за ним — A+4 и так далее.
Возможность доступа по невыровненным адресам определяется версией архитектуры процессора и несколькими управляющими битами. Подробнее об этом будет сказано ниже в соответствующем подразделе.
Порядок BE-32[]
При порядке BE-32 старший байт полуслова, выровненного по границе полуслова и расположенного по адресу A (он будет кратен 2), находится по адресу A, а младший байт — по адресу A+1. Старший байт слова, выровненного на границу слова и расположенного по адресу A (он будет кратен 4), находится по адресу A, следующий за ним байт — по адресу A+1, третий байт — по адресу A+2 и четвёртый, самый младший байт — по адресу A+3.
Если осуществляется доступ к нескольким словам подряд (например, выполняется считывание двойного слова), то адрес младшего слова будет равен A, следующего за ним — A+4 и так далее, т.е. слова идут в порядке «младший-старший», как и при порядке LE, хотя байты в них расположены в порядке «старший-младший». Именно это обстоятельство подчёркивается в названии данного порядка следования байтов: «старший-младший» с постоянным положением слов.
Возможность доступа по невыровненным адресам определяется версией архитектуры процессора и несколькими управляющими битами. Подробнее об этом будет сказано ниже в соответствующем подразделе.
Порядок BE-8[]
Как уже указывалось, порядок BE-8 появился в версии ARMv6 и распространяется только на доступы к данным; когда он активен, выборка инструкций производится в соответствии с порядком LE.
В отличие от порядка BE-32, порядок BE-8 не влияет на адреса байтов в памяти: они остаются одинаковыми в порядках LE и BE-8 (именно это подчёркивается названием: порядок «старший-младший» с постоянным положением байтов). Вместо этого при включении режима BE-8 информация, передаваемая между памятью и регистрами процессора, переворачивается «с ног на голову», что и создаёт эффект доступа с порядком следования байтов «старший-младший». Таким образом, младший байт полуслова, расположенного по адресу A, физически находится по адресу A, а старший байт — по адресу A+1, однако в регистре они будут расположены в разрядах 15:8 и 7:0 соответственно. Аналогичным образом, младший байт слова, расположенного по адресу A, физически находится по адресу A, следующий за ним байт — по адресу A+1, третий байт — по адресу A+2 и четвёртый, самый старший байт — по адресу A+3, однако в регистре они займут разряды соответственно 31:24, 23:16, 15:8 и 7:0.
Многословные доступы осуществляются как последовательность обращений к отдельным словам с последовательным увеличением адресов слов. Таким образом, положение слов при порядках BE-8 и LE тоже будет одинаковым.
Возможность доступов по невыровненным адресам зависит от режима работы процессора; подробнее это описывается в одном из следующих подразделов.
Доступы по невыровненным адресам[]
Архитектура ARM традиционно рассчитана на осуществление доступов к памяти по правильно выровненным адресам: это проще в реализации, а также обеспечивает наивысшую производительность. Тем не менее, в определённых ситуациях она позволяет осуществлять обращения к данным по невыровненным адресам. Инструкции всегда должны быть выровнены на правильную границу: команды набора ARM располагаются по границе слова, а команды набора Thumb — по границе полуслова.
Архитектуры, предшествующие ARMv6[]
Инструкции чтения и записи двойного слова (LDRD и STRD) при обращении по невыровненному адресу дают непредсказуемый результат.
Невыровненные доступы к словам и полусловам подчиняются следующим правилам:
- если процессор оснащён сопроцессором управления системой CP15, то при установленном бите A его регистра управления при такой попытке возникает отказ данных;
- если CP15 отсутствует или если бит A равен нулю, обращения к словам и полусловам выполняются по принудительно выровненным адресам: для доступа к слову два младших бита считаются равными нулю, а для доступа к полуслову — один бит;
- в дополнение к предыдущему, если выполняется операция загрузки слова (команды LDR и LDRT набора ARM и LDR набора Thumb), после выборки из памяти по выровненному адресу осуществляется циклический сдвиг («вращение») считанного значения вправо на число байтов, равное значению двух младших битов адреса.
Архитектура ARMv6[]
Процессоры архитектуры ARMv6 всегда имеют в своём составе сопроцессор CP15, поэтому позволяют включать или отключать контроль выравнивания (бит A) по мере надобности. Кроме того, у них появился ещё один управляющий бит, U, который позволяет разрешить невыровненные доступы к словам и полусловам в командах LDRH, LDRSH, LDR, LDRT, STRH, STR и STRT набора ARM и их аналогов набора Thumb, а также ослабить контроль выравнивания для команд доступа к двойным словам LDRD и STRD (при установленном бите U задаваемый в них адрес должен быть кратен слову, а при сброшенном – двойному слову). Доступы к памяти в других инструкциях всегда должны быть выровненными независимо от состояния бита U.
Подробнее о выполнении различных видов доступов к памяти будет сказано в одном из следующих подразделов.
Управление порядком следования байтов и невыровненными доступами[]
Для переключения моделей следования байтов и управления невыровненными доступами используется пять битов:
- необязательный бит B регистра 1 сопроцессора управления системой CP15. Он присутствует, если поддерживается модель BE-32, и позволяет включить её. Когда он равен нулю, активна либо модель LE, либо модель BE-8 (см. ниже);
- бит A регистра 1 сопроцессора управления системой CP15, управляющий обнаружением невыровненных доступов (когда установлен, попытка доступа по невыровненному адресу вызывает отказ данных;
- бит U регистра 1 сопроцессора управления системой CP15, управляющий поддержкой невыровненных доступов (когда установлен, разрешаются «нормальные» невыровненные доступы в моделях LE и BE-8);
- бит EE регистра 1 сопроцессора управления системой CP15, определяющий значение бита E CPSR, загружаемого в CPSR при возникновении исключения;
- бит E регистра текущего состояния программы CPSR. Этот бит переключает модели LE и BE-8, когда бит B регистра 1 сопроцессора управления системой CP15 равен нулю, а процессор не находится в режиме совместимости (установлен хотя бы один из битов U и A регистра 1 сопроцессора управления системой CP15).
В процессорах версий, предшествовавших ARMv6, может поддерживаться любая из моделей LE и BE-32 или обе вместе — это зависит от конкретной реализации процессора. В последнем случае переключение между ними осуществляется с помощью бита B регистра 1 сопроцессора управления системой CP15: когда он равен нулю, активна модель LE, а когда равен единице — модель BE-32. Обе эти модели распространяются на доступы и к коду, и к данным. В том случае, если необходимо использовать не ту модель, которая устанавливается автоматически после сброса, необходимо изменить значение бита B как можно раньше, до того, как будет выполнен первый доступ к полуслову или слову либо до переключения на выполнение кода Thumb или Jazelle. Другие средства управления порядком байтов и невыровненными доступами в версиях до ARMv6 отсутствуют, хотя из документации можно сделать вывод, что бит A в некоторых процессорах мог присутствовать и ранее.
Процессоры версии ARMv6 всегда поддерживают модели LE и BE-8; модель BE-32 является необязательной. Модель BE-8 распространяется только на данные; когда она активна, для доступа к коду используется модель LE. Бит B реализован только в тех процессорах ARMv6, которые поддерживают все три модели, и используется в целях обеспечения совместимости с предыдущими версиями архитектуры. Остальные четыре бита присутствуют во всех процессорах ARMv6.
При сбросе бит A всегда сбрасывается, что отключает контроль за невыровненными доступами. Остальные четыре бита устанавливаются в зависимости от состояния конфигурационных линий CFGEND[1:0], как показано в следующей таблице.
CFGEND[1:0] | EE | U | B | E | Описание |
---|---|---|---|---|---|
00 | 0 | 0 | 0 | 0 | Модель LE для кода и данных без невыровненных доступов |
01 | 0 | 0 | 1 | 0 | Модель BE-32 для кода и данных |
10 | 0 | 1 | 0 | 0 | Модель LE для кода и данных, поддержка невыровненных доступов |
11 | 1 | 1 | 0 | 1 | Модель LE для кода и BE-8 для данных, поддержка невыровненных доступов |
Комбинация линий CFGEND[1:0], равная 01, трактуется как 00, если процессор не поддерживает модель BE-32. В тех процессорах, где линии CFGEND[1:0] отсутствуют, устанавливается режим, соответствующий нулевым значениям на этих линиях. В процессорах, предшествовавших ARMv6 и поддерживающих две модели следования байтов, для выбора модели по умолчанию использовалась конфигурационная линия BigEndinit.
Комбинации битов U и A позволяют выбрать следующие варианты работы с невыровненными доступами:
U | A | Описание |
---|---|---|
0 | 0 | Унаследованный режим для совместимости с версиями до ARMv6, модели LE и BE-32 |
0 | 1 | Контроль выравнивания двойных слов на границу 8 байтов, все три модели |
1 | 0 | Поддержка невыровненного доступа, модели LE и BE-8 |
1 | 1 | Контроль выравнивания двойных слов на границу 4 байтов, все три модели |
Первый вариант (U и A равны нулю) полностью соответствует работе процессоров до ARMv6. Используемая в нём модель следования байтов определяется битом B. В трёх других вариантах для управления моделью следования байтов используются биты B и E.
Используемая модель следования байтов и реакция на невыровненные доступы в зависимости от состояния битов U, A, B и E приведены в следующей таблице. В ней указаны только допустимые комбинации указанных битов; все остальные варианты являются зарезервированными. Результат выполнения инструкций, устанавливающих зарезервированную комбинацию битов, будет непредсказуемым.
U | A | B | E | Модель для инструкций | Модель для данных | Невыровненные доступы | Описание |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | LE | LE | вращение при загрузке слова | унаследованный порядок байтов данных «младший-старший» |
0 | 0 | 1 | 0 | BE-32 | BE-32 | вращение при загрузке слова | унаследованный порядок байтов данных «старший-младший» |
0 | 1 | 0 | 0 | LE | LE | отказ данных | контроль выравнивания двойных слов по границе 8 байтов; порядок данных «младший-старший» |
0 | 1 | 0 | 1 | LE | BE-8 | отказ данных | контроль выравнивания двойных слов по границе 8 байтов; порядок данных «старший-младший» |
0 | 1 | 1 | 0 | BE-32 | BE-32 | отказ данных | контроль выравнивания двойных слов по границе 8 байтов; унаследованный порядок данных «старший-младший» |
1 | 0 | 0 | 0 | LE | LE | нормальный доступ | разрешён невыровненный доступ, порядок данных «старший-младший» |
1 | 0 | 0 | 1 | LE | BE-8 | нормальный доступ | разрешён невыровненный доступ; порядок данных «старший-младший» |
1 | 1 | 0 | 0 | LE | LE | отказ данных | контроль выравнивания двойных слов по границе 4 байтов; порядок данных «младший-старший» |
1 | 1 | 0 | 1 | LE | BE-8 | отказ данных | контроль выравнивания двойных слов по границе 4 байтов; порядок данных «старший-младший» |
1 | 1 | 1 | 0 | BE-32 | BE-32 | отказ данных | контроль выравнивания двойных слов по границе 4 байтов; унаследованный порядок данных «старший-младший» |
Выполнение доступов к памяти при разном выравнивании[]
Список видов доступа к памяти и вызывающих эти доступы инструкций приведён в следующей таблице.
Вид доступа | Инструкции набора ARM | Инструкции набора Thumb |
---|---|---|
Byte | LDRB, LDRBT, LDRSB, STRB, STRBT, SWPB | LDRB, LDRSB, STRB |
Halfword | LDRH, LDRSH, STRH | LDRH, LDRSH, STRH |
WLoad | LDR, LDRT, SWP (только загрузка при U=0) | LDR |
WStore | STR, STRT, SWP (только запись при U=0) | STR |
WSync | SWP (загрузка и запись при U=1) | |
Two-word | LDRD, STRD | |
Multi-word | LDC, LDM, RFE, STC, STM | LDMIA, POP, PUSH, STMIA |
Как выполняются эти виды доступов при различном выравнивании, показано в следующей таблице. Запись Align(Addr) в этой таблице означает, что используется значение адреса, принудительно выровненное на границу слова, т.е. со сброшенными двумя младшими битами. Обнаружение ошибки выравнивания приводит к возникновению отказа данных.
U | A | Addr[2:0] | Вид доступа | Поведение | Обращение к памяти | Примечания |
---|---|---|---|---|---|---|
0 | 0 | Унаследованный режим, без контроля выравнивания | ||||
0 | 0 | xxx | Byte | обычное | Byte[Addr] | |
0 | 0 | xx0 | Halfword | обычное | Halfword[Addr] | |
0 | 0 | xx1 | Halfword | непредсказуемое | ||
0 | 0 | xxx | WLoad | обычное | Word[Aling(Addr)] | Вращение загруженных данных вправо на число байтов, равное Addr[1:0] |
0 | 0 | xxx | WStore | обычное | Word[Aling(Addr)] | Операция не зависит от значения Addr[1:0] |
0 | 0 | x00 | WSync | обычное | Word[Addr] | |
0 | 0 | не x00 | WSync | непредсказуемое | ||
0 | 0 | 000 | Two-word | обычное | Word[Addr] | |
0 | 0 | не 000 | Two-word | непредсказуемое | ||
0 | 0 | xxx | Multi-word | обычное | Word[Align(Addr)] | Операция от значения разрядов Addr[1:0] не зависит |
1 | 0 | Доступ без выравнивания, ARMv6 | ||||
1 | 0 | xxx | Byte | обычное | Byte[Addr] | |
1 | 0 | xxx | Halfword | обычное | Halfword[Addr] | |
1 | 0 | xxx | WLoad, WStore | обычное | Word[Addr] | |
1 | 0 | x00 | WSync, Two-word, Multi-word | обычное | Word[Addr] | |
1 | 0 | не x00 | WSync, Two-word, Multi-word | ошибка выравнивания | ||
x | 1 | Доступ с контролем выравнивания, ARMv6 | ||||
x | 1 | xxx | Byte | нормальное | Byte[Addr] | |
x | 1 | xx0 | Halfword | нормальное | Halfword[Addr] | |
x | 1 | xx1 | Halfword | ошибка выравнивания | ||
x | 1 | x00 | WLoad, WStore, WSync, Multi-word | обычное | Word[Addr] | |
x | 1 | не x00 | WLoad, WStore, WSync, Multi-word | ошибка выравнивания | ||
x | 1 | 000 | Two-word | обычное | Word[Addr] | |
0 | 1 | 100 | Two-word | ошибка выравнивания | ||
1 | 1 | 100 | Two-word | обычное | Word[Addr] | |
x | 1 | xx1, x1x | Two-word | ошибка выравнивания |
Из описанных выше правил существует несколько исключений, приводящих к непредсказуемым последствиям вместо обычного выполнения (но не вместо отказа данных) соответствующих команд:
- попытка загрузки в счётчик команд с помощью команды LDR значения по адресу, не кратному 4;
- попытка загрузки в счётчик команд нового значения с помощью любой инструкции, кроме LDR, LDM, RFE и POP, независимо от выровненности адреса;
- попытка выполнения любой инструкции, выполняющей доступ к слову, двойному слову или группе слов, если её операндом является память с атрибутом «строго упорядоченная» или «память устройства», а адрес не кратен 4;
- попытка выполнения любой инструкции, выполняющей доступ к послуслову, если её операндом является память с атрибутом «строго упорядоченная» или «память устройства», а адрес не является чётным.
Невыровненные доступы не обязательно являются атомарными и могут производить к заметному падению производительности.
Инструкции для изменения порядка байтов[]
В процессорах версии ARMv6 предусмотрена инструкция SETEND, имеющаяся в наборах команд ARM и Thumb. Она устанавливает или сбрасывает бит E текущего регистра состояния программы.
Для программного изменения порядка следования байтов в регистрах общего назначения процессоры ARMv6 имеют команды REV, REVSH и REV16, также присутствующие в системах команд ARM и Thumb.