【问题标题】:How to read a condition flag in ARMv7 Thumb-2 assembly?如何在 ARMv7 Thumb-2 程序集中读取条件标志?
【发布时间】:2019-05-29 04:21:03
【问题描述】:

我正在使用带有 Thumb-2 指令的 ARMv7 处理器。

我执行了ADD、SUB 或CMP。现在我想将条件标志LE 移动到r2。在此之后,r2 应该包含 0 或 1。

我一直在查看 Thumb-2 手册,但没有找到条件 MOV 指令或读取标志的特殊指令。

最有效的方法是什么?提前致谢!

【问题讨论】:

    标签: assembly arm embedded armv7 thumb


    【解决方案1】:

    您需要使用ite (if-then-else) 指令开始一个条件块,然后使用条件赋值:

    ite le        @ if-then-else (le)
    movle r2, #1  @ if (le) then r2 = #1
    movgt r2, #0  @         else r2 = #0
    

    一般来说,如果您在 Thumb-2 中使用适当的 IT 指令作为前缀,则可以使用任意条件指令。详细阅读手册。

    【讨论】:

      【解决方案2】:

      在 ARM 中,(几乎)任何指令都可以被断言。在 thumb 模式下,这需要 it 指令来为接下来的几条指令编码谓词和模式是否否定。

      但我认为,在统一语法中,汇编程序可以为您执行此操作,而无需显式 it。

      例如movle r0, #1 设置 r0 = 1 如果标志中的 LE 条件为真,否则保持不变。所以你首先需要一个mov r0, #0。

      ARM32 没有像 x86 的 setcc 这样的从条件设置指令。

      AArch64 可以:将标志条件转换为整数只需要一条 cset 指令。

      这个 C 源代码:

      int booleanize(int x, int y) { return x<y; }
      int booleanize_u(unsigned a, unsigned b) { return a<b; }
      

      使用 clang -O3 (on the Godbolt compiler explorer) 为 ARM32 thumb 编译,揭示了一些愚蠢的错过优化。 gcc 类似,在没有-mcpu 的情况下生成分支代码,甚至比使用-mcpu=cortex-a53 的clang 更糟糕。在简单的微控制器上,Branchy 可能并非完全不合理。

      @@ BAD EXAMPLE, compiler missed optimizations
      
      @ clang7.0 -target arm -mthumb -mcpu=cortex-a53
      booleanize(int, int):
          movs    r2, #0         @ movs is 16-bit, mov is a 32-bit instruction, I think.
          cmp     r0, r1
          it      lt
          movlt   r2, #1
          mov     r0, r2         @ wasted instruction because the compiler wanted to mov #0 before cmp
          bx      lr
      
      booleanize_u(unsigned int, unsigned int):
          movs    r2, #0
          cmp     r0, r1
          it      lo
          movlo   r2, #1
          mov     r0, r2
          bx      lr
      

      这绝对比@fuz 的答案中的ite le / movle / movgt 差,有2条谓词指令。

      ARM 模式的代码生成或多或少都很好,其中每个 32 位指令字在谓词条件的编码中都有 4 位。 (asm 源中不带后缀的默认是al = always。)

      @ gcc8.2 -O3 -mcpu=cortex-a53
      booleanize(int, int):
          cmp     r0, r1
          movge   r0, #0     @ a simple mov without predication or flag-setting would work
          movlt   r0, #1
          bx      lr
      
      booleanize_u(unsigned int, unsigned int):
          cmp     r0, r1
          movcs   r0, #0
          movcc   r0, #1
          bx      lr
      

      AArch64 有cset,在一个罐子里布尔化。

      @ clang and gcc make the same efficient code
      booleanize(int, int):
          cmp     w0, w1
          cset    w0, lt            @ signed less-than
          ret
      booleanize_u(unsigned int, unsigned int):
          cmp     w0, w1
          cset    w0, lo            @ unsigned lower
          ret
      

      【讨论】:

      • 感谢您的详细解答!
      【解决方案3】:

      我一直在查看 Thumb-2 手册,但没有找到条件 MOV 指令或读取标志的特殊指令。

      您可以使用MRS,将条件标志复制到寄存器(即r2)。

      最有效的方法是什么?

      到目前为止,您还没有包含conditional execution code 不够的要求,因此这是最有效的方法。

      【讨论】:

      • MRS 并不是一个好的选择;仍然需要一到两条指令才能移动/以及您想要的单个位。
      • 谢谢,我不知道MRS指令。
      猜你喜欢
      • 2012-10-10
      • 2018-06-20
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多