Различия между архитектурами ARM с точки зрения программиста на C? - PullRequest
30 голосов
/ 07 декабря 2010

Я довольно новичок в программировании для ARM.Я заметил, что есть несколько архитектур, таких как ARMv4, ARMv5, ARMv6 и т. Д. В чем разница между ними?У них разные наборы команд или поведения?

Самое главное, если я скомпилирую код C для ARMv6, будет ли он работать на ARMv5?А как насчет кода ARMv5, работающего на ARMv6?Или мне пришлось бы беспокоиться только о разнице, если бы я писал код сборки ядра?

Ответы [ 5 ]

35 голосов
/ 08 декабря 2010

Мир ARM немного запутан.

Для программистов на C все просто: все архитектуры ARM предлагают обычную 32-битную модель программирования с плоской адресацией.Пока вы остаетесь с исходным кодом C, единственное отличие, которое вы можете увидеть, - это порядковый номер и производительность.Большинство процессоров ARM (даже старые модели) могут быть как с прямым порядком байтов, так и с прямым порядком байтов;выбор тогда сделан платой логики и операционной системой.Хороший C-код endian-нейтральный : он компилируется и работает правильно, независимо от порядкового номера платформы (endian-нейтральность хороша для надежности и удобства обслуживания, но также и для производительности: ненейтральный код - это код, который обращается к тем же даннымчерез указатели разных размеров, и это наносит ущерб строгим правилам алиасинга, которые компилятор использует для оптимизации кода).

Ситуация совершенно иная, если учесть совместимость бинарную (то есть повторное использование кодакоторый был скомпилирован один раз):


  • Существует несколько наборов команд:
    1. исходный набор команд ARM с 26-битным счетчиком программ (очень старый, очень маловероятныйв наше время)
    2. набор команд ARM с 32-разрядным программным счетчиком (часто называемый «кодом ARM») *
    3. набор команд Thumb (16-разрядные упрощенные коды операций)
    4. набор команд Thumb-2 (Thumb с расширениями)

Данный процессор можетдополняют несколько наборов инструкций.Новейшим процессором, который знает только код ARM, является StrongARM, представитель ARMv4, которому уже достаточно лет (15 лет).ARM7TDMI (архитектура ARMv4T) знает как ARM, так и Thumb, как и почти все последующие системы ARM, за исключением Cortex-M.Код ARM и Thumb могут быть смешаны вместе в одном приложении, при условии, что вставляется соответствующий клей в случае изменения соглашений;это называется совместное использование большого пальца и может обрабатываться автоматически компилятором C.

Cortex-M0 знает только инструкции Thumb.Он знает несколько расширений, потому что в «обычных» процессорах ARM операционная система должна использовать код ARM (для обработки прерываний);таким образом, Cortex-M0 знает несколько вещей Thumb-for-OS.Это не имеет значения для кода приложения.

Другой Cortex-M знает только Thumb-2.Thumb-2 в основном обратно совместим с Thumb, по крайней мере, на уровне сборки.


  • Некоторые архитектуры добавляют дополнительные инструкции.

Таким образом, если какой-то код скомпилирован с переключателем компилятора, говорящим, что это для ARMv6, то компилятор может использовать одну из немногих инструкций с ARMv6, но не с ARMv5.Это обычная ситуация, с которой сталкиваются почти на всех платформах: например, если вы компилируете код C на ПК с помощью GCC, используя флаг -march=core2, то получающийся двоичный файл может не работать на старом процессоре Pentium.


  • Существует несколько соглашений о вызовах.

Соглашение о вызовах - это набор правил, которые определяют, как функции обмениваются параметрами и возвращаемыми значениями.Процессор знает только свои регистры и не имеет понятия о стеке.Соглашение о вызовах сообщает, в какие регистры идут параметры и как они кодируются (например, если есть параметр char, он идет в младших 8 битах регистра, но вызывающий должен очистить / подписать-расширить верхний24 бита или нет?).Он описывает структуру стека и выравнивание.Он нормализует условия выравнивания и заполнения для структурных полей.

Существует два основных соглашения для ARM, которые называются ATPCS (старая) и AAPCS (новая).Они совершенно разные по вопросу значений с плавающей запятой.Для целочисленных параметров они в основном идентичны (но AAPCS требует более строгого выравнивания стека).Конечно, условные обозначения различаются в зависимости от набора инструкций и наличия большого пальца.

В некоторых случаях возможно иметь некоторый двоичный код, который соответствует как ATPCS, так и AAPCS, но это ненадежно и нет предупреждения о несоответствии.Итак, суть заключается в следующем: вы не можете иметь истинную двоичную совместимость между системами, которые используют различные соглашения о вызовах.


  • Есть дополнительные сопроцессоры.

Архитектура ARMмогут быть расширены дополнительными элементами, которые добавляют свои собственные инструкции в основной набор команд.FPU является таким дополнительным сопроцессором (и он очень редко встречается на практике).Другим сопроцессором является NEON, набор инструкций SIMD, найденный на некоторых новых процессорах ARM.

Код, использующий сопроцессор, не будет работать на процессоре, который не поддерживает этот сопроцессор, если только операционная система не перехватывает соответствующие коды операцийи эмулирует сопроцессор в программном обеспечении (это более или менее то, что происходит с аргументами с плавающей запятой при использовании соглашения о вызовах ATPCS, и это медленно ).


Подводя итогЕсли у вас есть C-код, то перекомпилируйте его.Не пытайтесь повторно использовать код, скомпилированный для другой архитектуры или системы.

5 голосов
/ 08 декабря 2010

Думайте об этом ARM против ARM, как о компьютере Wintel против Intel Mac.Предположим, что даже у вас на обоих компьютерах один и тот же чип Intel (семейство), поэтому части кода на C могут быть скомпилированы один раз и работать на обоих процессорах просто отлично.Где и почему ваши программы отличаются друг от друга, не имеет ничего общего с процессором Intel, но в данном случае все связано с чипами и материнской платой вокруг него, а также с операционной системой.

С ARM против ARM большинство различий заключается не в ядре, а в специфической логике поставщика, которая окружает ядро.так что это загруженный вопрос, если ваш код на C - это какое-то приложение, вызывающее стандартные вызовы API, то он должен скомпилироваться на arm, intel или powerpc или где-либо еще.Если ваше приложение начинает взаимодействовать с микросхемой или встроенной периферией, то независимо от типа процессора, одна плата, одна микросхема будут отличаться, и в результате ваш код C должен быть написан для этой микросхемы или материнской платы.Если вы скомпилируете двоичный файл для ARMv6, он может и будет иметь инструкции, которые на ARMv4 считаются неопределенными, и вызовет исключение.Если вы компилируете для ARMv4, ARMv6 должен нормально его запускать.

В лучшем случае, если вы находитесь в этом пространстве приложения, то, скорее всего, вы увидите только различия в производительности.Некоторые из них связаны с вашим выбором в опциях компилятора.И иногда вы можете помочь с вашим кодом.Я рекомендую избегать делений и с плавающей точкой, где это возможно.Я не люблю умножения, но возьму умножение вместо деления при нажатии.x86 избаловал нас невыровненным доступом, если вы начнете сейчас с выровненного ввода-вывода, это спасет вас в будущем, когда вы попадете на другие чипы, которые также предпочитают выровненные доступы, или вы получите кусочек от разных операционных систем изагрузчики настраивают ARM для реакции, ни один из которых не является тем, к чему вы привыкли на x86.Аналогичным образом сохраните эту привычку, и ваш код x86 будет работать намного быстрее.

Получите копию ARM ARM (google: ARM Architectural Справочное руководство, вы можете скачать его бесплатно во многих местах, я не знаю, какая текущая версияесть, рев я или что-то может быть).Просмотрите набор инструкций ARM и убедитесь, что большинство инструкций поддерживаются на всех ядрах, а некоторые были добавлены с течением времени, например, split и byteswap и тому подобное.Вы увидите, что нечего бояться между ядрами.

Подумайте с точки зрения системы, wintel против Intel Mac.ARM не делает чипы, они делают и лицензируют ядра.У большинства производителей, которые используют ARM в своем чипе, есть свой особый соус.Таким образом, это похоже на wintel против Mac с тем же процессором посередине, но совершенно иным, когда дело касается всего того, что процессор касается и должен использовать.Он не останавливается на ядре ARM, ARM продает периферийные устройства, блоки с плавающей запятой, кеши и т. Д. Так мало, например, если ARMv4 одинаковы.Если ваш код касается различий, у вас будут проблемы, если это не так.

Для частей микросхемы в дополнение к ARM ARM имеются TRM (технические справочные руководства).но если вы получите неправильный trm для компонента, который вы используете, он может вызвать головную боль.TRM может иметь описания регистров и другие подобные вещи, которых нет в ARM ARM, но если вы живете в пространстве приложений, вам, вероятно, не понадобится ни одно из них, ни ARM ARM.ARM ARM хорош для образовательных целей, если ничего больше.Понимание того, почему вы не хотите разделять или использовать неприровненный доступ.

4 голосов
/ 07 декабря 2010

ARM сам по себе достаточно совместим при условии, что вы придерживаетесь пользовательского кода (код ядра, конечно, другой). В среде размещенной ОС вы, скорее всего, будете придерживаться ARMv5 (процессоры ARM926).

Большая разница происходит от:

  1. Поведение кэша сильно отличается. Кэш на некоторых ARM даже фактически решается, что может затруднить переключение процессов.
  2. FPU поставляется в нескольких вариантах (VFP, NEON и многое другое!). Многие меньшие процессоры даже не имеют FPU.
  3. Режим большого пальца сильно изменился. Режим Thumb между ARMv5 не переносим на Thumb2 (ARMv6 +) и не поддерживает обратную совместимость.
3 голосов
/ 08 декабря 2010

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

Но весь смысл написания на языке более высокого уровня (даже если он только"высокий" как C) означает не беспокоиться об этом .Все, что вы делаете, это перекомпилируйте .Даже внутри ядра не так много нужно писать на ассемблере;и когда вы должны написать что-то в сборке (то есть, не только для того, чтобы получить максимальную производительность), это, как правило, связано не только с выбором процессора (например, что было отображено в памяти где?)1009 *

2 голосов
/ 16 марта 2014

Очень быстрый и грязный список областей для проверки при переносе между архитектурами в целом:

  • Порядковый номер : использование объединения, приведение типов данных, битовых полей, совместное использование данных
  • Выравнивание : требования к выравниванию, а также рабочие характеристики возможного неприсоединенного доступа
  • Модель памяти : слабый против сильного?
  • Многоядерный : как работает когерентность?
  • Разное : типы данных со знаком и без знака, упаковка структуры данных, использование стека, тип данных enum ...
...