【问题标题】:Most effient way to push all registers to stack in ARM64在 ARM64 中将所有寄存器推入堆栈的最有效方法
【发布时间】:2020-10-29 21:39:21
【问题描述】:

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

    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

(即首先压入所有通用寄存器,然后压入所有 SIMD FP 寄存器,分支到正确的向量,然后将所有内容弹出)

有没有办法更有效地做到这一点?这种中断运行非常频繁,任何性能提升都很好。

【问题讨论】:

  • 考虑只推送您在中断处理程序中实际修改的寄存器。
  • 虽然我很想这样做,但我 必须 将所有寄存器推入堆栈,因为我不知道中断处理程序中将修改哪些寄存器,因为代码的编写方式
  • 你能不能至少跳过将 x19 保存到 x29,因为它们在 ARM64 中是被调用者保存的?
  • @qwerty123443 在这些限制下,我想除了你已经在做的事情之外别无他法。然而,我怀疑这是否真的如此。代码如何破坏任何寄存器?为什么会这样?
  • 如果中断“经常”运行,可能值得优化它以限制它可以破坏的寄存器。除非它已经足够快,在这种情况下,您可以继续花费周期来保存/恢复所有内容。

标签: assembly arm stack arm64


【解决方案1】:

我假设确实需要保存所有寄存器,正如 cmets 中已经提到的那样。

使用通用寄存器,最多只能同时写入或加载两个到内存中,根本没有指令可以这样做。 SIMD 寄存器有点不同:使用指令

ST4 { V0.2D, V1.2D, V2.2D, V3.2D }, [SP], #64

可以同时写入四个连续的 SIMD 寄存器。这会导致寄存器值在放入堆栈之前交错。但是,这应该不是问题,只要它们以相同的方式重新加载(使用LD4)并且在此期间没有被访问(否则你必须弄清楚你的值在哪里结束)。这减少了代码大小并且还可以使其更快(请参阅我的问题here)。这将替换您代码中的相应部分

    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 只支持后索引,而你一直使用前索引。在任何地方更改它是最简单的。

【讨论】:

  • 再次阅读 OPs 问题。他需要为中断处理程序保存通用寄存器。相反,保存一些其他寄存器对他没有特别帮助。
  • SIMD 寄存器也保存在 OP 的代码中,名称为 q0q31 而不是 v0.2dv31.2d(名称仅表示访问类型)。我只评论了保存这些寄存器,所以这只是部分答案,但应该解决这个问题。
  • 这是有道理的。但请注意,st4 将其参数置换为从 SoA 表示转换为 AoS 表示。您想要 st1 直接存储。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
  • 2012-04-27
  • 1970-01-01
  • 2013-05-12
  • 2011-02-19
  • 2017-03-09
相关资源
最近更新 更多