Assembly 在ARM64中将所有寄存器推送到堆栈的最有效方法

Assembly 在ARM64中将所有寄存器推送到堆栈的最有效方法,assembly,arm,stack,arm64,Assembly,Arm,Stack,Arm64,我正在寻找一种方法,将ISR中的所有寄存器推送到arm64的堆栈中。我当前的代码如下所示: stp x0, x1, [sp, #-16]! stp x2, x3, [sp, #-16]! stp x4, x5, [sp, #-16]! stp x6, x7, [sp, #-16]! stp x8, x9, [sp, #-16]! stp x10, x11, [sp, #-16]! stp x12, x13, [sp, #-16]!

我正在寻找一种方法,将ISR中的所有寄存器推送到arm64的堆栈中。我当前的代码如下所示:

    stp x0, x1, [sp, #-16]!
    stp x2, x3, [sp, #-16]!
    stp x4, x5, [sp, #-16]!
    stp x6, x7, [sp, #-16]!
    stp x8, x9, [sp, #-16]!
    stp x10, x11, [sp, #-16]!
    stp x12, x13, [sp, #-16]!
    stp x14, x15, [sp, #-16]!
    stp x16, x17, [sp, #-16]!
    stp x18, x19, [sp, #-16]!
    stp x20, x21, [sp, #-16]!
    stp x22, x23, [sp, #-16]!
    stp x24, x25, [sp, #-16]!
    stp x26, x27, [sp, #-16]!
    stp x28, x29, [sp, #-16]!
    str x30, [sp, #-16]!

    stp q0, q1, [sp, #-32]!
    stp q2, q3, [sp, #-32]!
    stp q4, q5, [sp, #-32]!
    stp q6, q7, [sp, #-32]!
    stp q8, q9, [sp, #-32]!
    stp q10, q11, [sp, #-32]!
    stp q12, q13, [sp, #-32]!
    stp q14, q15, [sp, #-32]!
    stp q16, q17, [sp, #-32]!
    stp q18, q19, [sp, #-32]!
    stp q20, q21, [sp, #-32]!
    stp q22, q23, [sp, #-32]!
    stp q24, q25, [sp, #-32]!
    stp q26, q27, [sp, #-32]!
    stp q28, q29, [sp, #-32]!
    stp q30, q31, [sp, #-32]!

    mrs x0, FPCR
    mrs x1, FPSR
    str x0, [sp, #-16]!
    str x1, [sp, #-16]!

    bl  vector_irq

    ldr x0,  [sp, #16]!
    ldr x1,  [sp, #16]!
    msr FPCR, x0
    msr FPSR, x1

    ldp q30, q31, [sp, #32]!
    ldp q28, q29, [sp, #32]!
    ldp q26, q27, [sp, #32]!
    ldp q24, q25, [sp, #32]!
    ldp q22, q23, [sp, #32]!
    ldp q20, q21, [sp, #32]!
    ldp q18, q19, [sp, #32]!
    ldp q16, q17, [sp, #32]!
    ldp q14, q15, [sp, #32]!
    ldp q12, q13, [sp, #32]!
    ldp q10, q11, [sp, #32]!
    ldp q8, q9, [sp, #32]!
    ldp q6, q7, [sp, #32]!
    ldp q4, q5, [sp, #32]!
    ldp q2, q3, [sp, #32]!
    ldp q0, q1, [sp, #32]!

    ldr x30, [sp, #16]!
    ldp x28, x29, [sp, #16]!
    ldp x26, x27, [sp, #16]!
    ldp x24, x25, [sp, #16]!
    ldp x22, x23, [sp, #16]!
    ldp x20, x21, [sp, #16]!
    ldp x18, x19, [sp, #16]!
    ldp x16, x17, [sp, #16]!
    ldp x14, x15, [sp, #16]!
    ldp x12, x13, [sp, #16]!
    ldp x10, x11, [sp, #16]!
    ldp x8, x9, [sp, #16]!
    ldp x6, x7, [sp, #16]!
    ldp x4, x5, [sp, #16]!
    ldp x2, x3, [sp, #16]!
    ldp x0, x1, [sp, #16]!

    eret
i、 e.首先推送所有通用寄存器,然后推送所有SIMD FP寄存器,分支到正确的向量,然后弹出所有内容


有没有更有效的方法?这个中断经常运行,任何性能提升都很好。

我假设所有寄存器都需要保存,正如注释中已经提到的那样

对于通用寄存器,同时写入或加载到内存中的寄存器不能超过两个,根本没有这样做的指令。对于SIMD寄存器,它有点不同:使用指令

ST4 { V0.2D, V1.2D, V2.2D, V3.2D }, [SP], #64
可以同时写入四个连续的SIMD寄存器。这会导致寄存器值在放入堆栈之前进行交错。但是,只要使用LD4以相同的方式重新加载它们,并且在此期间不访问它们,这就不应该是问题,否则您必须找出值的最终位置。这减少了代码的大小,也可以使它更快地查看我的问题。这将替换代码中相应的部分

    stp q0, q1, [sp, #-32]!
    // ...
    stp q30, q31, [sp, #-32]!
四行

    st4 {  v0.2d,  v1.2d,  v2.2d,  v3.2d }, [sp], #64
    st4 {  v4.2d,  v5.2d,  v6.2d,  v7.2d }, [sp], #64
    st4 {  v8.2d,  v9.2d, v10.2d, v11.2d }, [sp], #64
    st4 { v12.2d, v13.2d, v14.2d, v15.2d }, [sp], #64

与LD4类似。请注意,ST4只支持后期索引,而您一直使用预索引。在任何地方更改都是最容易的。

我假设所有的寄存器都需要保存,正如评论中已经提到的那样

对于通用寄存器,同时写入或加载到内存中的寄存器不能超过两个,根本没有这样做的指令。对于SIMD寄存器,它有点不同:使用指令

ST4 { V0.2D, V1.2D, V2.2D, V3.2D }, [SP], #64
可以同时写入四个连续的SIMD寄存器。这会导致寄存器值在放入堆栈之前进行交错。但是,只要使用LD4以相同的方式重新加载它们,并且在此期间不访问它们,这就不应该是问题,否则您必须找出值的最终位置。这减少了代码的大小,也可以使它更快地查看我的问题。这将替换代码中相应的部分

    stp q0, q1, [sp, #-32]!
    // ...
    stp q30, q31, [sp, #-32]!
四行

    st4 {  v0.2d,  v1.2d,  v2.2d,  v3.2d }, [sp], #64
    st4 {  v4.2d,  v5.2d,  v6.2d,  v7.2d }, [sp], #64
    st4 {  v8.2d,  v9.2d, v10.2d, v11.2d }, [sp], #64
    st4 { v12.2d, v13.2d, v14.2d, v15.2d }, [sp], #64

与LD4类似。请注意,ST4只支持后期索引,而您一直使用预索引。在任何地方更改都是最容易的。

考虑只在中断处理程序中推送您实际修改的寄存器。虽然我很乐意这样做,但我必须将所有寄存器推送到堆栈中,由于我不知道由于代码的编写方式,中断处理程序中会修改哪些寄存器。您能否至少跳过保存x19到x29,因为这些寄存器是保存在ARM64中的被调用方?@qwerty123443在这些约束条件下,我想除了您已经在做的事情之外,没有其他方法了。然而,我怀疑这是真的。这段代码怎么会破坏任何寄存器?为什么会这样呢?如果中断经常运行,那么可能需要对其进行优化,以限制它可以关闭哪些寄存器。除非它已经足够快,在这种情况下,你可以只需要花费一些周期来保存/恢复所有的东西。考虑只推你在中断处理程序中实际修改的寄存器。虽然我很乐意这样做,但是我必须把所有寄存器都推到栈中。由于我不知道由于代码的编写方式,中断处理程序中会修改哪些寄存器。您能否至少跳过保存x19到x29,因为这些寄存器是保存在ARM64中的被调用方?@qwerty123443在这些约束条件下,我想除了您已经在做的事情之外,没有其他方法了。然而,我怀疑这是真的。这段代码怎么会破坏任何寄存器?为什么会这样呢?如果中断经常运行,那么可能需要对其进行优化,以限制它可以关闭哪些寄存器。除非它已经足够快了,在这种情况下,你可以继续花费周期来保存/恢复所有东西。他需要为中断处理程序保存通用寄存器。它不会特别帮助他保存一些其他寄存器。SIMD寄存器也保存在OP的代码中,在名称q0到q31下,而不是v0.2d到v31.2d下,该名称仅表示访问类型。我只是对保存这些寄存器发表了评论,所以这只是一个部分答案,但应该解决这个问题。这是有道理的。不过请注意,st4会将其参数从SoA表示转换为AoS表示。您需要st1作为直接存储。请再次阅读操作问题。他需要为中断处理程序保存通用寄存器。它不会特别帮助他保存一些其他寄存器。SIMD寄存器也保存在OP的代码中,在名称q0到q31下,而不是v0.2d到v31.2d下,该名称仅表示访问类型。我只对保存这些寄存器发表了评论,所以这只是一个部分
回答问题,但要解决问题。这是有道理的。不过请注意,st4会将其参数从SoA表示转换为AoS表示。你想要st1作为直销店。