在MIPS64中加载地址

时间:2010-10-12 11:38:30

标签: mips mips64

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

la $at, LabelAddr

扩展为:

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

查看MIPS64指令集,我发现lui仍然会在32位字的上半部分加载一个16位立即数。似乎没有任何类型的扩展指令将立即加载到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]

这让我觉得有点......因为加载一个地址这样基本的东西令人费解,所以它让我确信我忽略了一些东西。

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

2 个答案:

答案 0 :(得分:3)

我认为如果你需要加载很多常量,你应该把它放在当前代码附近的常量池(AKA "literal pool")中然后通过ld指令加载它。

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

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

然而,某些MIPS编译器仍然总是generate multiple instructions to load a 64-bit immediate。例如,在MIPS上加载0xfedcba0987654321 gcc使用

    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.在这些情况下,指令缓存成本可能低于数据缓存成本,或者有人可能不喜欢那个想法

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

我没有说服任何MIPS编译器发出文字池但是here's a compiler-generated example on ARM

答案 1 :(得分:0)

  

解决这个问题让我确信我忽视了一些事情。   我忽略了什么(如果有的话)?

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

Paxym