Home | History | Annotate | Download | only in x86
      1 	;
      2 /*
      3  * Written by Jos Fonseca <j_r_fonseca (at) yahoo.co.uk>
      4  */
      5 
      6 
      7 #ifdef USE_MMX_ASM
      8 #include "assyntax.h"
      9 #include "matypes.h"
     10 
     11 /* integer multiplication - alpha plus one
     12  *
     13  * makes the following approximation to the division (Sree)
     14  *
     15  *   rgb*a/255 ~= (rgb*(a+1)) >> 256
     16  *
     17  * which is the fastest method that satisfies the following OpenGL criteria
     18  *
     19  *   0*0 = 0 and 255*255 = 255
     20  *
     21  * note that MX1 is a register with 0xffffffffffffffff constant which can be easily obtained making
     22  *
     23  *   PCMPEQW    ( MX1, MX1 )
     24  */
     25 #define GMB_MULT_AP1( MP1, MA1, MP2, MA2, MX1 ) \
     26     PSUBW      ( MX1, MA1 )			/*   a1 + 1  |   a1 + 1  |   a1 + 1  |   a1 + 1  */	;\
     27     PMULLW     ( MP1, MA1 )			/*                  t1 = p1*a1                   */	;\
     28 													;\
     29 TWO(PSUBW      ( MX1, MA2 ))			/*   a2 + 1  |   a2 + 1  |   a2 + 1  |   a2 + 1  */	;\
     30 TWO(PMULLW     ( MP2, MA2 ))			/*                  t2 = p2*a2                   */	;\
     31 													;\
     32     PSRLW      ( CONST(8), MA1 )		/*               t1 >> 8 ~= t1/255               */	;\
     33 TWO(PSRLW      ( CONST(8), MA2 ))		/*               t2 >> 8 ~= t2/255               */
     34 
     35 
     36 /* integer multiplication - geometric series
     37  *
     38  * takes the geometric series approximation to the division
     39  *
     40  *   t/255 = (t >> 8) + (t >> 16) + (t >> 24) ..
     41  *
     42  * in this case just the first two terms to fit in 16bit arithmetic
     43  *
     44  *   t/255 ~= (t + (t >> 8)) >> 8
     45  *
     46  * note that just by itself it doesn't satisfies the OpenGL criteria, as 255*255 = 254,
     47  * so the special case a = 255 must be accounted or roundoff must be used
     48  */
     49 #define GMB_MULT_GS( MP1, MA1, MP2, MA2 ) \
     50     PMULLW     ( MP1, MA1 )			/*                  t1 = p1*a1                   */	;\
     51 TWO(PMULLW     ( MP2, MA2 ))			/*                  t2 = p2*a2                   */	;\
     52 													;\
     53     MOVQ       ( MA1, MP1 )										;\
     54     PSRLW      ( CONST(8), MA1 )		/*                    t1 >> 8                    */	;\
     55 													;\
     56 TWO(MOVQ       ( MA2, MP2 ))										;\
     57 TWO(PSRLW      ( CONST(8), MA2 ))		/*                    t2 >> 8                    */	;\
     58 													;\
     59     PADDW      ( MP1, MA1 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */	;\
     60     PSRLW      ( CONST(8), MA1 )		/*    sa1    |    sb1    |    sg1    |    sr1    */	;\
     61 													;\
     62 TWO(PADDW      ( MP2, MA2 ))			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */	;\
     63 TWO(PSRLW      ( CONST(8), MA2 ))		/*    sa2    |    sb2    |    sg2    |    sr2    */
     64 
     65 
     66 /* integer multiplication - geometric series plus rounding
     67  *
     68  * when using a geometric series division instead of truncating the result
     69  * use roundoff in the approximation (Jim Blinn)
     70  *
     71  *   t = rgb*a + 0x80
     72  *
     73  * achieving the exact results
     74  *
     75  * note that M80 is register with the 0x0080008000800080 constant
     76  */
     77 #define GMB_MULT_GSR( MP1, MA1, MP2, MA2, M80 ) \
     78     PMULLW     ( MP1, MA1 )			/*                  t1 = p1*a1                   */	;\
     79     PADDW      ( M80, MA1 )			/*                 t1 += 0x80                    */	;\
     80 													;\
     81 TWO(PMULLW     ( MP2, MA2 ))			/*                  t2 = p2*a2                   */	;\
     82 TWO(PADDW      ( M80, MA2 ))			/*                 t2 += 0x80                    */	;\
     83 													;\
     84     MOVQ       ( MA1, MP1 )										;\
     85     PSRLW      ( CONST(8), MA1 )		/*                    t1 >> 8                    */	;\
     86 													;\
     87 TWO(MOVQ       ( MA2, MP2 ))										;\
     88 TWO(PSRLW      ( CONST(8), MA2 ))		/*                    t2 >> 8                    */	;\
     89 													;\
     90     PADDW      ( MP1, MA1 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */	;\
     91     PSRLW      ( CONST(8), MA1 )		/*    sa1    |    sb1    |    sg1    |    sr1    */	;\
     92 													;\
     93 TWO(PADDW      ( MP2, MA2 ))			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */	;\
     94 TWO(PSRLW      ( CONST(8), MA2 ))		/*    sa2    |    sb2    |    sg2    |    sr2    */
     95 
     96 
     97 /* linear interpolation - geometric series
     98  */
     99 #define GMB_LERP_GS( MP1, MQ1, MA1, MP2, MQ2, MA2) \
    100     PSUBW      ( MQ1, MP1 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */	;\
    101     PSLLW      ( CONST(8), MQ1 )		/*                    q1 << 8                    */	;\
    102     PMULLW     ( MP1, MA1 )			/*              t1 = (q1 - p1)*pa1               */	;\
    103 													;\
    104 TWO(PSUBW      ( MQ2, MP2 ))                    /* pa2 - qa2 | pb2 - qb2 | pg2 - qg2 | pr2 - qr2 */	;\
    105 TWO(PSLLW      ( CONST(8), MQ2 ))		/*                    q2 << 8                    */	;\
    106 TWO(PMULLW     ( MP2, MA2 ))			/*              t2 = (q2 - p2)*pa2               */	;\
    107 													;\
    108     MOVQ       ( MA1, MP1 )										;\
    109     PSRLW      ( CONST(8), MA1 )		/*                    t1 >> 8                    */	;\
    110 													;\
    111 TWO(MOVQ       ( MA2, MP2 ))										;\
    112 TWO(PSRLW      ( CONST(8), MA2 ))		/*                    t2 >> 8                    */	;\
    113 													;\
    114     PADDW      ( MP1, MA1 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */	;\
    115 TWO(PADDW      ( MP2, MA2 ))			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */	;\
    116 													;\
    117     PADDW      ( MQ1, MA1 )			/*              (t1/255 + q1) << 8               */	;\
    118 TWO(PADDW      ( MQ2, MA2 ))			/*              (t2/255 + q2) << 8               */	;\
    119 													;\
    120     PSRLW      ( CONST(8), MA1 )		/*    sa1    |    sb1    |    sg1    |    sr1    */	;\
    121 TWO(PSRLW      ( CONST(8), MA2 ))		/*    sa2    |    sb2    |    sg2    |    sr2    */
    122 
    123 
    124 /* linear interpolation - geometric series with roundoff
    125  *
    126  * this is a generalization of Blinn's formula to signed arithmetic
    127  *
    128  * note that M80 is a register with the 0x0080008000800080 constant
    129  */
    130 #define GMB_LERP_GSR( MP1, MQ1, MA1, MP2, MQ2, MA2, M80) \
    131     PSUBW      ( MQ1, MP1 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */	;\
    132     PSLLW      ( CONST(8), MQ1 )		/*                    q1 << 8                    */	;\
    133     PMULLW     ( MP1, MA1 )			/*              t1 = (q1 - p1)*pa1               */	;\
    134 													;\
    135 TWO(PSUBW      ( MQ2, MP2 ))                    /* pa2 - qa2 | pb2 - qb2 | pg2 - qg2 | pr2 - qr2 */	;\
    136 TWO(PSLLW      ( CONST(8), MQ2 ))		/*                    q2 << 8                    */	;\
    137 TWO(PMULLW     ( MP2, MA2 ))			/*              t2 = (q2 - p2)*pa2               */	;\
    138 													;\
    139     PSRLW      ( CONST(15), MP1 )		/*                 q1 > p1 ? 1 : 0               */	;\
    140 TWO(PSRLW      ( CONST(15), MP2 ))		/*                 q2 > q2 ? 1 : 0               */	;\
    141 													;\
    142     PSLLW      ( CONST(8), MP1 )		/*             q1 > p1 ? 0x100 : 0               */	;\
    143 TWO(PSLLW      ( CONST(8), MP2 ))		/*             q2 > q2 ? 0x100 : 0               */	;\
    144 													;\
    145     PSUBW      ( MP1, MA1 )			/*                  t1 -=? 0x100                 */	;\
    146 TWO(PSUBW      ( MP2, MA2 ))			/*                  t2 -=? 0x100                 */	;\
    147  													;\
    148     PADDW      ( M80, MA1 )			/*                 t1 += 0x80                    */	;\
    149 TWO(PADDW      ( M80, MA2 ))			/*                 t2 += 0x80                    */	;\
    150 													;\
    151     MOVQ       ( MA1, MP1 )										;\
    152     PSRLW      ( CONST(8), MA1 )		/*                    t1 >> 8                    */	;\
    153 													;\
    154 TWO(MOVQ       ( MA2, MP2 ))										;\
    155 TWO(PSRLW      ( CONST(8), MA2 ))		/*                    t2 >> 8                    */	;\
    156 													;\
    157     PADDW      ( MP1, MA1 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */	;\
    158 TWO(PADDW      ( MP2, MA2 ))			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */	;\
    159 													;\
    160     PADDW      ( MQ1, MA1 )			/*              (t1/255 + q1) << 8               */	;\
    161 TWO(PADDW      ( MQ2, MA2 ))			/*              (t2/255 + q2) << 8               */	;\
    162 													;\
    163     PSRLW      ( CONST(8), MA1 )		/*    sa1    |    sb1    |    sg1    |    sr1    */	;\
    164 TWO(PSRLW      ( CONST(8), MA2 ))		/*    sa2    |    sb2    |    sg2    |    sr2    */
    165 
    166 
    167 /* linear interpolation - geometric series with correction
    168  *
    169  * instead of the roundoff this adds a small correction to satisfy the OpenGL criteria
    170  *
    171  *   t/255 ~= (t + (t >> 8) + (t >> 15)) >> 8
    172  *
    173  * note that although is faster than rounding off it doesn't give always the exact results
    174  */
    175 #define GMB_LERP_GSC( MP1, MQ1, MA1, MP2, MQ2, MA2) \
    176     PSUBW      ( MQ1, MP1 )                     /* pa1 - qa1 | pb1 - qb1 | pg1 - qg1 | pr1 - qr1 */	;\
    177     PSLLW      ( CONST(8), MQ1 )		/*                    q1 << 8                    */	;\
    178     PMULLW     ( MP1, MA1 )			/*              t1 = (q1 - p1)*pa1               */	;\
    179 													;\
    180 TWO(PSUBW      ( MQ2, MP2 ))                    /* pa2 - qa2 | pb2 - qb2 | pg2 - qg2 | pr2 - qr2 */	;\
    181 TWO(PSLLW      ( CONST(8), MQ2 ))		/*                    q2 << 8                    */	;\
    182 TWO(PMULLW     ( MP2, MA2 ))			/*              t2 = (q2 - p2)*pa2               */	;\
    183 													;\
    184     MOVQ       ( MA1, MP1 )										;\
    185     PSRLW      ( CONST(8), MA1 )		/*                    t1 >> 8                    */	;\
    186 													;\
    187 TWO(MOVQ       ( MA2, MP2 ))										;\
    188 TWO(PSRLW      ( CONST(8), MA2 ))		/*                    t2 >> 8                    */	;\
    189 													;\
    190     PADDW      ( MA1, MP1 )			/*        t1 + (t1 >> 8) ~= (t1/255) << 8        */	;\
    191     PSRLW      ( CONST(7), MA1 )		/*                    t1 >> 15                   */	;\
    192 													;\
    193 TWO(PADDW      ( MA2, MP2 ))			/*        t2 + (t2 >> 8) ~= (t2/255) << 8        */	;\
    194 TWO(PSRLW      ( CONST(7), MA2 ))		/*                    t2 >> 15                   */	;\
    195 													;\
    196     PADDW      ( MP1, MA1 )			/*  t1 + (t1 >> 8) + (t1 >>15) ~= (t1/255) << 8  */	;\
    197 TWO(PADDW      ( MP2, MA2 ))			/*  t2 + (t2 >> 8) + (t2 >>15) ~= (t2/255) << 8  */	;\
    198 													;\
    199     PADDW      ( MQ1, MA1 )			/*              (t1/255 + q1) << 8               */	;\
    200 TWO(PADDW      ( MQ2, MA2 ))			/*              (t2/255 + q2) << 8               */	;\
    201 													;\
    202     PSRLW      ( CONST(8), MA1 )		/*    sa1    |    sb1    |    sg1    |    sr1    */	;\
    203 TWO(PSRLW      ( CONST(8), MA2 ))		/*    sa2    |    sb2    |    sg2    |    sr2    */
    204 
    205 
    206 /* common blending setup code
    207  *
    208  * note that M00 is a register with 0x0000000000000000 constant which can be easily obtained making
    209  *
    210  *   PXOR      ( M00, M00 )
    211  */
    212 #define GMB_LOAD(rgba, dest, MPP, MQQ) \
    213 ONE(MOVD       ( REGIND(rgba), MPP ))		/*     |     |     |     | qa1 | qb1 | qg1 | qr1 */	;\
    214 ONE(MOVD       ( REGIND(dest), MQQ ))		/*     |     |     |     | pa1 | pb1 | pg1 | pr1 */	;\
    215 													;\
    216 TWO(MOVQ       ( REGIND(rgba), MPP ))		/* qa2 | qb2 | qg2 | qr2 | qa1 | qb1 | qg1 | qr1 */	;\
    217 TWO(MOVQ       ( REGIND(dest), MQQ ))		/* pa2 | pb2 | pg2 | pr2 | pa1 | pb1 | pg1 | pr1 */
    218 
    219 #define GMB_UNPACK(MP1, MQ1, MP2, MQ2, M00) \
    220 TWO(MOVQ       ( MP1, MP2 ))										;\
    221 TWO(MOVQ       ( MQ1, MQ2 ))										;\
    222 													;\
    223     PUNPCKLBW  ( M00, MQ1 )			/*    qa1    |    qb1    |    qg1    |    qr1    */	;\
    224 TWO(PUNPCKHBW  ( M00, MQ2 ))                    /*    qa2    |    qb2    |    qg2    |    qr2    */	;\
    225     PUNPCKLBW  ( M00, MP1 )			/*    pa1    |    pb1    |    pg1    |    pr1    */	;\
    226 TWO(PUNPCKHBW  ( M00, MP2 ))                    /*    pa2    |    pb2    |    pg2    |    pr2    */
    227 
    228 #define GMB_ALPHA(MP1, MA1, MP2, MA2) \
    229     MOVQ       ( MP1, MA1 )										;\
    230 TWO(MOVQ       ( MP2, MA2 ))										;\
    231 													;\
    232     PUNPCKHWD  ( MA1, MA1 )			/*    pa1    |    pa1    |           |           */	;\
    233 TWO(PUNPCKHWD  ( MA2, MA2 ))			/*    pa2    |    pa2    |           |           */	;\
    234     PUNPCKHDQ  ( MA1, MA1 )                     /*    pa1    |    pa1    |    pa1    |    pa1    */	;\
    235 TWO(PUNPCKHDQ  ( MA2, MA2 ))                    /*    pa2    |    pa2    |    pa2    |    pa2    */
    236 
    237 #define GMB_PACK( MS1, MS2 ) \
    238     PACKUSWB   ( MS2, MS1 )			/* sa2 | sb2 | sg2 | sr2 | sa1 | sb1 | sg1 | sr1 */	;\
    239 
    240 #define GMB_STORE(rgba, MSS ) \
    241 ONE(MOVD       ( MSS, REGIND(rgba) ))		/*     |     |     |     | sa1 | sb1 | sg1 | sr1 */	;\
    242 TWO(MOVQ       ( MSS, REGIND(rgba) ))		/* sa2 | sb2 | sg2 | sr2 | sa1 | sb1 | sg1 | sr1 */
    243 
    244 /* Kevin F. Quinn <kevquinn (at) gentoo.org> 2 July 2006
    245  * Replace data segment constants with text-segment
    246  * constants (via pushl/movq)
    247     SEG_DATA
    248 
    249 ALIGNDATA8
    250 const_0080:
    251     D_LONG 0x00800080, 0x00800080
    252 
    253 const_80:
    254     D_LONG 0x80808080, 0x80808080
    255 */
    256 #define const_0080_l 0x00800080
    257 #define const_0080_h 0x00800080
    258 #define const_80_l 0x80808080
    259 #define const_80_h 0x80808080
    260 
    261     SEG_TEXT
    262 
    263 
    264 /* Blend transparency function
    265  */
    266 
    267 #define TAG(x) CONCAT(x,_transparency)
    268 #define LLTAG(x) LLBL2(x,_transparency)
    269 
    270 #define INIT \
    271     PXOR       ( MM0, MM0 )			/*   0x0000  |   0x0000  |   0x0000  |   0x0000  */
    272 
    273 #define MAIN( rgba, dest ) \
    274     GMB_LOAD( rgba, dest, MM1, MM2 )									;\
    275     GMB_UNPACK( MM1, MM2, MM4, MM5, MM0 )								;\
    276     GMB_ALPHA( MM1, MM3, MM4, MM6 )									;\
    277     GMB_LERP_GSC( MM1, MM2, MM3, MM4, MM5, MM6 )							;\
    278     GMB_PACK( MM3, MM6 )										;\
    279     GMB_STORE( rgba, MM3 )
    280 
    281 #include "mmx_blendtmp.h"
    282 
    283 
    284 /* Blend add function
    285  *
    286  * FIXME: Add some loop unrolling here...
    287  */
    288 
    289 #define TAG(x) CONCAT(x,_add)
    290 #define LLTAG(x) LLBL2(x,_add)
    291 
    292 #define INIT
    293 
    294 #define MAIN( rgba, dest ) \
    295 ONE(MOVD       ( REGIND(rgba), MM1 ))		/*     |     |     |     | qa1 | qb1 | qg1 | qr1 */	;\
    296 ONE(MOVD       ( REGIND(dest), MM2 ))		/*     |     |     |     | pa1 | pb1 | pg1 | pr1 */	;\
    297 ONE(PADDUSB    ( MM2, MM1 ))										;\
    298 ONE(MOVD       ( MM1, REGIND(rgba) ))		/*     |     |     |     | sa1 | sb1 | sg1 | sr1 */	;\
    299 													;\
    300 TWO(MOVQ       ( REGIND(rgba), MM1 ))		/* qa2 | qb2 | qg2 | qr2 | qa1 | qb1 | qg1 | qr1 */	;\
    301 TWO(PADDUSB    ( REGIND(dest), MM1 ))		/* sa2 | sb2 | sg2 | sr2 | sa1 | sb1 | sg1 | sr1 */	;\
    302 TWO(MOVQ       ( MM1, REGIND(rgba) ))
    303 
    304 #include "mmx_blendtmp.h"
    305 
    306 
    307 /* Blend min function
    308  */
    309 
    310 #define TAG(x) CONCAT(x,_min)
    311 #define LLTAG(x) LLBL2(x,_min)
    312 
    313 /* Kevin F. Quinn 2nd July 2006
    314  * Replace data segment constants with text-segment instructions
    315 #define INIT \
    316     MOVQ       ( CONTENT(const_80), MM7 )
    317  */
    318 #define INIT \
    319     PUSH_L     ( CONST(const_80_h) ) 		/* 0x80| 0x80| 0x80| 0x80| 0x80| 0x80| 0x80| 0x80*/	;\
    320     PUSH_L     ( CONST(const_80_l) ) 									;\
    321     MOVQ       ( REGIND(ESP), MM7 ) 									;\
    322     ADD_L      ( CONST(8), ESP)
    323 
    324 #define MAIN( rgba, dest ) \
    325     GMB_LOAD( rgba, dest, MM1, MM2 )									;\
    326     MOVQ       ( MM1, MM3 )										;\
    327     MOVQ       ( MM2, MM4 )										;\
    328     PXOR       ( MM7, MM3 )			/*              unsigned -> signed               */	;\
    329     PXOR       ( MM7, MM4 )			/*              unsigned -> signed               */	;\
    330     PCMPGTB    ( MM3, MM4 )			/*                 q > p ? 0xff : 0x00           */	;\
    331     PAND       ( MM4, MM1 )			/*                 q > p ? p : 0                 */	;\
    332     PANDN      ( MM2, MM4 )			/*                 q > p ? 0 : q                 */	;\
    333     POR        ( MM1, MM4 )			/*                 q > p ? p : q                 */	;\
    334     GMB_STORE( rgba, MM4 )
    335 
    336 #include "mmx_blendtmp.h"
    337 
    338 
    339 /* Blend max function
    340  */
    341 
    342 #define TAG(x) CONCAT(x,_max)
    343 #define LLTAG(x) LLBL2(x,_max)
    344 
    345 /* Kevin F. Quinn 2nd July 2006
    346  * Replace data segment constants with text-segment instructions
    347 #define INIT \
    348     MOVQ       ( CONTENT(const_80), MM7 )
    349  */
    350 #define INIT \
    351     PUSH_L     ( CONST(const_80_l) ) 		/* 0x80| 0x80| 0x80| 0x80| 0x80| 0x80| 0x80| 0x80*/	;\
    352     PUSH_L     ( CONST(const_80_h) ) 									;\
    353     MOVQ       ( REGIND(ESP), MM7 ) 									;\
    354     ADD_L      ( CONST(8), ESP)
    355 
    356 #define MAIN( rgba, dest ) \
    357     GMB_LOAD( rgba, dest, MM1, MM2 )									;\
    358     MOVQ       ( MM1, MM3 )										;\
    359     MOVQ       ( MM2, MM4 )										;\
    360     PXOR       ( MM7, MM3 )			/*              unsigned -> signed               */	;\
    361     PXOR       ( MM7, MM4 )			/*              unsigned -> signed               */	;\
    362     PCMPGTB    ( MM3, MM4 )			/*                 q > p ? 0xff : 0x00           */	;\
    363     PAND       ( MM4, MM2 )			/*                 q > p ? q : 0                 */	;\
    364     PANDN      ( MM1, MM4 )			/*                 q > p ? 0 : p                 */	;\
    365     POR        ( MM2, MM4 )			/*                 q > p ? p : q                 */	;\
    366     GMB_STORE( rgba, MM4 )
    367 
    368 #include "mmx_blendtmp.h"
    369 
    370 
    371 /* Blend modulate function
    372  */
    373 
    374 #define TAG(x) CONCAT(x,_modulate)
    375 #define LLTAG(x) LLBL2(x,_modulate)
    376 
    377 /* Kevin F. Quinn 2nd July 2006
    378  * Replace data segment constants with text-segment instructions
    379 #define INIT \
    380     MOVQ       ( CONTENT(const_0080), MM7 )
    381  */
    382 #define INIT \
    383     PXOR       ( MM0, MM0 )			/*   0x0000  |   0x0000  |   0x0000  |   0x0000  */	;\
    384     PUSH_L     ( CONST(const_0080_l) ) 	/*   0x0080  |   0x0080  |   0x0080  |   0x0080  */	;\
    385     PUSH_L     ( CONST(const_0080_h) ) 								;\
    386     MOVQ       ( REGIND(ESP), MM7 ) 									;\
    387     ADD_L      ( CONST(8), ESP)
    388 
    389 #define MAIN( rgba, dest ) \
    390     GMB_LOAD( rgba, dest, MM1, MM2 )									;\
    391     GMB_UNPACK( MM1, MM2, MM4, MM5, MM0 )								;\
    392     GMB_MULT_GSR( MM1, MM2, MM4, MM5, MM7 )								;\
    393     GMB_PACK( MM2, MM5 )										;\
    394     GMB_STORE( rgba, MM2 )
    395 
    396 #include "mmx_blendtmp.h"
    397 
    398 #endif
    399 
    400 #if defined (__ELF__) && defined (__linux__)
    401 	.section .note.GNU-stack,"",%progbits
    402 #endif
    403