Портирование кода C/C++ VisualDSP на GCC Печать
Добавил(а) microsin   

В большинстве случаев для портирования исходного кода C/C++ среды VisualDSP++ (VDSP) на компилятор GCC достаточно просто перекомпилировать код с использованием Blackfin GCC [2]. Однако Вам нужно позаботиться о различиях дополнительных директив и синтаксиса компиляторов VDSP C/C++ и GCC, поскольку каждый из них определяет свой собственный набор расширений языка. В этой статье рассматривается трансляция между собой этих диалектов (перевод [1]). Всякий раз, когда это возможно, консультируйтесь с документацией на оба компилятора.

[Директивы #pragma]

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

Для большинства моделей процессоров GCC использует не прагмы, а атрибуты, поскольку они более естественно вписываются в стандарт языка.

Declaring Attributes of Functions site:gcc.gnu.org (http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html).

Specifying Attributes of Variables site:gcc.gnu.org (http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html).

Specifying Attributes of Types site:gcc.gnu.org (http://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html).

Например, когда #pragma исходного кода VDSP выглядит следующим образом:

#pragma align 4
char a;

Соответствующий атрибут GCC будет выглядеть так:

char a __attribute__((aligned(4)));

Ниже в таблице перечислено соответствие прагм и ключевых слов VDSP и GCC с описанием.

VDSP
GCC Описание
align num aligned(num) Установить значение выравнивания объектов на указанное число num.
alignment_region num нет аналога Установить выравнивание по умолчанию в num.
alloc malloc Функция возвратит выделенную память.
always_inline always_inline Всегда встраивать код функций (inline) вместо их вызова.
const const Работает так же, как и pure, но без доступа к глобальной памяти.
core(core) нет аналога Распределить символы на разные ядра.
exception exception_handler Функция как обработчик исключения.
file_attr нет аналога Декларировать атрибуты файла.
hdrstop нет аналога Управление остановкой действия прекомпилированного заголовка (precompiled header).
inline inline Встраивать, когда компилятору это понравится.
interrupt interrupt_handler Функция как обработчик прерывания.
interrupt_level нет аналога Функция как определенный обработчик прерывания.
interrupt_reentrant interrupt_handler, nesting Функция как обработчик прерывания, допускающий вложенность вызовов [7].
linkage_name name alias("name") Переименовать декларированный символ.
misra_func(arg) нет аналога Относится к MISRA-C.
never_inline noinline Не встраивать.
nmi nmi_handler Функция как обработчик немаскируемого прерывания (NMI).
no_implicit_inclusion нет аналога Запрет неявного поиска заголовков C++.
no_pch нет аналога Запретить опцию прекомилированного заголовка.
noreturn noreturn Функция, из которой нет возврата.
once once Этот заголовочный файл подключать только один раз.
optimize_as_cmd_line нет аналога Использовать оптимизацию командной строки.
optimize_for_space optimize("Os") Оптимизировать по размеру кода.
optimize_for_speed optimize(2) Оптимизировать по скорости выполнения.
optimize_off optimize(0) Отключить оптимизацию.
overlay нет аналога Функция может быть в оверлее.
pack(align) packed, aligned(num) Упаковать данные с выравниванием num.
pad(align) нет аналога Дополнить объект (нулями?) до указанного выравнивания num.
param_never_null name nonnull(pos) Аргумент функции не может быть NULL.
pgo_ignore нет аналога Игнорировать функцию при использовании оптимизации по профилю (profile guided optimization, PGO, см. [6]).
pure pure Возвращаемое значение то же самое, на базе входных аргументов.
regs_clobbered нет аналога Декларировать clobbered-регистры.
regs_clobbered_call
result_alignment(num) нет аналога Результат всегда выравнивается на num.
retain_name used Всегда сохранять символ.
section(section) section("section") Поместить символ в указанную секцию памяти.
suppress_null_check нет аналога Подавить проверку на NULL в генерируемом коде C++.
symbolic_ref нет аналога Декларировать символ с символической ссылкой.
system_header system_header Это системный заголовок.
weak_entry weak Декларировать символ со слабой связью.

[Что не поддерживается GCC]

Следующие прагмы никак не поддерживаются GCC:

• Loop Optimization (оптимизация циклов)
all_aligned, different_banks, extra_loop_loads, loop_count, loop_unroll, no_alias, no_vectorization, vector_for

• Memory Banks (банки памяти)
code_bank, data_bank, stack_bank, bank_memory_kind, bank_read_cycles, bank_write_cycles, bank_optimal_width

Хотя эти определенные атрибуты не поддерживаются, для обслуживания памяти есть обходные пути, см. on-chip_sram [3].

align

#ifdef __GNUC__
static char buf[SIZE] __attribute__((aligned(4)));
#else
#pragma align 4
static char buf[SIZE];
#endif

linkage_name

#ifdef __GNUC__
int foo (int) asm ("_foo_1");
#else
#pragma linkage_name _foo_1
int foo (int);
#endif

section

#ifdef __GNUC__
volatile u16 sFrame0[FRAMESIZE] __attribute__((section("vd0_sdram")));
#else
section("vd0_sdram") volatile u16 sFrame0[FRAMESIZE];
#endif

[Встроенные функции]

Для портирования кода VDSP с использованием встраиваемых (intrinsic) функций см. статью [4]. 

[Встраивание инструкций ассемблера]

Документацию по использованию встроенных в код инструкций ассемблера, вызов внешних функций на ассемблере из языка C/C++ см. [5].

Constraints for asm Operands site:gcc.gnu.org (http://gcc.gnu.org/onlinedocs/gcc/Constraints.html).

Constraints for Particular Machines site:site:gcc.gnu.org (http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html).

VDSP
GCC Описание
Регистры
a a Регистры общей адресации P0 - P5
p
A e Регистры аккумуляторов A0, A1
e
b b Регистры адресации DAG I0 - I3
i
d d Общие регистры для данных R0 - R7
D
r
E D Четные регистры данных R0, R2, R4, R6
f f Регистры-модификаторы M0 - M3
h нет аналога Старшие половинки регистров данных R0.H, R1.H, ..., R7.H
H нет аналога Младшие или старшие половинки регистров данных R0.H, R0.L, ..., R7.L, R7.H
I нет аналога Пары регистров данных (R0-R1), (R2-R3), (R4-R5), (R6-R7)
l нет аналога Младшие половинки регистров данных R0.L, R1.L, ..., R7.L
L k Регистры счетчика цикла LC0, LC1
n n Compile time constant -
O W Нечетные регистры данных R1, R3, R5, R7

[Библиотеки C и C++ времени выполнения (Run-Time Library)]

Для множества расширений Analog Devices в среде VDSP++ в виде библиотек (C/C++ Run Time Library) нет соответствующего эквивалента для gcc или Linux.

Если Вы сталкиваетесь с ошибками наподобие неразрешимой ссылки на внешнюю функцию, то это один из таких случаев. Здесь ничего сделать нельзя, кроме как понять, что делает оригинальный код, и переписать его как функцию POSIX или Linux.

[Ссылки]

1. Port C/C++ source code from VDSP to GCC site:blackfin.uclinux.org.
2. Blackfin GCC site:blackfin.uclinux.org.
3. Using On-Chip SRAM Memory site:blackfin.uclinux.org.
4. Blackfin GCC Built-in Functions site:blackfin.uclinux.org.
5. Using In-line Assembly, Calling External Assembly from C site:blackfin.uclinux.org.
6. PGO Linker: инструмент размещения кода для процессоров Blackfin.
7. Blackfin FAQ: как обеспечить вложенность прерываний?