我正在开发一个32位架构,其中int64_t
仅使用最新版本的编译器(软件仿真)定义。由于我们没有完全升级到最后一个编译器,我想用union来管理64位整数并定义基本的算术运算。
我写了这个:
typedef union _int64_u {
int64_t int64;
int64_32 int32;
} int64_u;
typedef struct _int64_32 {
int32_t hi;
int32_t lo;
}
我想澄清以下几点:
此后,添加和子功能的示例:
#pragma inline
#pragma always_inline
int64_u int64_sub(int64_u x, int64_u y)
{
int64_u n;
asm("%0 = %1 - %2;"
: "=d" (n.int32.lo)
: "d" (x.int32.lo), "d" (y.int32.lo));
asm("%0 = %1 - %2 + CI - 1;"
: "=d" (n.int32.hi)
: "d" (x.int32.hi), "d" (y.int32.hi));
return n;
}
#pragma inline
#pragma always_inline
int64_u int64_add(int64_u x, int64_u y)
{
int64_u n;
asm("%0 = %1 + %2;"
: "=d" (n.int32.lo)
: "d" (x.int32.lo), "d" (y.int32.lo));
asm("%0 = %1 + %2 + CI;"
: "=d" (n.int32.hi)
: "d" (x.int32.hi), "d" (y.int32.hi));
return n;
}
答案 0 :(得分:1)
%0 = %1 + %2;
不是我所知道的任何架构中的汇编指令。你甚至不需要像今天这样使用汇编来进行加法/减法
此外,由于您的旧编译器没有64位类型,因此无需声明联合,也不能这样做,因为之前未声明int64_t
。您可以将整个事物作为结构来访问。
#if COMPILER_VERSION <= SOME_VERSION
typedef INT64_T {
uint32_t h, l;
} uint64_t;
uint64_t add(uint64_t x, uint64_t y)
{
uint64_t z;
z.l = x.l + y.l;
z.h = x.h + y.h + (z.l < x.l);
return z;
}
// ...
#endif
现代编译器会认识到这一点,并在拥有它们的架构中变成add/adc
对,因此没有比较和/或分支。
答案 1 :(得分:0)
也许我误解了这些限制,但为什么不做以下的事情?
#ifdef HAS_INT64_T
typedef int64_t int64;
inline int64 int64_sub(int64 x, int64 y) {
return x - y;
}
...
#else /* !HAS_INT64_T */
typedef struct int64 { int32_t hi, lo; } int64;
inline int64 int64_sub(int64 x, int64 y) {
*ASM*
}
...
#endif /* !HAS_INT64_T */
当然,你必须小心使用endianess等。
如果您的编译器支持int64_t
但不支持某些操作,那么您可以按照建议使用union
或定义一些简单的转换函数。我会调用int32_t
组件部件之类的结构。
(值得注意的是,让int32_t
和int64_t
重叠并写入一个并从另一个读取不是严格别名安全的,尽管它在实践中会起作用。)< / p>