Листинг №6
Пример процедуры на
ассемблере умножения двух матриц для
процессора i860
.include "startend.mac"
// Умножение матриц, С = А * В , с размещением данных в кэше
.text
.globl _m_ab
.align 8
_m_ab:
STARTB
// Входные регистры
A=r16 // адрес матрицы А, записанной по строкам
B=r17 // адрес матрицы В, записанной по столбцам
C=r18 // адрес матрицы С, записанной по строкам
L=r19 // число строк в А должно быть не меньше 8
M=r20 // число столбцов в А и строк в В должно быть не меньше 16 и кpатно 4
N=r21 // число столбцов в В должно быть не меньше 2
// сумма произведений ( L*M + M*N ) не должна быть больше 2048/2 ?
// Локальные регистры
RC=r28 // счетчик цикла (строки/столбцы)
DEC=r27 // уменьшитель для указателя на строки/столбцы
Ar=r26 // счетчик строк в А
Bc=r25 // счетчик столбцов в В
Bp=r24 // рабочий указатель для В
SIZ=r23 // число байт в строке из А или столбце из В
A1=f4; A2=f5; A3=f6; A4=f7; A5=f8; A6=f9; A7=f10; A8=f11
// строки А
B1=f12; B2=f13; B3=f14; B4=f15; B5=f16; B6=f17; B7=f18; B8=f19
// столбцы В
T1=f20; T2=f21 // промежуточные результаты
shl 2, M, SIZ //число входных байт
adds -8, r0, DEC //уменьшитель для bla
adds -8, M, RC //счетчик строк/столбцов
adds -4, C, C //начальный индекс С
adds -1, L, Ar //счетчик строк
bla DEC, RC,start_row //инициализация LCC
subs A, SIZ, A //начальный указатель А
start_row::
d.fmov.sd f0, T1 // сдвоенная операция
nop
d.pfmul.ss f0, f0, f0
mov B, Bp //указатель на 1 столбец
// в B
d.pfmul.ss f0, f0, f0
adds SIZ, A, A //указатель на строку
// из А
d.pfmul.ss f0, f0, f0
fld.q 16(Bp), B5 //загрузка 4 из В
d.pfadd.ss f0, f0, f0
fld.q 16(A), A5 //загрузка 4 из А
d.pfadd.ss f0, f0, f0
adds -1, N, Bc //счетчик столбцов
d.pfadd.ss f0, f0, f0
fld.q 0(A), A1 //загрузка 4 из A
inner_loop:: //процесс по 8 строк из А
//и 8 эл.столбцов из В
d.m12apm.ss A5, B5, f0 // сложение и умножение за такт
fld.q 0(Bp), B1 //загрузка 4 из В
d.m12apm.ss A6, B6, f0 //
adds 32, A, A //перевод указателя A
//на 8 элементов
d.m12apm.ss A7, B7, f0 //
adds 32, Bp, Bp //перевод указателя B
//на 8 элементов
d.m12apm.ss A8, B8, f0 //
fld.q 16(Bp), B5 //загрузка 4 из В
d.m12apm.ss A1, B1, f0 //
fld.q 16(A), A5 //загрузка 4 из A
d.m12apm.ss A2, B2, f0 //
nop //
d.m12apm.ss A3, B3, f0 //
bla DEC, RC,inner_loop//выполнять пока есть
//столбцы и строки
d.m12apm.ss A4, B4, f0 //цикл по стоке А
fld.q 0(A), A1 //загрузка 4 из А
//Столбцы или строки закончились
d.m12apm.ss f0, f0, f0 //
subs A, SIZ, A //установка на начало
d.m12apm.ss f0, f0, f0 //
adds -8, M, RC //переинициализация
d.m12apm.ss f0, f0, f0 //
nop //
d.pfadd.ss f0, f0, T1 //
bla DEC, RC,inner_loop//инициализация LCC
d.pfadd.ss T1, T2, T2 //
fld.q 16(A), A5 //загрузка 4 из А
d.pfadd.ss f0, f0, T1 //
fld.q 16(Bp), B5 //загрузка 4 из B
d.pfadd.ss f0, f0, f0 //
fld.q 0(A), A1 //загрузка 4 из A
d.pfadd.ss f0, f0, T2 //
adds -1, Bc, Bc //уменьшение счетчика
d.fadd.ss T1, T2, T1 //
nop
d.pfmul.ss f0, f0, f0
nop
d.pfmul.ss f0, f0, f0
nop
d.pfmul.ss f0, f0, f0
nop
d.pfadd.ss f0, f0, f0 //
fst.l T1, 4(C)++ //запись результата в С
d.pfadd.ss f0, f0, f0 //
nop //
//Продолжение со следующим столбцом из В?
d.pfadd.ss f0, f0, f0 //
bnc.t inner_loop //если есть столбцы в В
//флаг СС от adds
d.fmov.sd f0, T1
nop
//Продолжение со следующей строкой из А?
d.fnop //
xor Ar, r0, r0 //Счетчик строк = 0?
d.fnop //
bnc.t start_row //если счетчик строк<>0
d.fnop //
adds -1, Ar, Ar //уменшение счетчика строк
fnop //выход из dual mode
nop //
fnop //последний
//
ENDB