Насколько я понимаю, в SPARC 32-разрядные целочисленные величины хранятся в одиночных регистрах, а 64-разрядные целочисленные величины хранятся в смежных парах регистров, причем четный регистр содержит старшие 32 бита, а нечетный регистр - младшие. 32 бита.
Мне нужно написать несколько специализированных макросов SPARC для встроенной сборки (функции встроенной сборки тоже подойдут), которые работают с 64-битными целочисленными парами двойных слов, и я не могу понять, как ссылаться вообще (используя расширенную встроенную сборку GCC) ) к двум половинкам пары в моей встроенной сборке. Хотя мои макросы сборки будут немного более сложными, чем макрос MULTIPLY (), показанный ниже, пример умножения, если он сработает, продемонстрирует, как работать с двумя половинами 64-битной пары двойных слов. Может кто-нибудь сказать мне, как исправить мой макрос MULTIPLY ()?
В случае, если это имеет значение, я на ...
bash-2.03 $ uname -a
SunOS [...] 5.8 Generic_117350-39 sun4u sparc SUNW, Ultra-80
Вот мой тривиальный пример программы (на C):
#include <stdio.h>
//#include <stdint.h>
#define uint32 unsigned long int
#define uint64 unsigned long long int
#define MULTIPLY(r, a, b) /* (r = a * b) */ \
asm("umul %1, %2, %0;" /* unsigned mul */ \
: /* regs out */ "=h"(r) \
: /* regs in */ "r"(a), "r"(b));
#if 0
: /* clobbers */ "%y" );
#endif
int main(int argc, char** argv)
{
uint64 r;
uint32 a=0xdeadbeef, b=0xc0deba5e;
// loses the top 32 bits of the multiplication because the result is
// truncated at 32 bits which then gets assigned to the 64-bit 'r'...
r = a * b;
printf("u64=u32*u32 ----> r=a*b "
"----> 0x%016llx = 0x%x * 0x%x\n",
r, a, b);
// force promotion of 'a' to uint64 to get 64-bit multiplication
// (could cast either a or b as uint64, which one doesn't matter,
// as one explicit cast causes the other to be promoted as well)...
r = ((uint64)a) * b;
printf("u64=u64*u32 ----> r=((u64)a)*b "
"----> 0x%016llx = 0x%x * 0x%x\n",
r, a, b);
MULTIPLY(r, a, b);
printf("u64=u64*u32 ----> MULTIPLY(r,a,b) "
"----> 0x%016llx = 0x%x * 0x%x\n",
r, a, b);
return 0;
}
Который при компиляции с gcc-3.2-sun4u/bin/gcc -o mult -mcpu=ultrasparc mult.c
дает такой вывод:
u64=u32*u32 ----> r=a*b ----> 0x00000000d3c7c1c2 = 0xdeadbeef * 0xc0deba5e
u64=u64*u32 ----> r=((u64)a)*b ----> 0xa7c40bfad3c7c1c2 = 0xdeadbeef * 0xc0deba5e
u64=u64*u32 ----> MULTIPLY(r,a,b) ----> 0xd3c7c1c2deadbeef = 0xdeadbeef * 0xc0deba5e
Я посмотрел на вывод -S -fverbose-asm
gcc, и он делает странное смещение регистра результата (который является четным) и записывает в соседний нечетный регистр. Моя проблема в том, что я не знаю, как в общем случае ссылаться на соседний нечетный регистр в расширенном синтаксисе asm. Я подумал, что ограничение 'h' asm в "=h"(r)
может иметь к этому какое-то отношение, но я не могу найти примеров того, как его использовать.