Умножение n-битного числа на m-битное число дает (n + m) битовое число. Таким образом, умножение трех 32-битных чисел дает 96-битное произведение
Предположим, что три числа - это a, b и c, мы имеем следующий результат
a*b = ABH*2³² + ABL
c(a*b) = c(ABH*2³² + ABL)
= c*ABH*2³² + c*ABL
= (CABH_H*2³² + CABH_L)*2³² + (CABL_H*2³² + CABL_L)
= CABH_H*2⁶⁴ + (CABH_L + CABL_H)*2³² + CABL_L
где H и L - это старшая и младшая части результата, которые сохраняются в регистрах HI и LO соответственно. Здесь умножение на 2 32 и 2 64 будет заменено сдвигом влево на 32 и 64 соответственно.
Итак, в MIPS32, если a, b и c хранятся в $ s0, $ s1 и $ s2, мы можем выполнить математику, как показано ниже.
multu $s0, $s1 # (HI, LO) = a*b
mfhi $t0 # t0 = ABH
mflo $t1 # t1 = ABL
multu $s2, $t1 # (HI, LO) = c*ABL
mfhi $t4 # t4 = CABL_H
mflo $s7 # s7 = CABL_L
multu $s2, $t0 # (HI, LO) = c*ABH
mfhi $s5 # s5 = CABH_H
mflo $t3 # t3 = CABH_L
addu $s6, $t3, $t4 # s6 = CABH_L + CABL_H
sltu $t5, $s6, $t3 # carry if s6 overflows
addu $s5, $s5, $t5 # add carry to s5
# result = (s5 << 64) | (s6 << 32) | s7
Результат сохраняется в кортеже ($ s5, $ s6, $ s7)
В MIPS64 все будет намного проще:
mul(unsigned int, unsigned int, unsigned int):
multu $4,$5
dext $6,$6,0,32
mfhi $3
mflo $2
dins $2,$3,32,32
dmultu $6,$2
mflo $3
j $31
mfhi $2
Вам может потребоваться небольшая модификация для подписанных операций
Вот пример вывода сборки из GCC на Godbolt
person
phuclv
schedule
10.08.2014