使用int32_t访问int64_t的高低部分

时间:2015-03-03 09:56:07

标签: c struct unions

我正在开发一个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;
} 

2 个答案:

答案 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_tint64_t重叠并写入一个并从另一个读取不是严格别名安全的,尽管它在实践中会起作用。)< / p>