Понимание блоков asm, написанных для gcc
Что означает следующая сборка в простом C (это должно быть скомпилировано с помощью gcc):
asm volatile
(
"mov.d %0,%4\n\t"
"L1: bge %2,%3,L2\n\t"
"gsLQC1 $f2,$f0,0(%1)\n\t"
"gsLQC1 $f6,$f4,0(%5)\n\t"
"madd.d %0,%0,$f6,$f2\n\t"
"madd.d %0,%0,$f4,$f0\n\t"
"add %1,%1,16\n\t"
"add %2,%2,2\n\t"
"add %5,%5,16\n\t"
"j L1\n\t"
"L2: nop\n\t"
:"=f"(sham)
:"r"(foo),"r"(bar),"r"(ro),"f"(sham),"r"(bo)
:"$f0","$f2","$f4","$f6"
);
После нескольких часов поиска и чтения я придумал следующий ассемблерный код в синтаксисе AT&T:
mov.d %xmm0,%xmm1
L1: bge %ebx,%ecx,L2
gsLQC1 $f2,$f0,0(%eax)
gsLQC1 $f6,$f4,0(%esi)
madd.d %xmm0,%xmm0,$f6,$f2
madd.d %xmm0,%xmm0,$f4,$f0
add %eax,%eax,16
add %ebx,%ebx,2
add %esi,%esi,16
jmp L1
L2: nop
Я нахожусь в процессе нахождения способа запустить это на Windows и обновлю, когда я выясню способ сделать это (после исправления всех ошибок, которые я уверен, что сделал).
У меня очень мало опыта сборки x86, но я смутно признаю, что это цикл, но я не смог найти, что означает инструкция gsLQC1. или какова была бы цель цикла.
Если у вас есть вопросы ко мне, я буду рад ответить на них. Если у вас есть какие-либо идеи, я хотел бы услышать их. Спасибо за ваше время.
РЕДАКТИРОВАТЬ:
Сама функция имеет дело с выполнением разложения по сингулярным числам (SVD), которое в основном связано с матрицами.
Я обновляю ниже некоторые мои собственные комментарии, автор оригинальной сборки не писал их, но я на 80% уверен, что они правильные, учитывая мое исследование записи блока asm для GCC.
asm volatile
(
"mov.d %0,%4\n\t"
"L1: bge %2,%3,L2\n\t"
"gsLQC1 $f2,$f0,0(%1)\n\t"
"gsLQC1 $f6,$f4,0(%5)\n\t"
"madd.d %0,%0,$f6,$f2\n\t"
"madd.d %0,%0,$f4,$f0\n\t"
"add %1,%1,16\n\t"
"add %2,%2,2\n\t"
"add %5,%5,16\n\t"
"j L1\n\t"
"L2: nop\n\t"
:"=f"(sham) /*Corresponds to %0 in the above code*/
:"r"(foo) /*Corresponds to %1*/,"r"(bar) /*%2*/,"r"(ro) /*%3*/,"f"(sham) /*%4*/,"r"(bo) /*%5*/
:"$f0","$f2","$f4","$f6"
);
Я предположил, что это было в x86, но, скорее всего, ошибся. Я полагаю, что выше написана сборка MIPS64 для процессора семейства loongson.
Спасибо за интерес к вопросу. Я ценю ваше время. Опять же, если есть какие-либо вопросы, я был бы рад сделать все возможное, чтобы ответить на них.
PS оригинальный код можно найти здесь, а сборка, о которой я спрашиваю, начинается в строке 189
1 ответ
Это на самом деле не ответ, но он также не вписывается в комментарий. Учитывая, что вы опускаете несколько критических частей информации (для какого процессора предназначены исходные инструкции, типы данных параметров, общее представление о том, что делает код и т. Д.), Трудно найти хороший ответ.
В общем смысле я бы подумал:
float messy(const float *foo, int bar, int ro, const float *bo)
{
float sham = 0;
while (bar < ro)
{
__m256 a = _mm256_load_ps(foo);
__m256 b = _mm256_load_ps(bar);
__m256 c = _mm256_add_ps(a, a);
__m256 d = _mm256_add_ps(b, b);
foo += 2;
bar += 2;
bo += 2;
}
return sham;
}
Это будет не совсем правильно, так как (между прочим) sham
не устанавливается Но это место для начала. Без подробностей чего madd.d
делает (что трудно сказать, не зная, о каком оборудовании мы говорим), это как можно ближе к вам.
Просто чтобы подчеркнуть то, что я сказал в своем комментарии, оригинальный код не выглядит хорошо написанным (изменение параметров только для чтения, двойных переходов, НЕТ КОММЕНТАРИЙ и т. Д.).