2010-12-07 4 views
29

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

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

ответ

34

Мир ARM немного грязный.

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

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


  • Есть несколько наборов инструкций:
    1. оригинальная инструкция ARM установленный с 26-битным программным счетчиком (очень старый, вряд ли встречается в настоящее время)
    2. набор инструкций ARM с 32-разрядным счетчиком программ (часто c alled "АРМ-код")
    3. набор команд Thumb (16-битные упрощенные опкоды)
    4. набор команд Thumb-2 (большой палец с расширениями)

Данный процессор может реализовывать несколько инструкции наборы.Новейшим процессором, который знает только 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 требует более строгого выравнивания стека). Конечно, соглашения варьируются в зависимости от набора инструкций и наличия взаимодействия Thumb.

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


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

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

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


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

4

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

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

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

Это на самом деле не ответить на вопрос, как спросил (который был «с точки зрения C программистом «). –

+1

Спасибо за этот ответ. Похоже, что бинарная совместимость довольно хороша, если вы держитесь подальше от операций FP и большого пальца. –

3

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

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

5

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

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

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

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

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

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

+0

Я работаю над операционной системой, которая работает на различных процессорах ARM. Интерфейс программного обеспечения в основном одинаковый для всех из них, поэтому я в основном интересуюсь бинарной совместимостью. У меня такое впечатление, что разница больше похожа на i686 vs i386 или i686 с SSE3: в основном обратно совместима с некоторыми новыми инструкциями. Это точно? –

+0

Что касается команд рукоятки, да, новые ядра добавили новые инструкции. Модули с плавающей точкой, хотя и не совместимы с бинарными, поэтому вы должны быть осторожны. Теоретически вы можете скомпилировать один наименее общий бинарный знаменатель, который работает по всем направлениям, однако он может не работать достаточно хорошо. И/или вы могли бы иметь код if-then-else в программе, если это ядро ​​или что-то обнаружено, тогда используйте его иначе. ARM ARM покажет вам совместимость команд ARM. –

2

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

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