Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / x86 / mmx_blend.S
1         ;
2 /*
3  * Written by Jos� Fonseca <j_r_fonseca@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@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