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

问题描述 投票:0回答:3

ARM7 命令集提供了在汇编程序中将 32 位值右旋转任意量的有效方法。对于操作的第二个操作数,它甚至可以通过指定 ror #n 作为移位器操作数来“免费”,但对于 64 位整数,指令集不提供直接支持。除了旋转 1、31、33 或 63 位位置(更不用说 0 或 32)的特殊情况外,我只知道如何使用 four 指令旋转 64 位值(这很简单,所以我不知道)不写在这里)。在四种特殊情况下,我可以将其减少为三个指令,但我不知道一般情况下该怎么做。所以这是我的问题:

给定两个寄存器(例如 R0 和 R1)中的 64 位值,是否可以仅使用 ARM7 指令将该值右旋转 n 位置(对于任意 n)?

assembly arm bit-manipulation arm7
3个回答
2
投票

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

 umull r3,r2,r1,r4
  乌姆拉尔 r2,r3,r0,r4

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


1
投票

如果有解决方案,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

0
投票
#include <stdint.h>

uint64_t rotl64 ( uint64_t x, int8_t r )
{
  return (x << r) | (x >> (64 - r));
}

变成:

rotl64(unsigned long, signed char):
        sxtb    w1, w1
        neg     w1, w1
        ror     x0, x0, x1
        ret

https://godbolt.org/z/6bjsW1avh

© www.soinside.com 2019 - 2024. All rights reserved.