Понимание блоков 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 делает (что трудно сказать, не зная, о каком оборудовании мы говорим), это как можно ближе к вам.

Просто чтобы подчеркнуть то, что я сказал в своем комментарии, оригинальный код не выглядит хорошо написанным (изменение параметров только для чтения, двойных переходов, НЕТ КОММЕНТАРИЙ и т. Д.).

Другие вопросы по тегам