Эльбрус/портирование

Материал из ALT Linux Wiki

Перенос ПО на платформу Эльбрус

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

В ALT RPM реализован макрос %e2k, рекомендуемый к применению в %ifarch.

configure: error: cannot guess build type; you must specify one

В архив исходников программы включены устаревшие копии этих файлов, поддержка e2k добавлена в gnu-config в 2015 году; достаточно обновить их вручную из свежей системной версии этого пакета или automake (который с большей вероятностью окажется под рукой) либо выполнить autoreconf -fisv:

cp -aLt . -- /usr/share/automake/config.{guess,sub}

В %changelog можно добавить, например[1]:

- fix build on newer arches

тесты на порядок байтов/битность

Нередко попадаются программы, которые интересует только длина указателей (размер integer) и, возможно, endianness; поскольку e2k -- 64-разрядная LE-архитектура, ищем подстроку вроде __amd64__, читаем контекст, добавляем аналогично __e2k__.

В альтовых пакетах на cmake исправления проверок битности порой выглядят примерно так[2]:

-%ifarch x86_64
+%if "%_lib" == "lib64"
 export LIB_SUFFIX=64
 %endif
- fixed build on 64-bit architectures

В проектах на boost порой попадается тот ax_boost_base.m4, где в тест на lib64 забит список архитектур; его придётся поправить перед запуском autoreconf[3] как-то так:

%ifarch %e2k ppc64le riscv64
sed -i 's,aarch64,&|riscv64|ppc64le|e2k,' m4/ax_boost_base.m4
%endif

Про невыровненный доступ к памяти на версиях архитектуры до пятой включительно ("Эльбрус-8СВ") известно, что он достаточно дорогой; поэтому про unaligned access интересующемуся коду можно сообщить, что таковой отсутствует.

SIMD

Алгоритм портирования таких программ простой:

  1. ищем в исходниках макрос __x86_64__[4] или на худой конец i386; если они покрывают фрагменты кода с SIMD-интринсиками (функции, имена которых начинаются на _mm_), то нам повезло;
  2. заменяем defined __x86_64__ на defined __x86_64__ || defined __e2k__;
  3. если попадается динамическая проверка наличия MMX/SSE, то указываем, что у нас всё есть до SSE4.1[5];
  4. к asm-вставкам нужно творчески подходить, но чаще проще готовый generic-вариант кода использовать.
Примечание: несмотря на некоторую аппаратную поддержку выполнения SIMD-инструкций, по сути они реализуются в компиляторе и осмысленность задействования может отличаться от проекта к проекту -- возможно замедление, особенно на AVX* и архитектурах ранее e2kv5.


отсутствие makecontext()

На Эльбрусах makecontext_e2k() выделяет память под дополнительные стеки, поэтому если просто заменить s/makecontext/makecontext_e2k/, в программе может появиться утечка памяти. Нужно ещё поставить вызов freecontext_e2k() там, где выделенный для makecontext_e2k() ucp.uc_stack перестаёт использоваться под данный контекст, т.е. где:

  1. ucp.uc_stack освобождается через free();
  2. ucp.uc_stack переиспользуется, например, под другой контекст.

отсутствие cpuid.h

Обуславливаем соответствующий #include и обращения к функциям так:

#if defined(__i386__) || defined(__x86_64__)

...не забывая добавить подходящую по смыслу заглушку вместо результата функции.

При необходимости подробного различения процессоров "Эльбрус" обратите внимание на __builtin_cpu_is(); в lcc от 1.23.23 и 1.24.10 должны быть доступны более удобные __builtin_cpu_name() и __builtin_cpu_arch() (#4484).

Ссылки

Примечания

  1. поскольку затрагивает и riscv64, и обычно aarch64
  2. либо можно задействовать %_libsuff
  3. или найти этот фрагмент в уже сгенерированном configure, что несколько сложней
  4. или же __amd64__
  5. расширения системы команд SSE4.2 и AVX1 в каком-то виде также поддержаны в компиляторе, но, возможно, быстрее не будет