Преобразование C/C++ int в короткий и встроенный ассемблер (для ARM)

Это не тривиальный вопрос.
ПРИМЕЧАНИЕ: Мне не нужны мнения или советы, чтобы использовать чистый ассемблер. На самом деле мне нужно сделать то, о чем я говорю: получить встроенный ассемблер без этого кода расширения знака/нуля при присвоении результата короткому int.

Я имею дело с библиотекой, которая злоупотребляет 16-битными шортами для многих функций, и я оптимизирую ее. Мне нужно добавить несколько оптимизированных функций со встроенным asm. Проблема в том, что во многих местах результат функции присваивается короткому int. То есть компилятор генерирует код операции uxth или sxth arm.

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

Проблема в том, что я понятия не имею, как пропустить преобразование int->short, которое компилятор генерирует внутри моей собственной функции.
Тупое приведение вида: *(short*)(void*)&valueне работает. Компилятор либо начинает возиться со стеком, еще больше усугубляя проблему, либо все еще использует тот же sxth для расширения результата по знаку.

Я компилировал для нескольких компиляторов, и мне удалось разрешить это для компилятора armcc, но я не могу сделать это с помощью GCC (я компилирую с 4.4.3 или 4.6.3). С armcc я использую короткий тип внутри встроенного оператора asm. В gcc, даже если я использую шорт, компилятор все равно почему-то считает, что требуется расширение знака.

Вот простой фрагмент кода, который я не могу заставить работать с GCC. Что посоветуете, как заставить его работать? Для этого простого примера я буду использовать инструкцию clz:

пример файла test.cфайл:

static __inline short CLZ(int n)
{
    short ret;
#ifdef __GNUC__
    __asm__("clz %0, %1" : "=r"(ret) : "r"(n));
#else
    __asm { clz ret, n; }
#endif
    return ret;
}

//test function
short test_clz(int n)
{
    return CLZ(n);
}



вот ожидаемый результат, который я получаю с помощью armcc -c -O3:

test_clz:
    CLZ      r0,r0
    BX       lr

Вот неприемлемый результат, который дает мне GCC -c -O3:

test_clz:
    clz r0, r0
    sxth    r0, r0
    bx  lr

Обратите также внимание, что если переписать CLZ с внутренней переменной int ret;вместо short ret;, то armcc генерирует тот же результат, что и GCC.

Быстрая строка для получения ассемблерного вывода с помощью gcc или armcc:
gcc -O3 -c test.c -o test.o && objdump -d test.o > test.s
armcc -O3 -- рука --asm -c test.c

9
задан Pavel P 3 June 2012 в 15:00
поделиться