Assembly 如何在ARM7汇编程序中高效地右转64位值?

Assembly 如何在ARM7汇编程序中高效地右转64位值?,assembly,arm,bit-manipulation,arm7,Assembly,Arm,Bit Manipulation,Arm7,ARM7命令集提供了在汇编程序中将32位值右转任意数量的有效方法。对于一个操作的第二个操作数,通过指定ror#n作为移位器操作数,它甚至是“免费的”,但对于64位整数,指令集不提供直接支持。除了按1、31、33或63位位置旋转的特殊情况(更不用说0或32位),我只知道如何使用四条指令旋转64位值(这很容易,所以我不在这里写)。在四种特殊情况下,我可以将其简化为三种说明,但一般来说我不知道如何操作。所以我的问题是: 在两个寄存器(例如R0和R1)中给定一个64位值,是否可以仅使用三个ARM7指令将

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


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

如果有解决方案,gcc也不会识别它:

unsigned long long int reg64 = random_value;
unsigned int n = shift_value;
reg64 = (reg64 >> (n%64)) | (reg64 << ((64-n)%64));
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:

如果寄存器(例如r4)恰好保持适当的魔常数(1向左移动所需的左旋转量),我认为可以通过两条指令来实现:

umull r3,r2,r1,r4 umlal r2,r3,r0,r4 umull r3、r2、r1、r4 umlal r2、r3、r0、r4
比使用四条单周期指令慢,但即使必须使用适当的常数加载r4,它仍然比四条指令方法更紧凑。

感谢您试用gcc。事实上,n=33需要四个命令(而不是使用n=1的公式,并交换R0和R1),这表明在ARM中旋转64位整数不是非常优化的。一般来说,ARM ISA对于编译器来说非常困难。它是供人类使用的。@ninjalj:我猜一些人类硬编码了gcc中的特殊情况n=1和n=63。谢谢,因为人们可以在一个命令中设置r4中的正确值,这回答了我的问题!但是-正如你所猜测的-我一直在寻找一个更有效的版本,所以我可能会等待一周,希望在接受你的答案之前得到一个三个周期的三个命令解决方案。你需要切掉并组合四个部分单词,除了乘法之外,ARM7-TDMI指令都不能写入,也不能应用移位,不止一个寄存器。我也不太希望在三个周期的解决方案中存在三个命令。但谁也不知道。也许有一个神奇的第一个命令,它允许用接下来的两个命令来解决问题。
ADDS R2, R0, R0
ADC R3, R1, R1
ORR R2, R2, R1, LSR #31
umull r3,r2,r1,r4 umlal r2,r3,r0,r4