如何在 32 位 ARM 汇编器中有效地右旋转 64 位值?

发布于 2024-10-25 01:10:18 字数 3127 浏览 4 评论 0原文

ARM7 命令集 (ARM7TDMI = ARMv4T) 提供了在汇编程序中将 32 位值右旋转任意量的有效方法。对于操作的第二个操作数,通过将 ror #n 指定为移位操作数,它甚至是“免费”的,但对于 64 位整数,指令集不提供直接支持。

除了旋转 1、31、33 或 63 位位置(更不用说 0 或 32)的特殊情况外,我只知道如何使用四个指令(就像编译器对常量计数所做的那样,使用 2x )。在四种特殊情况下,我可以将其减少为三个指令,但我不知道一般情况下该怎么做。所以这是我的问题:

给定两个寄存器中的 64 位值,例如 R0 和 R1,是否可以将该值右旋转 n 个位置(对于任意 n )只有三个 ARM7 指令?或者,如果有任何更新的 ARMv7 甚至 AArch32 ARMv8 指令可用,那也会很有趣。

The ARM7-command set (ARM7TDMI = ARMv4T) offers efficient ways to right rotate 32-bit values by an arbitrary amount in assembler. For the 2nd operand of an operation it is even "for free" by specifying ror #n as shifter operand, but for 64-bit integers no direct support by the instruction set is given.

Besides the special cases of rotating by 1, 31, 33 or 63 bit positions (not to mention 0 or 32), I only know how to rotate a 64-bit value using four instructions (like compilers do for constant counts, using 2x ). In the four special cases I can reduce this to three instructions, but I don't know how to do it in general. So here is my question:

Given a 64-bit value in two registers, say R0 and R1, is it possible to right rotate this value by n positions (for arbitrary n) with just three ARM7 instructions? Or if any newer ARMv7 or even AArch32 ARMv8 instructions are available, that would also be interesting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吖咩 2024-11-01 01:10:18

如果一个寄存器(例如 r4)碰巧保存了正确的魔术常数(1 左移了所需的左旋转量),我认为可以用两条指令来完成:

  umull r3,r2,r1,r4
  umlal r2,r3,r0,r4

比使用四个单周期指令慢,但即使有一个用适当的常量加载 r4 它仍然比四指令方法更紧凑。

If a register (e.g. r4) happens to hold the proper magic constant (1 shifted left by the desired left-rotate amount) I think one can do it in two instructions:

  umull r3,r2,r1,r4
  umlal r2,r3,r0,r4

Slower than using four single-cycle instructions, but even if one has to load r4 with the proper constant it's still more compact than the four-instruction methods.

乞讨 2024-11-01 01:10:18

如果有解决方案,gcc 也无法识别它:

unsigned long long int reg64 = random_value;
unsigned int n = shift_value;
reg64 = (reg64 >> (n%64)) | (reg64 << ((64-n)%64));

结果如下:

n=1:

MOVS R2, R0, LSR #1
MOV R3, R1, RRX
ORR R2, R2, R1, ASL #31

n=2-31:

MOV R2, R0, LSR #n
ORR R2, R2, R1, ASL #32-n
MOV R3, R0, ASL #32-n
ORR R3, R3, R1, LSR #n

n=33-62:

MOV R3, R0, ASL #64-n
ORR R3, R3, R1, LSR #n-32
MOV R2, R0, LSR, #n-32
ORR R2, R2, R1, ASL #64-n

n=63:

ADDS R2, R0, R0
ADC R3, R1, R1
ORR R2, R2, R1, LSR #31

If there is a solution to this, gcc also doesn't recognize it:

unsigned long long int reg64 = random_value;
unsigned int n = shift_value;
reg64 = (reg64 >> (n%64)) | (reg64 << ((64-n)%64));

results in the following:

n=1:

MOVS R2, R0, LSR #1
MOV R3, R1, RRX
ORR R2, R2, R1, ASL #31

n=2-31:

MOV R2, R0, LSR #n
ORR R2, R2, R1, ASL #32-n
MOV R3, R0, ASL #32-n
ORR R3, R3, R1, LSR #n

n=33-62:

MOV R3, R0, ASL #64-n
ORR R3, R3, R1, LSR #n-32
MOV R2, R0, LSR, #n-32
ORR R2, R2, R1, ASL #64-n

n=63:

ADDS R2, R0, R0
ADC R3, R1, R1
ORR R2, R2, R1, LSR #31
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文