1

假设您正在运行一个 32 位 RISC 系统。您将使用哪些指令来访问 64 位内存地址?

在 CISC 指令集中,您可以使用多字指令简单地传递额外的字。例如:

1a) JMP
1b) loAddress
1c) hiAddress

鉴于 RISC 指令每个只有一个字,您将如何访问多字地址?

假设 ALU 是 32 位的并且有一个进位标志。

此外,在 CISC 系统(例如8080)中,loAddress 和 hiAddress 字都将存储在程序存储器中。即JMP指令知道要查看程序存储器中的下一项来检索loAddress,然后再查看下一项来检索hiAddress。RISC 会发生什么?

4

2 回答 2

4

即使在 CISC 上,您所描述的也很不寻常。 这不是因为是 CISC,而是因为使用的地址比寄存器更宽。这通常只存在于 8 位 CPU 中。(尽管 x86 分段也符合条件,间接远跳转采用指向m16:32段/偏移对的指针。或者在 16 位模式下,m16:16. 作为 little-endian,偏移量是第一个。)在 64 位模式之外,jmp ptr16:32也是可编码的,绝对段:偏移量作为指令流的一部分。)

通常,当您想设计一个具有更大地址空间的 CPU 时,您还会使寄存器更宽,以便您可以有效地处理地址。只有当您想通过主要使用 8 位寄存器/ALU 来节省晶体管,但又不能将地址空间限制为 256 字节时,它才处于非常低端,您可以在其中找到这种设计。


即使地址大小与字长匹配,这里也存在一个真正的问题。 构造任意 32 位(或 64 位)常量是不同 ISA 解决方法不同的问题。ARM 经常使用来自附近“文字池”的 PC 相对加载,而其他人经常使用 alui或等价物来设置高 16 位并将其余部分归零,然后ori使用 16 位立即数。(ARM 有一些巧妙的技巧,可以通过使用移位/旋转的立即数对仅设置几位的立即数进行编码。)

一般来说,在 RISC 上,如果您需要跳得很远,您可能需要使用多条指令在寄存器中构造地址。 然后使用跳转到寄存器指令。

MIPS 分支指令很有趣:它具有向程序计数器添加一个相当大范围的有符号位移的相对分支,以及将 PC 的低 28 位替换为新地址的绝对跳转指令。(由 26 位立即左移构造,因为 MIPS 要求指令对齐,所以低 2 位不需要存储。) 如何计算跳转目标地址和分支目标地址?. 但是,当目标无法从当前位置到达时,您需要jr在寄存器中提供地址。

x86-64 也缺少 64 位相对跳转指令。如果您需要跳出超过 +-2GiB 的距离(不像far在新的 CS 段中那样),则需要间接跳跃。正常的跳转/分支指令仍然使用rel8rel32位移,保持机器代码紧凑。唯一可以采用 64 位立即数的指令是mov-to-register。普通代码模型假设同一库或可执行文件中的所有代码彼此之间的距离在 2GiB 以内,因此链接器将能够填充 32 位位移。


8 位 RISC

我所知道的唯一一个程序计数器比寄存器宽的 RISC ISA 是 AVR,它是一个具有 8 位寄存器的微控制器。 它可以把成对的寄存器当作 16 位地址,它的 PC 是 16 位的。它IJMP(间接跳转)指令设置 PC = Z(其中Z是一对 8 位寄存器)。在具有 22 位程序计数器而不是 16 位程序计数器的 AVR 上,它会归零PC(21:16)

EIJMP(扩展间接跳转)从 I/O 空间获取 EIND 寄存器用于 PC 的高位,低位仍然来自Z.

AVR 指令几乎都是 2 字节长,但有些版本有4 字节jmp指令,跳转目标需要 0..4M 绝对地址。


具有 32 位寄存器的主流 RISC 机器也具有 32 位程序计数器和虚拟地址空间。(拥有超过 4GiB 的物理内存是可能的,但您不能在一个进程中同时映射所有内存)。

它们中的大多数在设计中都非常面向字,因此它们所需要的只是jr reg(MIPS)或任何等效于分支到任何可能地址的东西,因为它适合一个寄存器。这是RISC 字面上所代表的降低复杂性的一部分。


在 MIPS、SPARC 或 PowerPC 等普通 RISC 上,64 位地址仅在 64 位 ISA 扩展中可用,其中您有 64 位整数寄存器。因此,您将使用 MIPS 之类的指令ld $2, 0($3)来执行 64 位(双字)加载,并将$3其用作 64 位基址。请参阅此MIPS-IV ISA 手册。(MIPS-III 添加了 64 位扩展,带有和 之类的指令lddaddu显然 MIPS-I 留下了很多未使用的操作码编码空间,因此新操作码有足够的空间来执行完整的 64 位 ALU 操作。)

一些 32 位 CPU 添加了扩展以支持大型物理地址,而无需增加虚拟地址空间。例如,x86 的 PAE 定义了一种具有 36 位物理地址的新页表格式。但即使有分段,单个进程一次也不能处理超过 4GiB 的虚拟内存。(x86 段基址+偏移发生virt->phys 转换之前,创建一个 32 位线性地址。因此它对于线程本地存储仍然有用,例如,[fs:0]根据该线程的fs段基址作为不同的线性地址。)


32 位 RISC ISA 上的扩展寻址

保罗克莱顿评论:

PA-RISC 具有提供扩展寻址的“空间寄存器”。32 位 PowerPC 具有根据 16 项表中有效地址的最高有效 4 位选择的段寄存器(提供 52 位虚拟地址空间)。对于 PA-RISC,“SR 5 到 7 只能通过在最高特权级别执行的代码进行修改。” 对于 PowerPC,任何段寄存器更改都需要特权。

因此,显然一些 RISC ISA 在完全 64 位之前确实扩展了它们的寻址。但我不知道细节,也不打算花时间研究这个。欢迎其他答案!

于 2018-06-07T21:03:50.603 回答
2

鉴于 RISC 指令每个只有一个字

这不是真的。大多数现代 RISC 架构都有一个可变宽度指令集,或者至少有一个特殊的可变宽度模式(ForwardComSuperHMIPS16e、ARM 中的thumb2 、RISC-V 中的C 指令集……)尽管它们主要用于压缩目的是增加代码密度。这仍然意味着您实际上可以使您的 RISC 架构使用多字指令

即使那样,除非您可以使用比 64 位更宽的指令(这些指令太大而无法实用),否则它对您也无济于事。只有两个 32 位字,您仍然会被限制在基地址周围的一些偏移,而不是完整的 64 位地址空间。但这应该不是问题,因为几乎没有单个程序可以利用巨大的 64 位地址空间。这就是为什么在 x86-64 中没有接收 64 位立即地址的指令的原因,因为 32 位偏移已经足够了。所以你可以做同样的事情:在大多数情况下使用一个小的立即偏移量,当你需要完整的 64 位地址时使用一个 2 寄存器对

正如彼得所说,比字长更宽的地址主要只出现在 8 位微控制器中。除了 AVR,它还用于程序计数器为 13 或 14 位长的 8 位PIC 。指令一般只包含地址的低位,高位将取自 PC 或 PCLATH 寄存器。如果您不想使用像上面这样的偏移量,那么像这样直接替换低位是另一种方法。显然,您仍然需要一个单独的寄存器来存放高位。但是,如果您不关心正交性,则只需使用专用的大寄存器进行寻址,例如在 8051、6502 或其他较旧的 CISC 架构中

有许多其他方法可以支持比我在此处描述的寄存器大小更宽的地址范围8 位处理器如何支持超过 256 字节的 RAM?. 其中之一是将虚拟地址限制为仅寄存器大小(如 ARM LPAE 或 x86 PAE),同时允许物理地址为 64 位宽。这些页面将在 TLB 中映射,您无需使用 2 个寄存器来寻址。如果您想在此模式下访问超过 4GB 的内存,只需使用一些类似于Windows AWE的 API ,或使用多个进程(如 Adob​​e Premiere CS4 所做的那样)

于 2020-02-14T13:43:54.273 回答