Как MIPS хранит число больше 32 бит? - PullRequest
0 голосов
/ 10 ноября 2018

Я искал ответ на этот вопрос, но не мог найти ясного. Делит ли он число между несколькими регистрами или просто не справляется? Я попытался протестировать его с MARS и использовать номер 4294967296, который равен 0x100000000, но регистр сохранил только 0x00000000, поэтому бит «1» пропущен. Есть ли способ справиться с такими цифрами?

1 Ответ

0 голосов
/ 10 ноября 2018

Используйте 2 регистра, дополнительный для старшей половины. MIPS не имеет флагов, поэтому нет способа добавить int64_t в 2 инструкции add / add-with-carry, как это делается во многих других ISA, но вы можете посмотреть на вывод компилятора для функции C, которая добавляет две 64 -битные целые числа достаточно легко.

#include <stdint.h>

int64_t add64(int64_t a, int64_t b) { 
    return a+b;
}

скомпилировано для MIPS в проводнике компилятора Godbolt с gcc5.4 -O3:

add64:
    addu    $3,$5,$7
    sltu    $5,$3,$5     # check for carry-out with  sum_lo < a_lo  (unsigned)
    addu    $2,$4,$6     # add high halves
    j       $31          # return (with a branch-delay slot)
    addu    $2,$5,$2     # add the carry-out from the low half into the high half

В памяти , MIPS в режиме с прямым порядком байтов (более распространенный выбор для MIPS) хранит все 64-битное целое число в порядке с прямым порядком байтов, таким образом «старшая половина» (большинство 32 значащих бита) находится по нижнему адресу , поэтому старший байт этого слова находится по младшему адресу, а все 8 байтов расположены в порядке убывания значения места.

void add64_store(int64_t a, int64_t b, int64_t *res) { 
    *res = a+b;
}

  ## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
    addu    $7,$5,$7        # low half
    lw      $2,16($sp)
    sltu    $5,$7,$5        # carry-out
    addu    $4,$4,$6        
    addu    $5,$5,$4        # high half
    sw      $5,0($2)        # store the high half to res[0..3]
    j       $31
    sw      $7,4($2)        # store the low half to res[4..7]

Как видно из использованных номеров регистров, соглашение о вызовах передает верхнюю половину в регистр с меньшим номером (ранее arg) , в отличие от архитектур с прямым порядком байтов, где старшая половина входит в более поздний слот прохождения арг. Это заставляет вещи работать как нужно, если вы исчерпали регистр и в стеке передается int64_t.


В архитектуре с флагами и инструкцией добавления с переносом (например, ARM32) вы получаете инструкцию добавления, которая создает 33-битный результат в C:R0 (старший бит в флаге переноса, младший 32 в регистр).

add64:
    adds    r0, r2, r0    @ ADD and set flags
    adc     r1, r3, r1    @ r1 = r1 + r3 + carry
    bx      lr

Вы пометили этот MIPS32, поэтому у вас нет 64-битного расширения для ISA (введено в MIPS III в 1991 году). Я думаю, что некоторые современные встроенные процессоры MIPS все еще только 32-битные. (То же самое относится и к 128-разрядным целым числам в MIPS64).

...