【问题标题】:How to right rotate a 64-bit value efficiently in ARM7 assembler?如何在 ARM7 汇编器中有效地右转 64 位值?
【发布时间】:2011-03-21 14:40:31
【问题描述】:

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

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

【问题讨论】:

    标签: assembly arm bit-manipulation arm7


    【解决方案1】:

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

    umull r3,r2,r1,r4 典型的 r2,r3,r0,r4

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

    【讨论】:

    • 谢谢,因为可以在一个命令中在 r4 中设置正确的值,这回答了我的问题!但是 - 正如你所猜测的 - 我正在寻找一个更高效的版本,所以在接受你的答案之前,我可能会等待一个星期,希望有一个三命令在三周期中的解决方案。
    • 您需要切掉并组合四个部分字,并且除乘法外,ARM7-TDMI 指令都不能写入或应用移位到多个寄存器。
    • 我对三循环三命令解决方案的存在也不抱太大希望。但一个人永远不知道。也许有一个神奇的 first 命令可以用接下来的两个命令来解决问题。
    【解决方案2】:

    如果有解决办法,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
    

    【讨论】:

    • 感谢您试用 gcc。 n=33 需要四个命令(而不是使用交换 R0 和 R1 的 n=1 的公式)这一事实表明,对于在 ARM 中旋转 64 位整数来说,它并不是很优化。
    • 一般来说,ARM ISA 对于编译器来说是非常困难的。它是供人类使用的。
    • @ninjalj:我猜有些人在 gcc 中硬编码了 n=1 和 n=63 的特殊情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-22
    • 2015-12-07
    相关资源
    最近更新 更多