Я думаю, что если вам нужно загрузить много констант, вы должны поместить его в постоянный пул (AKA "буквальный пул" ) рядом с текущий код и затем загрузить его с помощью инструкции ld
.
Например: $s0
содержит базовый адрес пула, а постоянная, которую вы хотите загрузить, имеет смещение 48, вы можете загрузить ее в $t1
по инструкции ld $t1, 48($s0)
Этот метод очень распространен в ARM , где инструкции могут загружать только 12-битные немедленные (только более поздние версии ARM могут загружать 16-битные немедленные с некоторыми ограничениями). И он также используется в Java .
Однако каким-то образом компиляторы MIPS все еще всегда генерируют несколько инструкций для немедленной загрузки 64-битного . Например, чтобы загрузить 0xfedcba0987654321 по MIPS, 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. Возможно, стоимость кэша инструкций ниже, чем стоимость кэша данных, или, возможно, кому-то просто не нравится эта идея
Вот пример рукописного постоянного пула в 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