Затык на знаковых операциях в MMX

Тема в разделе "WASM.ASSEMBLER", создана пользователем Relic, 2 апр 2008.

  1. Relic

    Relic Member

    Публикаций:
    0
    Регистрация:
    10 сен 2003
    Сообщения:
    79
    В общем есть такая формула (blending):
    Result := Fa * (Frgb - Brgb) shr 8 + Brgb, которую я перевожу на MMX. Здесь Fa - это байт, Frgb, Brgb, Result - dword. И всё бы хорошо, если бы всегда было Frgb > Brgb (побайтово, младшие 3 разряда), но в противном случае никак не могу получить правильный результат. Посмотрите, пожалуйста, и помогите найти правильное решение, а то уже голова не варит :dntknw:
    Вот код и лог выполнения на примере таких данных (случай Frgb > Brgb, правильный результат):
    f = EAX = B7 58 58 58 (старший разряд = Fa, остальные - Frgb)
    b = EDX = 53 1D 1D 54
    Код (Text):
    1.   MOVD      MM1,EAX        //* 00 00 00 00 B7 58 58 58     =Fa
    2.   PXOR      MM3,MM3
    3.   PUNPCKLBW MM1,MM3        //* 00 B7 00 58 00 58 00 58     =Fa: byte to word
    4.   MOVD      MM0,EAX        //* 00 00 00 00 B7 58 58 58     =f
    5.   PUNPCKHWD MM1,MM1        //* 00 B7 00 B7 00 58 00 58
    6.   MOVD      MM2,EDX        //* 00 00 00 00 53 1D 1D 54     =b
    7.   PUNPCKHDQ MM1,MM1        //* 00 B7 00 B7 00 B7 00 B7     = выделил только Fa
    8.   PSUBB     MM0,MM2        //* 00 00 00 00 64 3B 3B 04     =f-b
    9.   PUNPCKLBW MM0,MM3        //* 00 64 00 3B 00 3B 00 04     =f-b: byte to word
    10.   PMULLW    MM0,MM1        //* 47 7C 2A 2D 2A 2D 02 DC     =Fa*(f-b): word
    11.   PSRLW     MM0,8          //* 00 47 00 2A 00 2A 00 02     =Fa*(f-b) shr 8: word
    12.   PUNPCKLBW MM2,MM3        //* 00 53 00 1D 00 1D 00 54     =b: byte to word
    13.   PADDW     MM2,MM0        //* 00 9A 00 47 00 47 00 56     =Fa*(f-b) shr 8 + b: word
    14.   PACKUSWB  MM2,MM2        //* 9A 47 47 56 9A 47 47 56     = pack result
    15.   MOVD      EDX,MM2        //* 9A 47 47 56
    Ниже случай Frgb < Brgb, неправильный результат:
    f = EAX = 83 00 00 00 (старший разряд = Fa, остальные - Frgb)
    b = EDX = 53 1D 1D 54
    Код (Text):
    1.   MOVD      MM1,EAX        //* 00 00 00 00 83 00 00 00     =Fa
    2.   PXOR      MM3,MM3
    3.   PUNPCKLBW MM1,MM3        //* 00 83 00 00 00 00 00 00     =Fa: byte to word
    4.   MOVD      MM0,EAX        //* 00 00 00 00 83 00 00 00     =f
    5.   PUNPCKHWD MM1,MM1        //* 00 83 00 83 00 00 00 00
    6.   MOVD      MM2,EDX        //* 00 00 00 00 53 1D 1D 54     =b
    7.   PUNPCKHDQ MM1,MM1        //* 00 83 00 83 00 83 00 83     = выделил только Fa
    8.   PSUBB     MM0,MM2        //* 00 00 00 00 30 E3 E3 AC     =f-b
    9.   PUNPCKLBW MM0,MM3        //* 00 30 00 E3 00 E3 00 AC     =f-b: byte to word
    10.   PMULLW    MM0,MM1        //* 18 90 74 29 74 29 58 04     =Fa*(f-b): word
    11.   PSRLW     MM0,8          //* 00 18 00 74 00 74 00 58     =Fa*(f-b) shr 8: word
    12.   PUNPCKLBW MM2,MM3        //* 00 53 00 1D 00 1D 00 54     =b: byte to word
    13.   PADDW     MM2,MM0        //* 00 6B 00 91 00 91 00 AC     =Fa*(f-b) shr 8 + b: word
    14.   PACKUSWB  MM2,MM2        //* 6B 91 91 AC 6B 91 91 AC     = pack result
    15.   MOVD      EDX,MM2        //* 6B 91 91 AC  !!! а должно быть 6C 0E 0E 29
    Ошибка случается из-за того, что в строке PSUBB MM0,MM2 пропадают знаки результата операции. Как выйти из этой ситуации?
     
  2. Black_mirror

    Black_mirror Active Member

    Публикаций:
    0
    Регистрация:
    14 окт 2002
    Сообщения:
    1.035
    Relic
    Если переписать формулу так:
    Result := Frgb*Fa/256 + Brgb*(256-Fa)/256,
    то отрицательные числа исчезают.
     
  3. Relic

    Relic Member

    Публикаций:
    0
    Регистрация:
    10 сен 2003
    Сообщения:
    79
    Black_mirror
    Да, это выход, спасибо. Интересно, из-за такого преобразования формулы (было 4, стало 6 операций) насколько упадет, если упадет, производительность?
     
  4. valterg

    valterg Active Member

    Публикаций:
    0
    Регистрация:
    19 авг 2004
    Сообщения:
    2.105
    Relic
    Пять операций

    Result := (Frgb*Fa + Brgb*(256-Fa))/256
     
  5. Further

    Further New Member

    Публикаций:
    0
    Регистрация:
    8 май 2008
    Сообщения:
    1
    Мне кажется проблема в том, что вычитаются байты, а не слова. Такой код имеется для случа с единим фактором смешивания(не проверял, т.к. использую другой способ):

    4. Alpha blended
    ================
    movd mm4,eax
    punpcklwd mm4,mm4
    psrlw mm4,8 ; alpha
    pxor mm7,mm7
    :
    movd mm0,dword ptr[esi]
    movd mm1,dword ptr[edx]
    punpcklbw mm0,mm7
    punpcklbw mm1,mm7
    psubw mm0,mm1
    psllw mm1,8
    pmullw mm0,mm4
    paddw mm1,mm0
    psrlw mm1,8
    packuswb mm1,mm1
    movd dword ptr[edi],mm1
    add esi,4
    add edx,4
    add edi,4
     
  6. Relic

    Relic Member

    Публикаций:
    0
    Регистрация:
    10 сен 2003
    Сообщения:
    79
    Спасибо. Я уже разобрался и со своим кодом :)