在 MIPS64 中加载地址

发布于 2024-09-27 06:28:49 字数 617 浏览 0 评论 0原文

这可能是一件简单、明显的事情,我只是没有看到,但如何在 MIPS64 处理器中加载地址?在 MIPS32 处理器中,以下汇编器伪指令:

la $at, LabelAddr

扩展为:

lui $at, LabelAddr[31:16]
ori $at,$at, LabelAddr[15:0]

查看 MIPS64 指令集,我发现 lui 仍然将 16 位立即数加载到 32 位字的上半部分。似乎没有任何类型的扩展指令可以将立即数加载到 64 位字的上部区域中。那么,这似乎是为了执行相当于 la 伪指令的操作,我需要扩展为类似这样的代码:

lui $at, LabelAddr[63:48]
ori $at, $at, LabelAddr[47:32]
sll $at, 16
ori $at, $at, LabelAddr[31:16]
sll $at, 16
ori $at, $at, LabelAddr[15:0]

这让我觉得有点……对于像加载这样基本的东西来说有点复杂一个地址,所以它让我确信我忽略了一些东西。

我忽略了什么(如果有的话)?

This is probably a simple, obvious thing I'm just not seeing, but how do I load an address in a MIPS64 processor? In a MIPS32 processor the following assembler pseudo-instruction:

la $at, LabelAddr

Expands into:

lui $at, LabelAddr[31:16]
ori $at,$at, LabelAddr[15:0]

Looking at the MIPS64 instruction set, I see that lui still loads a 16-bit immediate into the upper half of a 32-bit word. There doesn't appear to be any kind of expanded instruction that loads an immediate anywhere into the upper area of a 64-bit word. This seems, then, that to do the equivalent of an la pseudo-instruction I'd need to expand into code something like:

lui $at, LabelAddr[63:48]
ori $at, $at, LabelAddr[47:32]
sll $at, 16
ori $at, $at, LabelAddr[31:16]
sll $at, 16
ori $at, $at, LabelAddr[15:0]

This strikes me as a bit ... convoluted for something as basic as loading an address so it leaves me convinced that I've overlooked something.

What is it I've overlooked (if anything)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

牵强ㄟ 2024-10-04 06:28:49

我认为如果您需要加载很多常量,您应该将其放入常量池(又名"literal pool") 靠近当前代码,然后通过 ld 指令加载它。

例如:$s0包含池的基地址,而你要加载的常量位于偏移量48处,你可以通过指令将其加载到$t1 ld $t1, 48($s0)

这种技术在 ARM,其中指令只能加载 12 位立即数(只有更高版本的 ARM 可以加载 16 位立即数,但有一些限制)。它也用于 Java 中。

然而不知何故,MIPS编译器仍然总是生成多个指令来加载 64 位立即数。例如,在 MIPS gcc 上加载 0xfedcba0987654321 使用

    li      $2,-9568256       # 0xffffffffff6e0000
    daddiu  $2,$2,23813
    dsll    $2,$2,17
    daddiu  $2,$2,-30875
    dsll    $2,$2,16
    daddiu  $2,$2,17185

许多其他 RISC 架构有更有效的方法来加载立即数,因此它们需要更少的指令,但仍然至少 4。在这些情况下,指令缓存成本可能低于数据缓存成本,或者可能有人只是不喜欢这个想法

这是 MIPS 上手写常量池的示例

# load pool base address
    dla $s0, pool
foo:
# just some placeholder
    addu $t0, $t0, $t1
bar:
# load from pool
    ld $a0, pool_foo($s0)
    ld $a1, pool_bar($s0)

.section pool
# macro helper to define a pool entry
.macro ENTRY label
pool_entry_\label\(): .quad \label
.equ pool_\label\(), pool_entry_\label - pool
.endm
ENTRY foo
ENTRY bar

我未能说服任何 MIPS 编译器发出文字池,但是 这是编译器生成的示例ARM

I think if you need to load a lot of constants, you should put it in a constant pool (A.K.A "literal pool") near the current code and then load it by an ld instruction.

For example: $s0 contains the pool's base address, and the constant you want to load is at offset 48, you can load it to $t1 by the instruction ld $t1, 48($s0)

This technique is very common in ARM, where instructions could only load a 12-bit immediate (only later versions of ARM can load 16-bit immediates with some restrictions). And it is used in Java too.

However somehow MIPS compilers still always generate multiple instructions to load a 64-bit immediate. For example to load 0xfedcba0987654321 on MIPS gcc uses

    li      $2,-9568256       # 0xffffffffff6e0000
    daddiu  $2,$2,23813
    dsll    $2,$2,17
    daddiu  $2,$2,-30875
    dsll    $2,$2,16
    daddiu  $2,$2,17185

Many other RISC architectures have more efficient ways to load an immediate so they need less instructions, but still at least 4. Maybe the instruction cache cost is lower than data cache cost in those cases, or maybe someone just don't like that idea

Here's an example of handwritten constant pool on MIPS

# load pool base address
    dla $s0, pool
foo:
# just some placeholder
    addu $t0, $t0, $t1
bar:
# load from pool
    ld $a0, pool_foo($s0)
    ld $a1, pool_bar($s0)

.section pool
# macro helper to define a pool entry
.macro ENTRY label
pool_entry_\label\(): .quad \label
.equ pool_\label\(), pool_entry_\label - pool
.endm
ENTRY foo
ENTRY bar

I failed to persuade any MIPS compilers to emit a literal pool but here's a compiler-generated example on ARM

南风几经秋 2024-10-04 06:28:49

地址,所以它让我确信我忽略了一些东西。
我忽略了什么(如果有的话)?

您缺少的是,即使在 Mips64 中,指令大小仍为 32 位(4 字节)。在这个32位机器代码编码系统中,翻译为“lui”+“ori”组合的“la”最多可以处理32位值(地址)。 4 字节机器指令中没有足够的位来轻松编码 64 位地址。为了处理 64 位地址,需要使用相同的更多迭代 (lui+ori) 以及移位 (dsll)。

帕克希姆

address so it leaves me convinced that I've overlooked something.
What is it I've overlooked (if anything)?

What you are missing is that even in Mips64 the instruction size stays 32bit (4bytes). In this 32bit machine code encoding system, The 'la' translated to 'lui' + 'ori' combination can handle a max of 32 bit value (address). There are not enough bits in the 4byte machine instruction to easily encode a 64bit address. To deal with 64bit address, more iterations of the same (lui+ori) is used along with shifts (dsll).

Paxym

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文