【发布时间】:2017-10-07 16:52:15
【问题描述】:
我遇到的所有 CPU 架构都有对称寄存器 - 即您读取的值就是您写入的值。
对于寄存器限制的 16 位指令,是否存在非对称寄存器的情况?
例如
- 寄存器 0-6 是函数调用的“本地”。此函数调用中写入的值就是要读取的值。每个级别的函数调用都有自己的寄存器硬件,因此本地寄存器被隐式保存。
- 寄存器 7-9 是“全局的”,可能是 SMP CPU 上的“线程本地”。
- 写入“调用”寄存器 10-13 的值不会影响从它们读取的内容在此函数调用上下文中。
- 从“调用”寄存器 10-13 读取的值是写入调用函数的值,即函数的寄存器参数是不可变的。
- 写入“返回”寄存器 14-15 的值不会影响在此函数调用上下文中从它们读取的值。
- 从“返回”寄存器 14-15 读取的值是写入函数中最近返回给当前函数的值。
每个函数级的寄存器都有自己的硬件,只有在调用深度超过硬件时才会溢出到堆栈。
(local) (global) ( call ) (ret)
global regset 07 .. 09
.
.
.
. | | ^ ^
. v v | |
regsetN-1 00 .. 06 10 .. 13 14 15
|^ |^ | | ^ ^
v| v| v v | |
fnN-1 RW RW RW RW RW RW
| | ^ ^
v v | |
regsetN 00 .. 06 10 .. 13 14 15
|^ |^ | | ^ ^
v| v| v v | |
fnN RW RW RW RW RW RW
| | ^ ^
v v | |
regsetN+1 00 .. 06 10 .. 13 14 15
|^ |^ | | ^ ^
v| v| v v | |
这样的方案能否将每个函数调用中的寄存器压力减少两个或更多寄存器?
我并不期待这是一个新想法,但我对它是否已经完成感兴趣,如果没有,为什么不呢?如果这不是一个疯狂的想法,或者已经完成,我可能会在 FPGA CPU 上实现它。
是否太复杂以至于不值得节省注册费?
llvm-difficulties 是没有完成的主要原因吗?
附:我知道超标量处理器已经比这复杂得多,包括寄存器重命名方案等。我只是在思考微控制器级架构。
更新:看起来 SPARC 架构是这样做的。为什么后来的 ISA 设计者认为它没有用?
当一个过程被调用时,寄存器窗口移动 16 个寄存器,隐藏旧的输入寄存器和旧的本地寄存器,使旧的输出寄存器成为新的输入寄存器。
【问题讨论】:
-
我不清楚为什么这需要在微架构(硬件)级别实现。这可以很容易地成为设计师建立并由软件遵守的约定。我的意思是,我猜你不会得到硬件辅助保护反对写入你不应该的寄存器,但是在这些低级别,你通常不能保证这些类型的保护,无论如何.除此之外,一旦您拥有 16 个寄存器,您似乎就不会被归类为“寄存器受限”的 ISA。
-
此外,有架构实现了register windows,这听起来与您所描述的非常相似,但认为并不完全相同。
-
你是对的,这没有理由需要硬件,它可能只是一个 ISA。 “保护”不是一个目标,只是一个快乐的巧合。关键是函数可以将值写入“调用寄存器”(在调用函数之前),而不会破坏它本身被调用的参数等,从而缓解 ISA 中的寄存器压力。
-
re:寄存器窗口 - 是的,这是寄存器窗口的一种形式,但也允许读写更高和更低的窗口,具体取决于寄存器编号和访问类型。
-
Zilog Z8 的“经典”版本可以有 144 或 256 个 8 位寄存器,通常配对(偶/奇)以形成 16 位地址。有一个简短的指令,它使用来自基址寄存器的 16 位索引来选择一个寄存器。通过每个“线程”使用一个基址寄存器(或更多),您可以获得您提到的一些功能。代码读取与数据读取/写入之间有一个引脚,使其成为哈佛架构..
标签: llvm cpu-architecture cpu-registers