Перейти к содержанию
    

GCC, ассемблерные вставки и int64

Добрый день!

Что бы передать внутрь ассемблерной вставки половинки 64-битной переменной, использую union, примерно вот так:

union u_i64
{
	int64_t i64;
	int32_t i32[2];
};

int64_t mul64(int32_t m1, int32_t m2)
{
	register union u_i64 ret;

	asm volatile
	(
		"smull %0, %1, %[m2], %[m1]     \n"
		: "=r" (ret.i32[0]), "=r" (ret.i32[1])
		: [m1] "r" (m1), [m2] "r" (m2)
	);

	return ret.i64;
}

Но хотелось бы, что бы можно было на входе/выходе asm'а указывать непосредственно половинки большой переменной, что-то вроде "res.H" и "res.L".

Или объявлять переменную с явным указанием пары регистров, примерно как register uint64_t res asm ("r0:r1"), тогда можно было бы скормить указанную пару r0 и r1.

Беглый просмотр документации ответа не дал. Это вообще возможно?

Заранее благодарю за ответ.

Компилятор arm-none-eabi-gcc 5.4.1 из состава embitz 1.11, проект для Cortex-M3, если что.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тут как бы напрашивается struct, например:

union u_i64
{
  int64_t i64;
  int32_t i32[2];
  struct 
  {
    int32_t L;
    int32_t H;
  } res;
};

или я не правильно понял замысел ))

 

ps. А чем, если не секрет, не устраивают штатные библиотеки для работы математикой? Они ведь тоже на asm сделаны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Forger, штатные библиотеки устраивают, умножение 32х32 приведено в качестве примера.

Вопрос в том, что бы обойтись без структур, объединений и прочего. Что бы объявить переменную long long, и разбить её на 2 половинки. В avr-ском ассемблере, емнип, были директивы hi/lo, которые позволяли получить доступ к 8-битным половинкам 16-битной переменной.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 minutes ago, Vitёk said:

были директивы hi/lo, которые позволяли получить доступ к 8-битным половинкам

Сделайте макросы для доступа к 32-битным и 8-битным половинкам. По-другому, в общем случае, сделать всё равно не получится. Можно сделать inline-функции вместо макросов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В CMSIS давно куски есть... Попробуйте взять за основу:


__STATIC_FORCEINLINE uint64_t __SMLSLD (uint32_t op1, uint32_t op2, uint64_t acc)
{
  union llreg_u{
    uint32_t w32[2];
    uint64_t w64;
  } llr;
  llr.w64 = acc;

#ifndef __ARMEB__   /* Little endian */
  __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[0]), "=r" (llr.w32[1]): "r" (op1), "r" (op2) , "0" (llr.w32[0]), "1" (llr.w32[1]) );
#else               /* Big endian */
  __ASM volatile ("smlsld %0, %1, %2, %3" : "=r" (llr.w32[1]), "=r" (llr.w32[0]): "r" (op1), "r" (op2) , "0" (llr.w32[1]), "1" (llr.w32[0]) );
#endif

  return(llr.w64);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Vitёk сказал:

Беглый просмотр документации ответа не дал. Это вообще возможно?

А если не бегло просмотреть, а внимательнее?

У IAR похожий синтаксис inline asm и он имеет нативные средства для работы с 64-битными переменными (без всяких костылей типа union):

static u64 volatile zz1;
u64 q0, q1 = 0x300000004ull;
asm("SMULL %0, %1" : "=Rp"(q0) : "Rp"(q1));
zz1 = q0;

.lst:

0x2204             MOVS     R2,#+4
0x2303             MOVS     R3,#+3
0xFB82 0x0103      SMULL R0,R1, R2,R3
0xE9C5 0x0102      STRD     R0,R1,[R5, #+8]

Может и GCC умеет "Rp"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

53 minutes ago, GenaSPB said:

В CMSIS давно куски есть...

По сути я так и делаю - получаю доступ к половинкам через юнион.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 hours ago, Vitёk said:

Компилятор arm-none-eabi-gcc 5.4.1 из состава embitz 1.11, проект для Cortex-M3, если что.

gcc-arm-none-eabi-10.3-2021.07-win32.zip https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads

Будет ругаться на default.specs https://www.embitz.org/forum/thread-4.html, и ebmon.specs - который можно оставить пустым. Для того чтобы работала печать в отладку - использовать мой код https://github.com/AVI-crak/Rtos_cortex/blob/master/monitor.c. При использовании без ос - заменить os_data.system_us на обычный счётчик. Он там как собака работает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

42 minutes ago, jcxz said:

У IAR похожий синтаксис inline asm и он имеет нативные средства для работы с 64-битными переменными ...

Очень близко к тому, что я ищу. Но, к сожалению, компилятор выдаёт ошибку:

Error: bad arguments to instruction -- smull r4,r5

Видимо, в регистровые пары (или что значит Rp) ассемблер не умеет.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 8/23/2021 at 2:36 AM, Vitёk said:

Forger, штатные библиотеки устраивают, умножение 32х32 приведено в качестве примера.

Вопрос в том, что бы обойтись без структур, объединений и прочего. Что бы объявить переменную long long, и разбить её на 2 половинки. В avr-ском ассемблере, емнип, были директивы hi/lo, которые позволяли получить доступ к 8-битным половинкам 16-битной переменной.

 

Можно сделать указатель на 64 битную переменную. Потом, сделав кастинг, присвоить этот указатель указателю на 32, 16 или 8 битное значение. Эти указатели на 32, 16 или 8 можно использовать как массив.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...