Перетасовка байтов в массиве (586 и SSE2)

Тема в разделе "WASM.A&O", создана пользователем SolidCode, 11 дек 2006.

  1. SolidCode

    SolidCode New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2002
    Сообщения:
    162
    Адрес:
    Kazakhstan
    Есть массив длиной 48 байт. Нужен алгоритм быстрого копирования/сдвига байтов в массиве.
    Логически массив делится на 6 блоков по 8 байт.
    Алгоритм для 586 должен произвести операцию в памяти.
    Алгоритм для SSE2 не обязан сохранять результат в память. Массив загружается в регистры следующим образом:
    xmm0 = 0:1 (блок 0 в low qword, блок 1 в high qword)
    xmm1 = 3:2
    xmm2 = 5:4
    В этих же регистрах должен быть и результат.
    В прикреплённом файле последняя версия макросов для SSE (нужен ml.exe версии 6.15). Пользуйте на свой страх и риск.

    Вот описание первой перетасовки:
    0.0->5.0 4.0->0.0 2.2->4.6 5.0->2.4
    0.6->5.6 4.6->0.6 2.3->4.7 5.6->2.2
    0.7->5.7 4.7->0.7 2.4->4.0 5.7->2.3
    3.[0..7] rotate left (типа ROL только на все 8 байтов)

    Для 586 я фактически копирую отдельные байты через 8-битные регистры и сохраняю их.
    ROL делаю с помощью SHLD. Мне кажется это самый быстрый вариант.

    Код (Text):
    1.     mov     ah,[esi].CubeSide0.Sqr0
    2.     mov     dh,[esi].CubeSide0.Sqr6
    3.     mov     ch,[esi].CubeSide0.Sqr7
    4.    
    5.     mov     al,[esi].CubeSide4.Sqr0
    6.     mov     dl,[esi].CubeSide4.Sqr6
    7.     mov     cl,[esi].CubeSide4.Sqr7
    8.     mov     [esi].CubeSide0.Sqr0,al
    9.     mov     [esi].CubeSide0.Sqr6,dl
    10.     mov     [esi].CubeSide0.Sqr7,cl
    11.    
    12.     mov     al,[esi].CubeSide2.Sqr2
    13.     mov     dl,[esi].CubeSide2.Sqr3
    14.     mov     cl,[esi].CubeSide2.Sqr4
    15.     mov     [esi].CubeSide4.Sqr0,cl
    16.     mov     [esi].CubeSide4.Sqr6,al
    17.     mov     [esi].CubeSide4.Sqr7,dl
    18.    
    19.     mov     al,[esi].CubeSide5.Sqr0
    20.     mov     dl,[esi].CubeSide5.Sqr6
    21.     mov     cl,[esi].CubeSide5.Sqr7
    22.     mov     [esi].CubeSide2.Sqr2,dl
    23.     mov     [esi].CubeSide2.Sqr3,cl
    24.     mov     [esi].CubeSide2.Sqr4,al
    25.    
    26.     mov     [esi].CubeSide5.Sqr0,ah
    27.     mov     [esi].CubeSide5.Sqr6,dh
    28.     mov     [esi].CubeSide5.Sqr7,ch
    29.    
    30.     mov     eax,dword ptr [esi].CubeSide3
    31.     mov     edx,dword ptr [esi].CubeSide3.Sqr4
    32.     shld    dword ptr [esi].CubeSide3,edx,16
    33.     shld    dword ptr [esi].CubeSide3.Sqr4,eax,16
    Для выполнения аналогичной задачи средствами SSE2 приходится обнулять (AND) соответствующие байты в источнике и в конечном блоке, а потом OR-ить их и раскладывать назад. Код прилагается. В регистрах 6 и 7 лежат константы для логических операций.
    Может ли кто-нибудь предложить более быстрый вариант? Может есть более быстрый алгоритм? Или этот вариант можно ускорить?
    Код (Text):
    1.                     xmm_xchgLq  xmm4,xmm1
    2.             xmm_xchg    xmm3,xmm2
    3.                     xmm_lo2hi   xmm4,xmm0
    4.     pand    xmm2,xmm7   ;!.dq067
    5.                             xmm_mov xmm5,xmm4
    6.             pand    xmm3,xmm6   ;.dq067
    7.                     pand    xmm4,xmm7   ;!.dq067
    8.             xmm_xchgLq  xmm3,xmm3
    9.                             pand    xmm5,xmm6   ;.dq067
    10.             xmm_xchgLq  xmm4,xmm4
    11.     xmm_rolHq   xmm1,xmm1
    12.                     por     xmm4,xmm3
    13.     por     xmm2,xmm5
    14.                     xmm_hi2lo   xmm0,xmm4
    15.                     xmm_lo2lo   xmm1,xmm4