Содержание
Адресное пространство
Архитектура 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.