Загрузка адреса в MIPS64 - PullRequest
7 голосов
/ 12 октября 2010

Это, вероятно, простая, очевидная вещь, которую я просто не вижу, но как мне загрузить адрес в процессор 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]

Это кажется мне немного ... замысловатым для чего-то такого базового, как загрузка адреса, так что я уверен, что я что-то упустил.

Что я пропустил (если вообще что-нибудь)?

Ответы [ 2 ]

3 голосов
/ 28 июня 2011

Я думаю, что если вам нужно загрузить много констант, вы должны поместить его в постоянный пул (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

0 голосов
/ 22 июля 2016

адрес, так что я уверен, что что-то упустил. Что я пропустил (если вообще что-нибудь)?

Что вам не хватает, так это то, что даже в Mips64 размер инструкции остается 32-битным (4 байта) . В этой 32-битной системе кодирования машинного кода комбинация 'la', переведенная в 'lui' + 'ori', может обрабатывать максимум 32-битное значение (адрес). В 4-байтовой машинной инструкции недостаточно битов для простого кодирования 64-битного адреса. Для работы с 64-битным адресом используется больше итераций (lui + ori) и сдвиги (dsll).

Paxym

...