ARM,Thumb和Thumb 2指令编码有什么区别?

71G*_*1GA 33 arm thumb

我对指令集有点困惑.有Thumb,ARM和Thumb 2.根据我的阅读Thumb指令都是16位,但在ARMv7M用户手册(第vi页)中,提到了Thumb 16位和Thumb 32位指令.

现在我必须克服这种困惑.据说Thumb 2支持16位和32位指令.那么ARMv7M实际上支持Thumb 2指令而不仅仅是Thumb吗?

还有一件事.我可以说Thumb(32位)与ARM指令相同,它们都是32位吗?

Not*_*hat 53

哦,ARM和他们愚蠢的命名......

这是一种常见的误解,但官方认为没有"Thumb-2指令集"这样的东西.

忽略ARMv8(其中所有内容都被重命名,AArch64使事情复杂化),从ARMv4T到ARMv7-A有两个指令集:ARM和Thumb.它们都是"32位",因为它们在具有32位地址的32位宽寄存器中对高达32位的数据进行操作.事实上,在它们重叠的地方,它们代表完全相同的指令 - 它只是指令编码不同,而CPU实际上只有两个不同的解码前端到它的管道,它可以在它之间切换.为清楚起见,我现在故意避免使用"32位"和"16位"这两个术语......

ARM指令具有固定宽度的4字节编码,需要4字节对齐.拇指指令具有可变长度(2或4个字节的,现在被称为"窄"和"宽")需要2字节对齐编码-大多数指令具有2字节的编码,但blblx一直有4字节编码*.真正令人困惑的是ARMv6T2,它引入了"Thumb-2技术".Thumb-2不仅包括向Thumb添加更多指令(主要是4字节编码)以使其几乎与ARM进行奇偶校验,而且还扩展了执行状态以允许条件执行大多数Thumb指令,并最终引入全新的汇编语法(UAL,"统一汇编语言")取代了以前单独的ARM和Thumb语法,允许编写一次代码并将其汇编到任一指令集而无需修改.

Cortex-M架构仅实现Thumb指令集 - ARMv7-M(Cortex-M3/M4/M7)支持大多数"Thumb-2技术",包括条件执行和VFP指令编码,而ARMv6-M(Cortex-) M0/M0 +)仅以少数4字节系统指令的形式使用Thumb-2.

因此,新的4字节编码(以及稍后在ARMv7版本中添加的编码)仍然是Thumb指令 - 它们的"Thumb-2"方面是它们可以具有 4字节编码,并且它们(大多数情况下)可以有条件地编码通过it(并且,我认为,他们的menmonics仅在UAL中定义)执行.

*在ARMv6T2之前,关于bl(或blx)是作为4字节指令还是作为一对2字节指令执行,实际上是一个复杂的实现细节.架构定义是后者,但由于它们只能按顺序执行,因此出于性能原因将它们融合到一条指令中,除了中断中断的能力之外几乎没有什么损失.ARMv6T2刚刚根据融合的单指令执行重新定义了东西

  • 同样,在*Thumb2*中,还有随时间增加的操作码.所以不是所有*Thumb2*都是一样的.从主CPU的角度来看,没有任何模式称为*Thumb2*(我认为这是'官方'的意思吗?); 当然ARM持有似乎有*Thumb2*混合16/32位编码的想法,但除此之外它是模糊的. (3认同)

uni*_*urf 13

除了Notlikethat的答案,并且正如它所暗示的那样,ARMv8引入了一些新的术语来试图减少混淆(当然还增加了更多的新术语):

存在32位执行状态(AArch32)和64位执行状态(AArch64).

32位执行状态支持两个不同的指令集:T32("Thumb")和A32("ARM").64位执行状态仅支持一个指令集 - A64.

所有A64与所有A32一样,指令大小为32位(4字节),需要4字节对齐.

许多/大多数A64指令可以在32位和64位寄存器上运行(或者可以说是相同底层64位寄存器的32位或64位视图).

所有ARMv8处理器(与所有ARMv7处理器一样)都支持T32指令集中的Thumb-2指令.

  • 我没有足够的声誉来直接评论 unixsmurf 的答案,但它需要进行调整。ARMv8A 处理器内核可以选择根本不实现 aarch32 状态。这样的内核将不支持 T32 或 A32 指令。如果给定的处理器内核_确实_实现了 aarch32 状态(如 ARM ltds 的 cortex-A53、A57 和 A72),那么它也支持该状态下的 Thumb-2 模式。 (2认同)

ERF*_*F4N 12

Thumb:16位指令集

ARM:32 位宽指令集,因此指令更灵活,代码密度更低

Thumb2(混合 16/32 位) :在ARMthumb(16) (混合它们)之间以某种方式进行折衷,以获得 ARM 的性能/灵活性和 Thumb 的指令密度。因此,Thumb2 指令可以是 32 位宽指令的 ARM(仅是 ARM 的子集),也可以是 16 位宽的 Thumb 指令。

  • 实际上,这是一个很好的简单答案,适合一般理解,因为细节很血腥。Thumb1 限制了寄存器,这对性能产生了影响。使用thumb2,您可以通过压缩指令流获得ARM32 的几乎所有功能。结果是 Thumb2 的性能更高(取指令更少),并且几乎在所有情况下都具有更小的代码大小。 (3认同)

mun*_*764 6

让我感到困惑的是 Cortex M3 有 4 字节指令,但不执行 ARM 指令。或者 CPU 能够具有 2 字节和 4 字节操作码,但也能够执行 ARM 指令。所以我读了一本关于Arm的书,现在我对它的理解稍微好一些了。尽管如此,命名和重叠仍然让我感到困惑。我想先比较几个 CPU,然后再讨论 ISA 会很有趣。

比较几个 CPU 及其功能以及它们如何重叠:

  • Cortex M0/M0+/M1/M23被视为Thumb (Thumb-1),可以执行与其他相比有限的2 字节操作码。但是,某些指令(例如mrs, msr, bl, dmb, dsb, )isb来自 Thumb-2 并且是4 字节。Cortex M0/M0+/M1 是 ARMv6,而 Cortex M23 是 ARMv8。Thumb-1指令在ARMv7中得到了扩展,因此可以说ARMv8 Cortext M23支持更完整的Thumb-1(it指令除外),而ARMv6 Cortex M0/M0+仅支持ISA的一个子集(它们缺少具体的itcbz指令cbnz) 。我可能是错的(如果这是不正确的,请纠正我),但注意到一些有趣的事情,只有我看到的完全支持 Thumb-1 的 CPU 也已经支持 Thumb-2,我不知道只支持 Thumb-1 100%支持Thumb-1的CPU。我认为这是因为it它可以被视为 Thumb-2 操作码,它是 2 字节,本质上是添加到 Thumb-1 中的。在 Thumb-1 CPU 上,4 字节操作码可以被视为两个 2 字节来表示 4 字节操作码。

  • Cortex M3/M4/M7/M33/M35P/M55可以执行2 字节和 4 字节操作码,均为Thumb-1 和 Thumb-2,并支持全套 ISA。2字节和4字节操作码混合得更均匀,而上面的Cortex M0/M0+/M1/M23大多数时候偏向使用2字节操作码。Cortex M3/M4/M7 是 ARMv7,而 Cortex M33/M35P/M55 是 ARMv8。

  • Cortex A/R可以接受ARM 和 Thumb操作码,因此具有2 字节和 4 字节。为了在模式之间切换,PC 需要偏移一个字节(强制不对齐),这可以通过例如分支指令来完成,分支指令bx设置T的位CPSR并根据地址的最低位切换模式。这很有效,例如,当调用子例程时,PC(及其模式)被保存,然后在子例程中可以切换到 Thumb 模式,但是当从 Thumb 模式返回时,它将恢复 PC(及其 T 位)并切换回任何调用者(ARM 或 Thumb 模式),没有任何问题。

  • ARM7仅支持ARMv3 4字节ISA

  • ARM7T支持Thumb-1 和 ARM ISA(2 字节和 4 字节)

  • ARM11(ARMv6、ARMv6T2、ARMv6Z、ARMv6K)支持Thumb-1、Thumb-2 和 ARM ISA

我引用的书指出,在 ARMv7及更新版本中,架构从冯诺依曼(数据和指令共享总线)切换到哈佛(专用总线)以获得更好的性能。然而,绝对术语“更新”并不正确,因为 ARMv8 更新,但 ARMv8 Cortex M23 是冯诺依曼。

ISA 是:

  • ARM有16个寄存器(R0-R12、SP、LR、PC),只有4字节操作码,ISA有修订,但也只是4字节操作码。

  • Thumb(又名 Thumb-1)将 16 个寄存器分为低位寄存器(R0-R7)和高位寄存器(R8-R12、SP、LR、PC),大多数指令只能访问低位寄存器,而只有一些指令可以访问高位寄存器。只有 2 字节操作码。在具有 16 位总线(并且必须分两步执行 32 位字访问)的低端设备上,当它们执行 2 字节操作码时,性能会更好,因为它与总线相匹配。这个命名让我很困惑,Thumb 可以用作 Thumb-1 和 Thumb-2 的家族术语,或者有时 Thumb 只能用于 Thumb-1。我认为 Thumb-1 并不是 Arm 的官方术语,只是我所看到的人们用来区分 Thumb 系列 ISA 和第一个 Thumb ISA 的更清晰的术语。ARM 中的指令可以有可选的s后缀来更新CPSR寄存器(例如ands, orrs, movs, adds,subs指令),而在 Thumb-1 中该后缀始终打开,并且始终s保存寄存器。CPSR在一些较旧的工具链中,不需要隐式的s,但是在统一汇编语言(UAL)的努力中,现在需要显式指定,s即使没有不使用的选项s

  • Thumb-2是 Thumb 的扩展,可以像 ARM 一样访问所有寄存器,具有 4 字节操作码,与 ARM 相比有一些差异。在汇编中,可以使用后缀强制使用 Thumb-1 2 字节窄操作码和 Thumb-2 4 字节宽操作码.n.w示例orr.w)。ARM 和 Thumb-2 操作码格式/编码不同,它们的功能也不同。可以使用指令的条件执行,但仅当it(if-then)指令/块前置时。这可以显式或暗示地完成(并且由工具链在用户背后完成)。这种混乱实际上可能是好事,因为 Arm(该公司)希望它们相似,因此在统一汇编语言 (UAL) 方面付出了很大的努力,因此为 ARM 制作的汇编文件可以在 Thumb-2 上编译而无需更改。如果我理解正确的话,这不能 100% 保证,并且可能会出现一些边缘情况,其中 ARM 程序集无法编译为 Thumb-2,这是另一个不完全正确的绝对声明。例如,ARM7bl指令可以寻址 +-32MB,而在 Cortex M3 上只能寻址 +-16MB。与 Thumb-1 相比,这种情况要好得多,其中 ARM 程序集更有可能重写为目标 Thumb-1,而 ARM 到 Thumb-2 重写的可能性较小。另一个区别是数据处理指令。ARM 和 Thumb-2 都支持 8 位立即数,而 ARM 只能向右旋转位且只能按偶数位旋转,而 Thumb 可以向左旋转并按偶数/奇数位旋转,最重要的是允许重复的字节模式例如0xXYXYXYXY0x00XY00XY0xXY00XY00。因为移位是轮换的,所以左右移位可以通过“溢出”来实现,向一个方向移位太多,以至于实际上是向相反方向移位1 << (32 - n) == 1 >> n

总之,一些 Arm CPU 可以做到:

  • 只有 4 字节操作码指令,是纯 ARM ISA
  • 2 字节/4 字节 Thumb-1/Thumb-2 ISA,大部分时间重点使用 2 字节,仅使用少数 4 字节操作码,这些通常标记为 Thumb (Thumb-1) 2-字节操作码 CPU(有时不会提及少数 4 字节操作码)
  • 2 字节/4 字节 Thumb-1/Thumb-2 ISA,在 2 字节和 4 字节操作码之间更均匀地混合,通常标记为 Thumb-2
  • 通过在 ARM/Thumb 模式之间切换来实现 2 字节/4 字节操作码

有关此信息的参考:ARM 汇编语言编程和架构 Muhammad Ali Mazidi 等人 2016。这本书是在公司名称从 ARM 更改为 Arm 之前编写的,因此有时在引用公司 Arm 和 ARM ISA 时会造成混淆。

  • 我想知道 M4 处理器是否可以执行 ARM 以及 Thumb2。您的答案是解决我的问题的唯一答案。谢谢。 (2认同)