切换实现;手臂;汇编器; aarch64; arm64

switch implementation; arm; assembler; aarch64; arm64

我对在 aarch64 汇编器上实现 'switch' 运算符的方法很感兴趣。 在 arm32 平台上,我使用了类似

    ldr         pc,         [pc, ta, LSL#2]
    nop                                         // alignment
    .int        .L.case1
    .int        .L.case2
    ...
    .int        .L.caseN

但是由于64位版本对'pc'寄存器的使用有很多限制,这样的实现不再有效了。

似乎最简单的方法是使用一对比较和分支操作,例如

cmp ta, #1
b.eq .L.case1
cmp ta, #2
b.eq .L.case2
...

但有时会有多达十几个案例,这会导致在到达最后一个 'case' 之前出现明显的延迟。

能否分享一下如何在 aarch64 上实现快速切换的想法。

谢谢:)

我没有 64 位 ARM 汇编器来测试这个,但我相信你会做类似下面的事情来实现跳转 table:

    adr  x0, jmp_table
    ldr  x0, [x0, x1, LSL#3]
    br   x0

jmp_table:
    .quad .L.case1
    .quad .L.case2
    .quad .L.case3

第一条指令,ADR, loads the address of a label into a register. The last instruction, BR,跳转到寄存器中存储的地址。

如果您正在创建共享库或独立于位置的执行程序table,您可以尝试如下操作:

    adr  x0, jmp_table
    add  x0, x0, x1, LSL#2
    br   x0

jmp_table:
    b .L.case1
    b .L.case2
    b .L.case3

备用 PIC 示例

    adr  x0, jmp_table
    ldr  w1, [x0, x1, LSL#2]
    add  x0, x0, x1
    br   x0

jmp_table:
    .int  .L.case1 - jmp_table
    .int  .L.case2 - jmp_table
    .int  .L.case3 - jmp_table