Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Type double (64-bit) and IAR/gcc
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
RCray
Что вижу:
Передача double числа в качестве единственного параметра в функцию для IAR и для gcc приводит разному расположению частей double числа в регистрах R0:R1.

Тип - little-endian, процессор один и тот же.

Как воспроизвожу:
во время вызова

double function (double x);
a = function (2.0);

в IAR число 2.0 попадает как
R0 0x00000000
R1 0x40000000

в gcc число 2.0 попадает как
R0 0x40000000
R1 0x00000000


Теория:
Говорит о том, что long long, double и прочие больше 32-бит попадают в последовательные регистры R0:R1 или R2:R3.
Либо покажите где есть уточнения.


Как мне код-то писать на асме?
Стандартного разделения на big и little endian'а получается, что уже не хватает. Ещё привязываться и к компилятору? Или скажите какие вы видите результаты под разными компиляторами?


IAR 6.30.1
gcc 4.4.0

CPU - ARM Cortex.
demiurg_spb
Эти различия видимо уже определяются соответствию-несоответствию abi-eabi стандарту.
И одного рецепта тут ИМХО нет. Попробуйте разные сборки gcc (eabi noneabi) может что-то прояснится.
Опять же можно поискать описание на eabi и посмотреть что там на сей счёт имеется.
RCray
Цитата(demiurg_spb @ Nov 16 2011, 21:45) *
Эти различия видимо уже определяются соответствию-несоответствию abi-eabi стандарту.
И одного рецепта тут ИМХО нет. Попробуйте разные сборк gcc eabi noneabi может что-то прояснится.
Опять же можно поискать описание на eabi и посмотреть что там на сей счёт имеется.


Говоря про теорию я и имел ввиду документы по EABI. В них просто отмалчиваются про последовательные регистры R0:R1, R2:R3.
Сборка gcc у меня одна для этого ядра.

Вопрос собственно в том - какие результаты лично у коллег.
А за разъяснениями уже к суппорту.

или про eabi вы имели ввиду ключики? пошёл играться!
aaarrr
Цитата(RCray @ Nov 16 2011, 21:49) *
Говоря про теорию я и имел ввиду документы по EABI. В них просто отмалчиваются про последовательные регистры R0:R1, R2:R3.

По совокупности стандартов, в little-endian системе double должен передаваться как R0=LSB, R1=MSB. Т.е. IAR поступает корректно.
Сергей Борщ
QUOTE (RCray @ Nov 16 2011, 20:53) *
Вопрос собственно в том - какие результаты лично у коллег.
Мне нужно было использовать функции, созданные под IAR в коде для avr-gcc. Аргументы были типа uint16_t, которые IAR размещает в R16:R17 а GCC в R24:R25. Задача легко решилась использованием инлайн-асма. Возможно вам подойдет это решение:
CODE
uint16_t driver::serial_no()
{
    register uint16_t result asm ("r16");
    asm volatile
    (
    "  RCALL  drv_serial_no\n\t"
    : "=r" (result)
    :
    );
    return result;
}

void driver::rf::init(uint16_t coeff)
{
    register uint16_t Tmp asm("r16");
    Tmp = coeff;
    asm volatile
    (
    "        RCALL  drv_synth_init\n    "
    :"+r" (Tmp)
    );
}
А вот заставить IAR делать что-то подобное невозможно, требуются дополнительные команды.
RCray
Спасибо за ответы.

Как и ожидалось документ "Procedure Call Standard for the ARM® Architecture" определяет только то что long long кладётся в R0:R1 и R2:R3 а куда точно кладётся least significant word, а куда most не определено и даётся на откуп компилятору.

Пришлось ввести условную компиляцию по IAR и по gcc.

Цитата
5.1.1.1 Handling values larger than 32 bits Fundamental types larger than 32 bits may be passed as parameters to, or returned as the result of, function calls.
When these types are in core registers the following rules apply:
† A double-word sized type is passed in two consecutive registers (e.g., r0 and r1, or r2 and r3). The content of the registers is as if the value had been loaded from memory representation with a single LDM instruction.
† A 128-bit containerized vector is passed in four consecutive registers. The content of the registers is as if the value had been loaded from memory with a single LDM instruction.
aaarrr
Цитата(RCray @ Nov 17 2011, 15:16) *
Как и ожидалось документ "Procedure Call Standard for the ARM® Architecture" определяет только то что long long кладётся в R0:R1 и R2:R3 а куда точно кладётся least significant word, а куда most не определено и даётся на откуп компилятору.

Это не так.

AAPCS:
Цитата
The encoding of floating point numbers is described in [ARM DDI 0100E] chapter C2, VFP Programmer’s Model, §2.1.1 Single-precision format, and §2.1.2 Double-precision format.

Цитата
A double-word sized type is passed in two consecutive registers (e.g., r0 and r1, or r2 and r3). The content of the registers is as if the value had been loaded from memory representation with a single LDM instruction.


DDI 0100, C2.1.2:
Цитата
When held in memory, the two words must appear consecutively and must both be word-aligned. The order
of the two words depends on the endianness of the memory system:
• In a little-endian memory system, the least significant word appears at the lower memory address and
the most significant word at the higher memory address.
• In a big-endian memory system, the most significant word appears at the lower memory address and
the least significant word at the lower memory address.
RCray
Цитата
• In a little-endian memory system, the least significant word appears at the lower memory address and
the most significant word at the higher memory address.
• In a big-endian memory system, the most significant word appears at the lower memory address and
the least significant word at the lower memory address


регистры Rx в ARM имеют какие-то адреса?
aaarrr
Цитата(RCray @ Nov 17 2011, 16:38) *
регистры Rx в ARM имеют какие-то адреса?

Цитата
The content of the registers is as if the value had been loaded from memory representation with a single LDM instruction.
RCray
Хм, тут вы правы. LDM для IAR/gcc при пересылке 64-бит (LDM R4, {R0, R1}) ведёт себя одинаково, так почему же в вызове функции по-разному...
aaarrr
Цитата(RCray @ Nov 17 2011, 17:33) *
Хм, тут вы правы. LDM для IAR/gcc при пересылке 64-бит (LDM R4, {R0, R1}) ведёт себя одинаково, так почему же в вызове функции по-разному...

Подозреваю, что у gcc должны быть какие-нибудь ключики на эту тему.
RCray
в моём gcc всё оказалось гораздо прозаичней (и хуже), я сразу не догадался посмотреть на представление.
double (long long) если его представить как msw(32 бита):lsw(32 бита) ложится

msw на младшие адреса, lsw на старшие, т.е. 10.0
0x2001BE88 = 0x40240000
0x2001BE8C = 0x00000000

у IAR'а ложится наоборот
0x2001BE88 = 0x00000000
0x2001BE8C = 0x40240000

и это всё little-endian.

а в итоге вызов функции не влияет, т.к. если посмотреть дизассемблер, то вызов функции это две инструкции - ldm и bl, которые отрабатывают правильно, как я и говорил постом выше.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.