gpt4 book ai didi

c++ - SPARC : How to handle integer doubleword pairs? 的 GCC 内联汇编

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:51:57 28 4
gpt4 key购买 nike

据我了解,在 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

我查看了 gcc 的 -S -fverbose-asm 输出,它正在对结果寄存器(偶数)进行一些奇怪的移位并写入相邻的奇数寄存器。我的问题是我不知道如何在扩展的 asm 语法中一般引用相邻的奇数寄存器。我认为 "=h"(r) 中的 'h' asm 约束可能与此有关,但我找不到任何有关如何使用它的示例。

最佳答案

umul 指令将两个寄存器的下半部分中的两个 32 位(unsigned int)值相乘,并将 64 位结果的下半部分放入目标寄存器。结果的上半部分写入 Y 寄存器。目标寄存器的上半部分被清除。所以你可能想要使用它是这样的:

#define MULTIPLY(u, r, a, b) /* (u,r = a * b) */     \
asm("umul %2, %3, %0;" /* unsigned mul */ \
"rd %%y, %1;" /* get hi word of result */ \
: /* regs out */ "=r"(r), "=r"(u) \
: /* regs in */ "r" (a), "r" (b) \
: /* clobbers */ "%y" );

但是请注意,几乎可以肯定,使用 uint64_tunsigned long long 操作数在 C 中编写乘法肯定会更好。

关于c++ - SPARC : How to handle integer doubleword pairs? 的 GCC 内联汇编,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9879193/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com