mmx_blend.S revision d60bb2fbc8b61e9748ce9c235acd4e870a2df613
19add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul/*
29add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * Written by Jos� Fonseca <j_r_fonseca@yahoo.co.uk>
39add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul */
49add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
50a59ca6cae6ef24990f1c41c8c7857214489443cGareth Hughes#include "matypes.h"
6afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
79add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul/*
89add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * make the following approximation to the division (Sree)
99add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
109add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   rgb*a/255 ~= (rgb*(a+1)) >> 256
119add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
129add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * which is the fastest method that satisfies the following OpenGL criteria
139add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
149add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   0*0 = 0 and 255*255 = 255
159add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
169add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * note this one should be used alone
179add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul */
189add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#define GMBT_ALPHA_PLUS_ONE	0
199add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
209add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul/*
219add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * take the geometric series approximation to the division
229add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
239add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   t/255 = (t >> 8) + (t >> 16) + (t >> 24) ..
249add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
259add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * in this case just the first two terms to fit in 16bit arithmetic
269add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
279add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   t/255 ~= (t + (t >> 8)) >> 8
289add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
299add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * note that just by itself it doesn't satisfies the OpenGL criteria, as 255*255 = 254,
309add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * so the special case a = 255 must be accounted or roundoff must be used
319add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul */
329add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#define GMBT_GEOMETRIC_SERIES	1
339add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
349add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul/*
359add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * when using a geometric series division instead of truncating the result
369add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * use roundoff in the approximation (Jim Blinn)
379add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
389add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   t = rgb*a + 0x80
399add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
409add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * achieving the exact results
419add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul */
42cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul#define GMBT_ROUNDOFF		0
43cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul
44cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul/* instead of the roundoff this adds a small correction to satisfy the OpenGL criteria
45cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul *
46cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul *   t/255 ~= (t + (t >> 8) + (t >> 15)) >> 8
47cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul *
48cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul * note that although is faster than rounding off it doesn't give always the exact results
49cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul */
50cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul#define GMBT_GEOMETRIC_CORRECTION	1
519add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
529add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul/*
539add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * do
549add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
559add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   s = (q - p)*a + q
569add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
579add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * instead of
589add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
599add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *   s = p*a + q*(1-a)
609add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul *
619add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * this eliminates a multiply at the expense of
629add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul * complicating the roundoff but is generally worth it
639add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul */
649add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#define GMBT_SIGNED_ARITHMETIC	1
659add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
669add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
679add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    SEG_DATA
68afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
699add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulALIGNDATA8
709add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paulconst_80:
719add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul	D_LONG 0x00800080, 0x00800080
729add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
73afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
749add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul   SEG_TEXT
75afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
76afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen GerlachALIGNTEXT16
77865322f931197c5c73c57b366b64300894565dabBrian PaulGLOBL GLNAME(_mesa_mmx_blend_transparency)
78afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
7901bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul/*
8001bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul * void blend_transparency( GLcontext *ctx,
8101bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul *                          GLuint n,
8201bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul *                          const GLubyte mask[],
8301bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul *                          GLchan rgba[][4],
8401bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul *                          CONST GLchan dest[][4] )
8501bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul *
8601bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul * Common transparency blending mode.
8701bcd83defe1e258007a4449edb8bd3072f008b0Brian Paul */
88865322f931197c5c73c57b366b64300894565dabBrian PaulGLNAME( _mesa_mmx_blend_transparency ):
89b63e8556fa9655bdfcc69fa04663e854f7fb2fbdBrian Paul
909add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUSH_L     ( EBP )
919add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( ESP, EBP )
929add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUSH_L     ( ESI )
939add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUSH_L     ( EDI )
949add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUSH_L     ( EBX )
959add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
969add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( REGOFF(12, EBP), ECX )		/* n */
979add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_L      ( CONST(0), ECX)
989add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JE         ( LLBL (GMBT_return) )
999add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1009add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( REGOFF(16, EBP), EBX )		/* mask */
1019add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( REGOFF(20, EBP), EDI )         /* rgba */
1029add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( REGOFF(24, EBP), ESI )         /* dest */
1039add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1049add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    TEST_L     ( CONST(4), EDI )		/* align rgba on an 8-byte boundary */
1059add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JZ         ( LLBL (GMBT_align_end) )
1069add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1079add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_B      ( CONST(0), REGIND(EBX) )	/* *mask == 0 */
1089add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JE         ( LLBL (GMBT_align_continue) )
1099add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1109add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PXOR       ( MM0, MM0 )			/*   0x0000  |   0x0000  |   0x0000  |   0x0000  */
1119add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1129add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( REGIND(ESI), MM1 )		/*     |     |     |     | qa1 | qb1 | qg1 | qr1 */
1139add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( REGIND(EDI), MM2 )		/*     |     |     |     | pa1 | pb1 | pg1 | pr1 */
1149add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1159add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM1 )			/*    qa1    |    qb1    |    qg1    |    qr1    */
1169add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM2 )			/*    pa1    |    pb1    |    pg1    |    pr1    */
1179add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1189add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
1199add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1209add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHWD  ( MM3, MM3 )			/*    pa1    |    pa1    |           |           */
1219add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHDQ  ( MM3, MM3 )                     /*    pa1    |    pa1    |    pa1    |    pa1    */
1229add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1239add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ALPHA_PLUS_ONE
1249add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
1259add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1269add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM3 )                     /*   pa1 + 1 |   pa1 + 1 |   pa1 + 1 |   pa1 + 1 */
1279add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1289add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1299add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
1309add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM1, MM2 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */
1319add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1329add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM1 )		/*                    q1 << 8                    */
1339add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1349add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
1359add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM4 )
1369add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1379add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1389add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*              t1 = (q1 - p1)*pa1               */
1399add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1409add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
1419add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(15), MM4 )		/*                 q1 > p1 ? 1 : 0               */
1429add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1439add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM4 )		/*             q1 > p1 ? 0x100 : 0               */
1449add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1459add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM2 )                     /*                  t1 -=? 0x100                 */
1469add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1479add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1489add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#else
1499add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
1509add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM4 )			/*   0x00ff  |   0x00ff  |   0x00ff  |   0x00ff  */
1519add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM4, MM0 )
1529add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1539add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*                     p1*pa1                    */
1549add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1559add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM3, MM0 )			/* 255 - pa1 | 255 - pa1 | 255 - pa1 | 255 - pa1 */
1569add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1579add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM0, MM1 )			/*                  q1*(255 - pa1)               */
1589add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1599add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*           t1 = p1*pa1 + q1*(255 - pa1)        */
1609add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1619add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1629add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
1639add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( CONTENT(const_80), MM4 )
1649add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1659add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM4, MM2 )                     /*                 t1 += 0x80                    */
1669add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1679add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1689add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_GEOMETRIC_SERIES
1699add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
1709add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1719add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM3 )		/*                    t1 >> 8                    */
1729add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1739add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM3, MM2 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */
174d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca
175d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca#if GMBT_GEOMETRIC_CORRECTION
176d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca    PSRLW      ( CONST(7), MM3 )		/*                    t1 >> 15                   */
177d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca
178d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca    PADDW      ( MM3, MM2 )			/*  t1 + (t1 >> 8) + (t1 >>15) ~= (t1/255) << 8  */
179d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca#endif
1809add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1819add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1829add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
1839add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*              (t1/255 + q1) << 8               */
1849add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
1859add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1869add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM2 )		/*    sa1    |    sb1    |    sg1    |    sr1    */
1879add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1889add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PACKUSWB   ( MM0, MM2 )			/*     |     |     |     | sa1 | sb1 | sg1 | sr1 */
1899add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( MM2, REGIND(EDI) )
1909add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1919add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_align_continue):
1929add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1939add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    DEC_L      ( ECX )				/* n -= 1 */
1949add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    INC_L      ( EBX )		                /* mask += 1 */
1959add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    ADD_L      ( CONST(4), EDI )		/* rgba += 1 */
1969add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    ADD_L      ( CONST(4), ESI )		/* dest += 1 */
1979add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
1989add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_align_end):
1999add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2009add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_L      ( CONST(2), ECX)
2019add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JB         ( LLBL (GMBT_loop_end) )
202afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
203b63e8556fa9655bdfcc69fa04663e854f7fb2fbdBrian PaulALIGNTEXT16
2049add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_loop_begin):
2059add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2069add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_W      ( CONST(0), REGIND(EBX) )	/* *mask == 0 && *(mask + 1) == 0 */
2079add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JE         ( LLBL (GMBT_loop_continue) )
2089add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2099add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    /* NOTE: the instruction pairing when multiple pipelines are available must be checked */
2109add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2119add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PXOR       ( MM0, MM0 )			/*   0x0000  |   0x0000  |   0x0000  |   0x0000  */
2129add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2139add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( REGIND(ESI), MM7 )		/* qa2 | qb2 | qg2 | qr2 | qa1 | qb1 | qg1 | qr1 */
2149add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( REGIND(EDI), MM6 )		/* pa2 | pb2 | pg2 | pr2 | pa1 | pb1 | pg1 | pr1 */
2159add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2169add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM7, MM1 )
2179add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM6, MM2 )
2189add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2199add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM1 )			/*    qa1    |    qb1    |    qg1    |    qr1    */
2209add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHBW  ( MM0, MM7 )                     /*    qa2    |    qb2    |    qg2    |    qr2    */
2219add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM2 )			/*    pa1    |    pb1    |    pg1    |    pr1    */
2229add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHBW  ( MM0, MM6 )                     /*    pa2    |    pb2    |    pg2    |    pr2    */
2239add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2249add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
2259add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM6, MM5 )
2269add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2279add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHWD  ( MM3, MM3 )			/*    pa1    |    pa1    |           |           */
2289add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHWD  ( MM5, MM5 )			/*    pa2    |    pa2    |           |           */
2299add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHDQ  ( MM3, MM3 )                     /*    pa1    |    pa1    |    pa1    |    pa1    */
2309add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHDQ  ( MM5, MM5 )                     /*    pa2    |    pa2    |    pa2    |    pa2    */
2319add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2329add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ALPHA_PLUS_ONE
2339add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
2349add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2359add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM3 )                     /*   pa1 + 1 |   pa1 + 1 |   pa1 + 1 |   pa1 + 1 */
2369add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM5 )                     /*   pa2 + 1 |   pa2 + 1 |   pa2 + 1 |   pa2 + 1 */
2379add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
2389add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2399add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
2409add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM1, MM2 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */
2419add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM7, MM6 )                     /* pa2 - qa2 | pb2 - qb2 | pg2 - qg2 | pr2 - qr2 */
2429add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2439add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM1 )		/*                    q1 << 8                    */
2449add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM7 )		/*                    q2 << 8                    */
2459add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2469add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
2479add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM0 )
2489add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM6, MM4 )
2499add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
2509add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2519add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*              t1 = (q1 - p1)*pa1               */
2529add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM5, MM6 )			/*              t2 = (q2 - p2)*pa2               */
2539add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2549add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
2559add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(15), MM0 )		/*                 q1 > p1 ? 1 : 0               */
2569add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(15), MM4 )		/*                 q2 > q2 ? 1 : 0               */
2579add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2589add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM0 )		/*             q1 > p1 ? 0x100 : 0               */
2599add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM4 )		/*             q2 > q2 ? 0x100 : 0               */
2609add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2619add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM0, MM2 )                     /*                  t1 -=? 0x100                 */
2629add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM7 )                     /*                  t2 -=? 0x100                 */
2639add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
2649add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2659add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#else
2669add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
2679add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM4 )			/*   0x00ff  |   0x00ff  |   0x00ff  |   0x00ff  */
2689add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM4, MM0 )
2699add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2709add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*                     p1*pa1                    */
2719add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM5, MM6 )			/*                     p2*pa2                    */
2729add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2739add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM3, MM0 )			/* 255 - pa1 | 255 - pa1 | 255 - pa1 | 255 - pa1 */
2749add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM5, MM4 )			/* 255 - pa2 | 255 - pa2 | 255 - pa2 | 255 - pa2 */
2759add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2769add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM0, MM1 )			/*                  q1*(255 - pa1)               */
2779add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM4, MM7 )			/*                  q2*(255 - pa2)               */
2789add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2799add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*           t1 = p1*pa1 + q1*(255 - pa1)        */
2809add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM7, MM6 )			/*           t2 = p2*pa2 + q2*(255 - pa2)        */
2819add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
2829add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2839add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
2849add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( CONTENT(const_80), MM4 )
2859add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2869add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM4, MM2 )                     /*                 t1 += 0x80                    */
2879add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM4, MM6 )                     /*                 t2 += 0x80                    */
2889add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
2899add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2909add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_GEOMETRIC_SERIES
2919add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
2929add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM6, MM5 )
2939add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2949add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM3 )		/*                    t1 >> 8                    */
2959add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM5 )		/*                    t2 >> 8                    */
2969add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
2979add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM3, MM2 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */
2989add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM5, MM6 )			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */
299cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul
300cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul#if GMBT_GEOMETRIC_CORRECTION
301cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul    PSRLW      ( CONST(7), MM3 )		/*                    t1 >> 15                   */
302cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul    PSRLW      ( CONST(7), MM5 )		/*                    t2 >> 15                   */
303cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul
304cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul    PADDW      ( MM3, MM2 )			/*  t1 + (t1 >> 8) + (t1 >>15) ~= (t1/255) << 8  */
305cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul    PADDW      ( MM5, MM6 )			/*  t2 + (t2 >> 8) + (t2 >>15) ~= (t2/255) << 8  */
306cffb351a62ebc0e1954422cf749458106671b9d6Brian Paul#endif
3079add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3089add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3099add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
3109add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*              (t1/255 + q1) << 8               */
3119add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM7, MM6 )			/*              (t2/255 + q2) << 8               */
3129add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3139add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3149add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM2 )		/*    sa1    |    sb1    |    sg1    |    sr1    */
3159add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM6 )		/*    sa2    |    sb2    |    sg2    |    sr2    */
3169add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3179add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PACKUSWB   ( MM6, MM2 )			/* sa2 | sb2 | sg2 | sr2 | sa1 | sb1 | sg1 | sr1 */
3189add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, REGIND(EDI) )
3199add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3209add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_loop_continue):
3219add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3229add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    DEC_L      ( ECX )
3239add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    DEC_L      ( ECX )				/* n -= 2 */
3249add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    ADD_L      ( CONST(2), EBX )		/* mask += 2 */
3259add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    ADD_L      ( CONST(8), EDI )		/* rgba += 2 */
3269add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    ADD_L      ( CONST(8), ESI )		/* dest += 2 */
3279add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_L      ( CONST(2), ECX )
3289add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JAE        ( LLBL (GMBT_loop_begin) )
3299add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3309add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_loop_end):
3319add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3329add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_L      ( CONST(1), ECX )
3339add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JB         ( LLBL (GMBT_done) )
3349add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3359add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    CMP_B      ( CONST(0), REGIND(EBX) )	/* *mask == 0 */
3369add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    JE         ( LLBL (GMBT_done) )
3379add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3389add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PXOR       ( MM0, MM0 )			/*   0x0000  |   0x0000  |   0x0000  |   0x0000  */
3399add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3409add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( REGIND(ESI), MM1 )		/*     |     |     |     | qa1 | qb1 | qg1 | qr1 */
3419add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( REGIND(EDI), MM2 )		/*     |     |     |     | pa1 | pb1 | pg1 | pr1 */
3429add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3439add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM1 )			/*    qa1    |    qb1    |    qg1    |    qr1    */
3449add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM2 )			/*    pa1    |    pb1    |    pg1    |    pr1    */
3459add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3469add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
3479add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3489add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHWD  ( MM3, MM3 )			/*    pa1    |    pa1    |           |           */
3499add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKHDQ  ( MM3, MM3 )                     /*    pa1    |    pa1    |    pa1    |    pa1    */
3509add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3519add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ALPHA_PLUS_ONE
3529add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
3539add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3549add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM3 )                     /*   pa1 + 1 |   pa1 + 1 |   pa1 + 1 |   pa1 + 1 */
3559add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3569add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3579add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
3589add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM1, MM2 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */
3599add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3609add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM1 )		/*                    q1 << 8                    */
3619add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3629add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
3639add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM4 )
3649add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3659add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3669add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*              t1 = (q1 - p1)*pa1               */
3679add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3689add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
3699add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(15), MM4 )		/*                 q1 > p1 ? 1 : 0               */
3709add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3719add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSLLW      ( CONST(8), MM4 )		/*             q1 > p1 ? 0x100 : 0               */
3729add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3739add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM4, MM2 )                     /*                  t1 -=? 0x100                 */
3749add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3759add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3769add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#else
3779add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PCMPEQW    ( MM4, MM4 )			/*   0xffff  |   0xffff  |   0xffff  |   0xffff  */
3789add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PUNPCKLBW  ( MM0, MM4 )			/*   0x00ff  |   0x00ff  |   0x00ff  |   0x00ff  */
3799add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM4, MM0 )
3809add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3819add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM3, MM2 )			/*                     p1*pa1                    */
3829add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3839add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSUBW      ( MM3, MM0 )			/* 255 - pa1 | 255 - pa1 | 255 - pa1 | 255 - pa1 */
3849add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3859add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PMULLW     ( MM0, MM1 )			/*                  q1*(255 - pa1)               */
3869add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3879add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*           t1 = p1*pa1 + q1*(255 - pa1)        */
3889add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3899add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3909add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_ROUNDOFF
3919add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( CONTENT(const_80), MM4 )
3929add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3939add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM4, MM2 )                     /*                 t1 += 0x80                    */
3949add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
3959add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3969add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_GEOMETRIC_SERIES
3979add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVQ       ( MM2, MM3 )
3989add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
3999add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM3 )		/*                    t1 >> 8                    */
4009add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4019add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM3, MM2 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */
402d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca
403d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca#if GMBT_GEOMETRIC_CORRECTION
404d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca    PSRLW      ( CONST(7), MM3 )		/*                    t1 >> 15                   */
405d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca
406d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca    PADDW      ( MM3, MM2 )			/*  t1 + (t1 >> 8) + (t1 >>15) ~= (t1/255) << 8  */
407d60bb2fbc8b61e9748ce9c235acd4e870a2df613José Fonseca#endif
4089add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
4099add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4109add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#if GMBT_SIGNED_ARITHMETIC
4119add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PADDW      ( MM1, MM2 )			/*              (t1/255 + q1) << 8               */
4129add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul#endif
4139add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4149add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PSRLW      ( CONST(8), MM2 )		/*    sa1    |    sb1    |    sg1    |    sr1    */
4159add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4169add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    PACKUSWB   ( MM0, MM2 )			/*     |     |     |     | sa1 | sb1 | sg1 | sr1 */
4179add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOVD       ( MM2, REGIND(EDI) )
4189add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4199add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_done):
4209add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
421afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach    EMMS
422afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
4239add9a21d8c51ee4238169265541fa9a40f0a8b0Brian PaulLLBL (GMBT_return):
4249add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul
4259add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    POP_L      ( EBX )
4269add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    POP_L      ( EDI )
4279add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    POP_L      ( ESI )
4289add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    MOV_L      ( EBP, ESP )
4299add9a21d8c51ee4238169265541fa9a40f0a8b0Brian Paul    POP_L      ( EBP )
430afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach    RET
431