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

 
 
 
Reply to this topicStart new topic
> Type double (64-bit) and IAR/gcc
RCray
сообщение Nov 16 2011, 17:33
Сообщение #1


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Что вижу:
Передача 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.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 16 2011, 17:45
Сообщение #2


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Эти различия видимо уже определяются соответствию-несоответствию abi-eabi стандарту.
И одного рецепта тут ИМХО нет. Попробуйте разные сборки gcc (eabi noneabi) может что-то прояснится.
Опять же можно поискать описание на eabi и посмотреть что там на сей счёт имеется.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
RCray
сообщение Nov 16 2011, 17:53
Сообщение #3


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



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


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

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

или про eabi вы имели ввиду ключики? пошёл играться!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 16 2011, 17:54
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



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

По совокупности стандартов, в little-endian системе double должен передаваться как R0=LSB, R1=MSB. Т.е. IAR поступает корректно.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Nov 17 2011, 10:19
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



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 делать что-то подобное невозможно, требуются дополнительные команды.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
RCray
сообщение Nov 17 2011, 11:16
Сообщение #6


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Спасибо за ответы.

Как и ожидалось документ "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.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 17 2011, 11:48
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(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.
Go to the top of the page
 
+Quote Post
RCray
сообщение Nov 17 2011, 12:38
Сообщение #8


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Цитата
• 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 имеют какие-то адреса?
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 17 2011, 12:41
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(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.
Go to the top of the page
 
+Quote Post
RCray
сообщение Nov 17 2011, 13:33
Сообщение #10


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Хм, тут вы правы. LDM для IAR/gcc при пересылке 64-бит (LDM R4, {R0, R1}) ведёт себя одинаково, так почему же в вызове функции по-разному...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Nov 17 2011, 13:41
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(RCray @ Nov 17 2011, 17:33) *
Хм, тут вы правы. LDM для IAR/gcc при пересылке 64-бит (LDM R4, {R0, R1}) ведёт себя одинаково, так почему же в вызове функции по-разному...

Подозреваю, что у gcc должны быть какие-нибудь ключики на эту тему.
Go to the top of the page
 
+Quote Post
RCray
сообщение Nov 17 2011, 15:18
Сообщение #12


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

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



в моём 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, которые отрабатывают правильно, как я и говорил постом выше.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 12:09
Рейтинг@Mail.ru


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