реклама на сайте
подробности

 
 
> Использование inline assembler в ARM GCC
ek74
сообщение Apr 18 2007, 11:51
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 81
Регистрация: 4-08-05
Из: г. Саратов
Пользователь №: 7 351



Возникла проблема при использовании inline assembler в ARM GCC. Есть следующий работающий код:
Код
typedef signed long        fr32;
typedef signed long long fx64;

fr32 fr32_mul(fr32 arg1, fr32 arg2)
{
  fr32 result;
  asm
  (
    "smull ip, r3, %1, %2    \n"
    "mov  ip, ip, lsr #%a3    \n"
    "orr    %0, ip, r3, lsl #2    \n"
    : "=r" (result)
    : "r" (arg1), "r" (arg2), "I" (FR32_FRACTION_BITS)
    : "r3", "ip"
    );
  return result;
}

В нём аргумены и результат ("=r" (result), "r" (arg1), "r" (arg2)) 32-битные, а как описать 64-битные данные непонятно?
Код
fx64 fx64_mul(fx64 arg1, fx64 arg2)
{
  fx64 result;
  asm
  (
...
    : "=r" (result)        // <- Какие модификатор тут должны быть ?
    : "r" (arg1), "r" (arg2)    // <- Какие модификатор тут должны быть ?
  );
return result;
}

Есть, конечно, вариант реализовать аргументы и результат через объединение:
Код
union
{
  fx64 value;
  struct
  {
    signed long msw;
    unsigned long lsw;
  } words;
};

Но может, есть способ проще?

К слову сказать для msp430 gcc существуют модификаторы:
Код
• %A[tag] acts as %[tag] for a register or address constant operand, or wraps an integer value as #llo(). #llo is an
assembler macro, which extracts the lower 16 bits of the value.
• %B[tag] adds 1 to a register number, or 2 to an address constant, or substitutes #lhi() for an integer constant.
• %C[tag] adds 2 to a register number, or 4 to an address constant, or substitutes #hlo() for an integer constant.
• %D[tag] adds 3 to a register number, 6 to an address constant, or substitutes #hhi() for an integer constant.

#define LONGVAL 0x12345678l
{
  long a, b;
...
  asm("mov %A2, %A0 \n\t"
         "mov %B2, %B0 \n\t"
         "mov %A2, %A1 \n\t"
         "mov %B2, %B1 \n\t"
         : "=r"((long)a), "=m"((long)b)
         : "i"((long)LONGVAL) );
...
}

А вот для arm gcc, я что-то подобного не нашёл.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Alex03
сообщение Apr 19 2007, 17:35
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034



Немного не по вопросу, но...
Если оно не инлайн, то что мешает полностью асм-овую функцию написать?
Можно опять же встроенную в С, только объявить её c __attribute__((naked)), стандарт на ARM по передаче параметров вроде компиляторами поддерживается.

Ещё не понял про FR32_FRACTION_BITS и "lsl #2". У Вас FR32_FRACTION_BITS может быть только 30? Или не нашли как из 32-х вычесть FR32_FRACTION_BITS (видимо можно так "lsl #(32 - %a3)" )?

Кстати код
Код
    b3 = (fr32)((((int64_t) b1) * ((int64_t) b2)) >> FR32_FRACTION_BITS);

Генерит без учёта загрузки значений в регистры и сохранение результата
на -O1 .. -O3
Код
    smull r1, r0, r2, r3
    mov r3, r0, lsr #0x1e
    orr r3, r3, r1, lsl #0x02
    mov r4, r1, asr #0x1e     // лишняя командочка r4 потом не используется


А на -Os вообще то что надо.
Код
    smull r3, r12, r1, r2
    mov r12, r12, lsr #0x1e
    orr r1, r12, r3, lsl #0x02

При этом на -Os GCC ещё и заинлайнил fr32_mul() вот в таком коде
Код
    a3 = fr32_mul(a1, a2);
    b3 = (fr32)((((int64_t) b1) * ((int64_t) b2)) >> FR32_FRACTION_BITS);



GCC - 4.1.2
PS Ещёб ответ на исходный вопрос найти. smile.gif

Упс!
Про -Os наврал.
Код
         mov r4, r1, asr #0x02

там присутствует, просто код настолько наоптимизирован (перепутан) что строки
Код
    a3 = fr32_mul(a1, a2);
    b3 = (fr32)((((int64_t) b1) * ((int64_t) b2)) >> FR32_FRACTION_BITS);

на практике выполняются практически в обратном порядке.
Go to the top of the page
 
+Quote Post



Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 18:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01401 секунд с 7
ELECTRONIX ©2004-2016