ARM Thumb/Thumb-2 性能

标签 arm cortex-m3

我正在研究具有 Thumb-2 指令集的 ARM Cortex-M3 Controller 。
Thumb 模式用于将指令压缩为 16 位大小。
因此减少了代码的大小。但是正常的Thumb模式下,为什么说性能下降呢?
在 Thumb-2 的情况下,据说根据以下两个链接提高了性能:

  • Wikipedia
  • Arm.com

  • Improve performance in cases where a single 16-bit instruction restricts functions available to the compiler.

    A stated aim for Thumb-2 was to achieve code density similar to Thumb with performance similar to the ARM instruction set on 32-bit memory.


    这究竟是什么表现?有人可以举几个与之相关的例子吗?

    最佳答案

    与 ARM 32 位指令集相比,thumb 16 位指令集(尚未谈论 thumb2 扩展)占用的空间更少,因为指令的大小是其一半,但性能下降,一般来说,因为它需要更多的指令做与 ARM 相同的事情。指令集功能较少,大部分指令只对寄存器r0-r7进行操作。 Apples 与 Apples 比较,做同样事情的指令越多越慢。

    现在thumb2 扩展采用以前未定义的thumb 指令并创建32 位thumb 指令。了解有不止一套 thumb2 扩展。 ARMv6m 可能增加了几十个。 ARMv7m 向拇指指令集添加了 150 条指令,我不知道 ARMv8 或 future 会怎样。因此,假设使用 ARMv7m,它们已经弥合了您可以在拇指中执行的操作与您可以在 ARM 中执行的操作之间的差距。因此,thumb2 与thumb 一样是精简的ARM 指令集,但没有精简。因此,与 ARM 做同样的事情相比,在 thumb2(假设加上拇指)中做同样的事情可能仍然需要更多的指令。

    这给出了问题的味道,arm 中的单个指令和拇指中的等价物。

    ARM
    
    and r8,r9,r10
    
    THUMB
    
    push {r0,r1}
    mov r0,r8
    mov r1,r9
    and r0,r1
    mov r1,r10
    and r0,r1
    mov r8,r0
    pop {r0,r1}
    

    现在编译器不会这样做,编译器会知道它是针对拇指并通过选择其他寄存器来做不同的事情。每条指令的寄存器和功能仍然较少:
    mov r0,r1
    and r0,r2
    

    仍然需要两个指令/执行周期将两个寄存器放在一起,而不修改操作数,并将结果放在第三个寄存器中。 Thumb2 具有三个寄存器,因此您将返回到使用 thumb2 扩展的单个指令。并且该thumb2 指令允许在thumb 被限制为r0-r7 的三个寄存器中的任何一个上使用r0-r15。

    查看 ARMv5 架构引用手册,在每个拇指指令下,它显示了等效的 ARM 指令。然后转到该 ARM 指令并比较您可以使用该 arm 指令执行哪些操作,而使用拇指指令则无法执行该指令。这是拇指指令(不是拇指2)与ARM指令一对一关系的单向路径。所有拇指指令都有一个等效的 ARM 指令。但并非所有 arm 指令都有等效的拇指指令。您应该能够从本练习中看到使用拇指指令集时对编译器的限制。然后拿到 ARMv7m 架构引用手册,查看指令集,比较“所有拇指变体”编码(包括 ARMv4T 的编码)和仅限于 ARMv6 和/或 v7 的编码,并查看拇指之间的功能扩展和thumb2 以及thumb2 only 没有对应thumb 的指令。这应该澄清编译器必须在拇指和拇指2之间使用什么。然后,您甚至可以将 thumb+thumb2 与完整的 ARM 指令进行比较(ARMv7 AR 就是所谓的?)。并且看到 thumb2 更接近于 ARM,但是你失去了例如每条指令的条件,所以在拇指中的条件执行变成了与代码分支的比较,在 ARM 中你有时可以有一个 if-then-else 而没有分支.. .

    关于ARM Thumb/Thumb-2 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15846737/

    相关文章:

    ios - 适用于 iOS 目标的 Ada 交叉编译器

    ARM位域提取?

    c - 通过 Uart ISR 更新变量而不中断分配

    c - 为什么编译器不优化掉中断代码?

    c - 如何设置异常发生时的回调函数?

    c++ - LPC1700不会从深度 sleep 中醒来

    debugging - 在调试期间在 IDE 中显示 printf 消息

    c - 内联 C 汇编破坏了它自己的变量

    arm - 在 ARM Cortex-M3 中使用 newlib 的 malloc

    c - 在 core_cm4.h 上,为什么会有类似 ((uint32_t)(int32_t)IRQn) 的转换?