RISC访问地址大于最大整数

时间:2018-06-07 18:59:17

标签: assembly mips cpu-architecture riscv sparc

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

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

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

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

假设ALU为32位且具有进位标志。

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

2 个答案:

答案 0 :(得分:3)

即使在CISC上,你所描述的也很不寻常。 这不是因为它是CISC,而是因为使用的地址比寄存器更宽。这通常只在8位CPU中找到。 (虽然x86分段也有资格,间接远跳采用指向m16:32段/偏移对的指针。或者在16位模式下,m16:16。作为little-endian,偏移是第一个。 )在64位模式之外,jmp ptr16:32也是可编码的,绝对段:offset作为指令流的一部分。)

通常,当您想要设计具有更大地址空间的CPU时,您还可以使寄存器更宽,以便您可以有效地处理地址。当你想通过使用大多数8位寄存器/ ALU来节省晶体管时,它只是在最低端,但是你不能将你的地址空间限制在256字节,你会发现这种设计。 / p>

即使地址大小与字大小匹配,也存在一个真正的问题。 构造任意32位(或64位)常量是一个问题,不同的ISA解决不同的方式。 ARM经常使用来自附近"文字池的PC相对负载#34;而其他人经常使用lui或等效设置高16位而其余为零,然后ori一个16位立即。 (通过使用移位/旋转立即数,ARM有一些简洁的技巧可以设置只有几位的immediate。)

通常在RISC上,如果需要跳远,可能需要使用多条指令在寄存器中构造地址。然后使用跳转到寄存器指令。

MIPS分支指令很有意思:它具有相对分支,它为程序计数器添加一个带有相当大范围的有符号位移,以及用新地址替换PC的低28位的绝对跳转指令。 (由26位立即左移构建,因为MIPS需要对齐指令,因此不需要存储低2位。)How to Calculate Jump Target Address and Branch Target Address?。但是当目标位置无法与目标位置到达时,您需要jr在寄存器中包含地址。

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

8位RISC

我唯一知道程序计数器比寄存器更宽的RISC ISA是AVR,一个带8位寄存器的微控制器。 它可以将寄存器对视为16位地址,其PC为16位。它IJMP (indirect jump) instruction设置PC = Z(其中Z是一对8位寄存器)。在具有22位程序计数器而不是16位的AVR上,它将PC(21:16)归零。

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

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

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

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

在MIPS,SPARC或PowerPC等普通RISC上, 64位地址仅​​在64位ISA扩展中可用,其中有64位整数寄存器。因此,您使用MIPS ld $2, 0($3)等指令使用$3作为64位基址进行64位(双字)加载。见MIPS-IV ISA manual。 (MIPS-III添加了64位扩展,带有lddaddu等指令。显然MIPS-I使其许多操作码编码空间未使用,因此新的操作码有足够的空间来做完整的64位ALU操作。)

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

在32位RISC ISA上进行扩展寻址

保罗克莱顿评论道:

  

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

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

答案 1 :(得分:2)

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

这不是事实。大多数现代RISC体系结构都具有可变宽度的指令集,或者至少具有特殊的可变宽度模式(在ARM中ForwardComSuperHMIPS16ethumb2,{{ 3}}在RISC-V中...),尽管它们主要是为了实现紧凑目的以提高代码密度。那仍然意味着您实际上可以使RISC体系结构使用多字指令

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

正如彼得所说,比字长更宽的地址主要仅在8位微控制器中才能看到。除了AVR,它还用于程序计数器为13或14位长的8位C instruction set中。指令通常只包含地址的低位,高位将来自PC或PCLATH寄存器。如果您不想使用上述偏移量,则可以直接替换低位,这是另一种方法。显然,您仍需要一个单独的寄存器来存储高位。但是,如果您不关心PIC,那么只需使用专用的大型寄存器即可寻址,例如8051、6502或其他较旧的CISC体系结构

还有很多其他方法可以支持比寄存器大小更大的地址范围,如我在orthogonality中所述。其中之一是将虚拟地址限制为仅寄存器大小(如ARM LPAE或x86 PAE),同时允许物理地址为64位宽。这些页面将被映射到TLB中,并且您不需要使用2个寄存器来寻址。如果您想在此模式下访问超过4GB的内存,只需使用类似于How can 8-bit processor support more than 256 bytes of RAM?的API,或使用多个进程(例如Adobe Premiere CS4的操作方式)