繁体   English   中英

为什么16位指令不能访问通用寄存器的高位寄存器

[英]Why can't 16-bit instructions access the high registers of the general purpose registers

所以现在我读了《ARM Cortex-M3/M4 权威指南》一书,不明白为什么 16 位指令无法访问高级通用寄存器 R8-R12。

它说实际上很少有人可以访问这些寄存器,但大多数不能。

16bits 意味着机器代码指令只有 16 位来编码信息。 8 个寄存器需要 3 位进行编码。 12 个寄存器需要 4 位进行编码。 然后我们需要操作码和其他选项的空间,这意味着额外的位可能有点太多了。

编码 8 个寄存器的地址需要 3 位。 编码 12 个寄存器的地址需要 4 位。

如果您有一个 3 寄存器指令,则需要 12 位来对 3 个寄存器进行编码,因此该指令只剩下 4 位。 您最多只能有 16 条指令。

这些核心的唯一实际权威指南是 arm 文档。 在阅读任何其他内容或学习指令集之前,您需要拥有文档; 在这种情况下,ARMV7-m 的 ARM 架构参考手册以及 cortex-m3 或 cortex-m4 技术参考手册。 如果你的书做出了这样的声明并且没有解释它,那么它远非确定性的。

这在技术上是可行的,但它会占用大量空间,并且可能会破坏尝试 16 位指令的目的(并不意味着 16 位处理器或寄存器或类似的东西,指令本身是 16 位)。 如果您查看编译后的代码以及编译器的工作方式,则生成的大量代码使用较低的寄存器或可以这样制作。 因此,这是指令集的丰富性与指令数量的权衡,这与您拥有的寄存器数量无关。

寄存器的大小无关紧要,寄存器的数量才是重要的。 为了例如

add r1,r2,r3

你必须在某个地方编码哪个寄存器是哪个。 注释当然是针对旧的/原始的 16 位指令而不是拇指 2 扩展的。

所以你需要一个模式,自然有人会:

000 r0
001 r1
010 r2
011 r3
100 r4
101 r5
110 r6
111 r7

如果您将自己限制为 8 个寄存器,那么每个寄存器只需要三个位来描述每个字段使用哪个寄存器。

如果要在指令中使用 16 个寄存器,则需要 4 位:

0000 r0
0001 r1
0010 r2
....
0111 r7
1000 r8
1001 r9
....
1110 r14
1111 r15

如果您的指令集中需要 32 个寄存器(通常不是 ARM 拇指),则需要 5 位:

00000 r0
00001 r1
10000 r16
11111 r31

笔记

2 to the power 0 is 1
2 to the power 1 is 2
2 to the power 2 is 4
2 to the power 3 is 8
2 to the power 4 is 16
2 to the power 5 is 32
2 to the power 16 is 65536

等等。

如果你想描述 8 件事需要 3 位,如果你想描述 16 件事需要 4 位。

16 位意味着潜在的 65536 条唯一指令。 ARM 的文档很好地展示了它如何布置指令集,与 MIPS 相比,MIPS 倾向于最大化指令的数量和可能的功能,后者首先倾向于解码逻辑的简单性,然后才是功能(设计权衡)。

跳过例如指令的前 6 位是操作码

00xxxx shift, add, subtract, move, and compare
010000 data processing instructions
010001 special data
01001x ...

等等。 根据您下载的 ARM ARM 以各种方式显示。

他们不必实现任何三个寄存器指令,但他们选择了。 如果这些指令支持每个操作数的 r0 到 r15,那么这意味着需要 12 位,剩下 4 位用于编码,其中包括一个或多个以指示此类指令,其余的是哪个操作数,您可能会至少删除一个一半可能的指令(一位专门用于指示这是不是三寄存器指令)留下 7 种可能的操作,或者,四分之一的指令空间(两位)留下 2 位来选择哪个操作数,这使得它的功能不是很丰富. 相反,他们实际做的是占用 1/4 的指令空间,但至少为操作数和/或其他功能(立即数等)留出 5 位。

所以 add 的 T1 编码是

0001100mmmnnnddd

前两位表示这是哪组指令,如果您看一下,您会看到第 10 位表示立即数或寄存器 mmm 位是寄存器或 0 到 7 之间的立即数,很多时候程序员想要递增1 或 2 或一些小数字,并且必须强制执行一条指令并烧毁一个寄存器来放置那个小数字与烧掉一些指令空间的权衡在这里是一个平衡。

不管怎样,你在这里看到,对于这个指令编码,rm、rn 和 rd 寄存器有三个位。 (add rd,rn,rm) 并且这表明 r0-r7 可以用于这些字段中的任何一个。

为了使它更完整,有一个 mov high 寄存器指令,允许您移动高/低,低/高或高/高,技术上的低/低,但他们更喜欢您使用记录的不同编码。 其中之一可以是添加与上述三个寄存器相关的 rd,rn,#0。 这就是你看到的 gnu 汇编程序所做的

.thumb
mov r1,r2
mov r10,r2
mov r1,r11
mov r10,r11
    
00000000 <.text>:
   0:   1c11        adds    r1, r2, #0
   2:   4692        mov r10, r2
   4:   4659        mov r1, r11
   6:   46da        mov r10, r11

重点是有一种方法可以在高位寄存器之间来回移动,这比进出堆栈更快(没有内存周期),因此编译器仍然可以选择使用一个/一些高位寄存器(理解推/弹出仅限于出于显而易见的原因(阅读文档),因此保存和恢复它们是有成本的,这是一种权衡)。

因此,您应该坚持对某事的实际权威指南,而不是自称是某事。

你几乎在任何地方都找不到的一件事,除非你碰巧在那一刻在大脑/立方体/办公室/会议室中,设计师实施了指令集或特定指令是他们“为什么”做吧。 (为什么没有三个注册和,异或等)所以尽管有其他答案、评论和上述内容,这是因为他们想要。 如果您需要了解更多信息,您也许可以找到一份工作,也许他们仍然在那里,可能会与您共度时光,但我希望他们退休。

很长时间以来,有关各方的回答可能会因多年前谁说了什么以及何时说而有所不同。 但是当尝试采用 32 位指令集并将子集映射到 16 位指令以将每单位空间的指令数量增加一倍时,同时尝试足够丰富以不大幅增加每个任务的指令数量,限制了大部分指令对于这种架构的较低通用寄存器似乎是一个明显的设计选择。 我将不得不重新审视相当于拇指的 MIPS,看看他们做了什么,我希望他们做同样的事情。 同样,我还必须重新审视 risc-v 和任何其他做过同样事情的人。

理解这是一个设计选择,而不是任何方式的要求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM