[svn] / trunk / xvidcore / src / quant / x86_asm / quantize_mpeg_mmx.asm Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/src/quant/x86_asm/quantize_mpeg_mmx.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1793 - (view) (download)

1 : edgomez 1382 ;/**************************************************************************
2 :     ; *
3 :     ; * XVID MPEG-4 VIDEO CODEC
4 :     ; * - 3dne Quantization/Dequantization -
5 :     ; *
6 :     ; * Copyright (C) 2002-2003 Peter Ross <pross@xvid.org>
7 :     ; * 2002-2003 Michael Militzer <isibaar@xvid.org>
8 :     ; * 2002-2003 Pascal Massimino <skal@planet-d.net>
9 :     ; *
10 :     ; * This program is free software ; you can redistribute it and/or modify
11 :     ; * it under the terms of the GNU General Public License as published by
12 :     ; * the Free Software Foundation ; either version 2 of the License, or
13 :     ; * (at your option) any later version.
14 :     ; *
15 :     ; * This program is distributed in the hope that it will be useful,
16 :     ; * but WITHOUT ANY WARRANTY ; without even the implied warranty of
17 :     ; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 :     ; * GNU General Public License for more details.
19 :     ; *
20 :     ; * You should have received a copy of the GNU General Public License
21 :     ; * along with this program ; if not, write to the Free Software
22 :     ; * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 :     ; *
24 : Isibaar 1793 ; * $Id: quantize_mpeg_mmx.asm,v 1.10 2008-11-11 20:46:24 Isibaar Exp $
25 : edgomez 1382 ; *
26 :     ; *************************************************************************/
27 :    
28 :     %define SATURATE
29 :    
30 :     BITS 32
31 :    
32 :     %macro cglobal 1
33 :     %ifdef PREFIX
34 : edgomez 1535 %ifdef MARK_FUNCS
35 : edgomez 1540 global _%1:function %1.endfunc-%1
36 :     %define %1 _%1:function %1.endfunc-%1
37 : Isibaar 1793 %define ENDFUNC .endfunc
38 : edgomez 1535 %else
39 :     global _%1
40 :     %define %1 _%1
41 : Isibaar 1793 %define ENDFUNC
42 : edgomez 1535 %endif
43 : edgomez 1382 %else
44 : edgomez 1535 %ifdef MARK_FUNCS
45 : edgomez 1540 global %1:function %1.endfunc-%1
46 : Isibaar 1793 %define ENDFUNC .endfunc
47 : edgomez 1535 %else
48 :     global %1
49 : Isibaar 1793 %define ENDFUNC
50 : edgomez 1535 %endif
51 : edgomez 1382 %endif
52 :     %endmacro
53 :    
54 :     %macro cextern 1
55 :     %ifdef PREFIX
56 :     extern _%1
57 :     %define %1 _%1
58 :     %else
59 :     extern %1
60 :     %endif
61 :     %endmacro
62 :    
63 :     ;=============================================================================
64 :     ; Local data (Read Only)
65 :     ;=============================================================================
66 :    
67 :     %ifdef FORMAT_COFF
68 : edgomez 1519 SECTION .rodata
69 : edgomez 1382 %else
70 : edgomez 1519 SECTION .rodata align=16
71 : edgomez 1382 %endif
72 :    
73 :     mmx_one:
74 :     times 4 dw 1
75 :    
76 :     ;-----------------------------------------------------------------------------
77 :     ; divide by 2Q table
78 :     ;-----------------------------------------------------------------------------
79 :    
80 :     ALIGN 16
81 :     mmx_div:
82 :     times 4 dw 65535 ; the div by 2 formula will overflow for the case
83 :     ; quant=1 but we don't care much because quant=1
84 :     ; is handled by a different piece of code that
85 :     ; doesn't use this table.
86 :     %assign quant 2
87 :     %rep 30
88 :     times 4 dw (1<<17) / (quant*2) + 1
89 :     %assign quant quant+1
90 :     %endrep
91 :    
92 :     %define VM18P 3
93 :     %define VM18Q 4
94 :    
95 :    
96 :     ;-----------------------------------------------------------------------------
97 :     ; quantd table
98 :     ;-----------------------------------------------------------------------------
99 :    
100 :     quantd:
101 :     %assign quant 1
102 :     %rep 31
103 :     times 4 dw ((VM18P*quant) + (VM18Q/2)) / VM18Q
104 :     %assign quant quant+1
105 :     %endrep
106 :    
107 :     ;-----------------------------------------------------------------------------
108 :     ; multiple by 2Q table
109 :     ;-----------------------------------------------------------------------------
110 :    
111 :     mmx_mul_quant:
112 :     %assign quant 1
113 :     %rep 31
114 :     times 4 dw quant
115 :     %assign quant quant+1
116 :     %endrep
117 :    
118 :     ;-----------------------------------------------------------------------------
119 :     ; saturation limits
120 :     ;-----------------------------------------------------------------------------
121 :    
122 :     ALIGN 16
123 :    
124 :     mmx_32767_minus_2047:
125 :     times 4 dw (32767-2047)
126 :     mmx_32768_minus_2048:
127 :     times 4 dw (32768-2048)
128 :     mmx_2047:
129 :     times 4 dw 2047
130 :     mmx_minus_2048:
131 :     times 4 dw (-2048)
132 :     zero:
133 :     times 4 dw 0
134 :    
135 :     ;=============================================================================
136 : syskin 1713 ; rounding
137 :     ;=============================================================================
138 :    
139 :     mmx_rounding:
140 :     dw (1<<13)
141 :     dw 0
142 :     dw (1<<13)
143 :     dw 0
144 :    
145 :     ;=============================================================================
146 : edgomez 1382 ; Code
147 :     ;=============================================================================
148 :    
149 :     SECTION .text
150 :    
151 :     cglobal quant_mpeg_intra_mmx
152 :     cglobal quant_mpeg_inter_mmx
153 :     cglobal dequant_mpeg_intra_mmx
154 :     cglobal dequant_mpeg_inter_mmx
155 :    
156 : syskin 1713
157 :     %macro QUANT_MMX 1
158 :     movq mm0, [eax + 16*(%1)] ; data
159 :     movq mm2, [ecx + 16*(%1) + 128] ; intra_matrix_rec
160 :     movq mm4, [eax + 16*(%1) + 8] ; data
161 :     movq mm6, [ecx + 16*(%1) + 128 + 8] ; intra_matrix_rec
162 :    
163 :     movq mm1, mm0
164 :     movq mm5, mm4
165 :    
166 :     pmullw mm0, mm2 ; low results
167 :     pmulhw mm1, mm2 ; high results
168 :     pmullw mm4, mm6 ; low results
169 :     pmulhw mm5, mm6 ; high results
170 :    
171 :     movq mm2, mm0
172 :     movq mm6, mm4
173 :    
174 :     punpckhwd mm0, mm1
175 :     punpcklwd mm2, mm1
176 :     punpckhwd mm4, mm5
177 :     punpcklwd mm6, mm5
178 :    
179 :     paddd mm2, mm7
180 :     paddd mm0, mm7
181 :     paddd mm6, mm7
182 :     paddd mm4, mm7
183 :    
184 :     psrad mm2, 14
185 :     psrad mm0, 14
186 :     psrad mm6, 14
187 :     psrad mm4, 14
188 :    
189 :     packssdw mm2, mm0
190 :     packssdw mm6, mm4
191 :    
192 :     movq [edi + 16*(%1)], mm2
193 :     movq [edi + 16*(%1)+8], mm6
194 :     %endmacro
195 :    
196 : edgomez 1382 ;-----------------------------------------------------------------------------
197 :     ;
198 :     ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff,
199 :     ; const int16_t const * data,
200 :     ; const uint32_t quant,
201 :     ; const uint32_t dcscalar,
202 :     ; const uint16_t *mpeg_matrices);
203 :     ;
204 :     ;-----------------------------------------------------------------------------
205 :    
206 :     ALIGN 16
207 :     quant_mpeg_intra_mmx:
208 :    
209 :     push edi
210 : syskin 1713 movq mm7, [mmx_rounding]
211 : edgomez 1382
212 : syskin 1713 mov eax, [esp + 4 + 8] ; data
213 :     mov ecx, [esp + 4 + 20] ; mpeg_quant_matrices
214 :     mov edi, [esp + 4 + 4] ; coeff
215 : edgomez 1382
216 : syskin 1713 QUANT_MMX(0)
217 :     QUANT_MMX(1)
218 :     QUANT_MMX(2)
219 :     QUANT_MMX(3)
220 :     QUANT_MMX(4)
221 :     QUANT_MMX(5)
222 :     QUANT_MMX(6)
223 :     QUANT_MMX(7)
224 : edgomez 1382
225 : syskin 1713 ; calculate DC
226 :     movsx eax, word [eax] ; data[0]
227 :     mov ecx, [esp + 4 + 16] ; dcscalar
228 : syskin 1728 mov edx, eax
229 :     mov edi, ecx
230 :     shr ecx, 1 ; ecx = dcscalar/2
231 :     sar edx, 31 ; edx = sign extend of eax (ready for division too)
232 :     xor ecx, edx ; adjust ecx according to the sign of data[0]
233 :     sub ecx, edx
234 :     add eax, ecx
235 : syskin 1713
236 : syskin 1728 mov ecx, [esp + 4 + 4] ; coeff again
237 :     idiv edi ; eax = edx:eax / dcscalar
238 :     mov [ecx], ax ; coeff[0] = ax
239 :    
240 : edgomez 1382 pop edi
241 :    
242 :     xor eax, eax ; return(0);
243 :     ret
244 : Isibaar 1793 ENDFUNC
245 : edgomez 1382
246 :    
247 :     ;-----------------------------------------------------------------------------
248 :     ;
249 :     ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
250 :     ; const int16_t const * data,
251 :     ; const uint32_t quant,
252 :     ; const uint16_t *mpeg_matrices);
253 :     ;
254 :     ;-----------------------------------------------------------------------------
255 :    
256 :     ALIGN 16
257 :     quant_mpeg_inter_mmx:
258 :    
259 :     push ecx
260 :     push esi
261 :     push edi
262 :     push ebx
263 :    
264 :     mov edi, [esp + 16 + 4] ; coeff
265 :     mov esi, [esp + 16 + 8] ; data
266 :     mov eax, [esp + 16 + 12] ; quant
267 :     mov ebx, [esp + 16 + 16] ; mpeg_quant_matrices
268 :    
269 :     xor ecx, ecx
270 :    
271 :     pxor mm5, mm5 ; sum
272 :    
273 :     cmp al, 1
274 :     jz near .q1loop
275 :    
276 :     cmp al, 2
277 :     jz near .q2loop
278 :    
279 :     movq mm7, [mmx_div + eax * 8 - 8] ; divider
280 :    
281 :     ALIGN 16
282 : Isibaar 1793 .loop:
283 : edgomez 1382 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
284 :     movq mm3, [esi + 8*ecx + 8] ;
285 :     pxor mm1, mm1 ; mm1 = 0
286 :     pxor mm4, mm4 ;
287 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
288 :     pcmpgtw mm4, mm3 ;
289 :     pxor mm0, mm1 ; mm0 = |mm0|
290 :     pxor mm3, mm4 ;
291 :     psubw mm0, mm1 ; displace
292 :     psubw mm3, mm4 ;
293 :     psllw mm0, 4
294 :     psllw mm3, 4
295 :     movq mm2, [ebx + 512 + 8*ecx]
296 :     psrlw mm2, 1
297 :     paddw mm0, mm2
298 :     movq mm2, [ebx + 768 + ecx*8]
299 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
300 :     movq mm2, [ebx + 512 + 8*ecx + 8]
301 :     psrlw mm2, 1
302 :     paddw mm3, mm2
303 :     movq mm2, [ebx + 768 + ecx*8 + 8]
304 :     pmulhw mm3, mm2
305 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
306 :     pmulhw mm3, mm7 ;
307 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
308 :     psrlw mm3, 1
309 :     paddw mm5, mm0 ; sum += mm0
310 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
311 :     paddw mm5, mm3 ;
312 :     pxor mm3, mm4 ;
313 :     psubw mm0, mm1 ; undisplace
314 :     psubw mm3, mm4
315 :     movq [edi + 8*ecx], mm0
316 :     movq [edi + 8*ecx + 8], mm3
317 :    
318 :     add ecx, 2
319 :     cmp ecx, 16
320 :     jnz near .loop
321 :    
322 : Isibaar 1793 .done:
323 : edgomez 1382 pmaddwd mm5, [mmx_one]
324 :     movq mm0, mm5
325 :     psrlq mm5, 32
326 :     paddd mm0, mm5
327 :     movd eax, mm0 ; return sum
328 :    
329 :     pop ebx
330 :     pop edi
331 :     pop esi
332 :     pop ecx
333 :    
334 :     ret
335 :    
336 :     ALIGN 16
337 : Isibaar 1793 .q1loop:
338 : edgomez 1382 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
339 :     movq mm3, [esi + 8*ecx+ 8]
340 :     pxor mm1, mm1 ; mm1 = 0
341 :     pxor mm4, mm4 ;
342 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
343 :     pcmpgtw mm4, mm3 ;
344 :     pxor mm0, mm1 ; mm0 = |mm0|
345 :     pxor mm3, mm4 ;
346 :     psubw mm0, mm1 ; displace
347 :     psubw mm3, mm4 ;
348 :     psllw mm0, 4
349 :     psllw mm3, 4
350 :     movq mm2, [ebx + 512 + 8*ecx]
351 :     psrlw mm2, 1
352 :     paddw mm0, mm2
353 :     movq mm2, [ebx + 768 + ecx*8]
354 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
355 :     movq mm2, [ebx + 512 + 8*ecx + 8]
356 :     psrlw mm2, 1
357 :     paddw mm3, mm2
358 :     movq mm2, [ebx + 768 + ecx*8 + 8]
359 :     pmulhw mm3, mm2
360 :     psrlw mm0, 1 ; mm0 >>= 1 (/2)
361 :     psrlw mm3, 1 ;
362 :     paddw mm5, mm0 ; sum += mm0
363 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
364 :     paddw mm5, mm3 ;
365 :     pxor mm3, mm4 ;
366 :     psubw mm0, mm1 ; undisplace
367 :     psubw mm3, mm4
368 :     movq [edi + 8*ecx], mm0
369 :     movq [edi + 8*ecx + 8], mm3
370 :    
371 :     add ecx, 2
372 :     cmp ecx, 16
373 :     jnz near .q1loop
374 :    
375 :     jmp .done
376 :    
377 :     ALIGN 16
378 : Isibaar 1793 .q2loop:
379 : edgomez 1382 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
380 :     movq mm3, [esi + 8*ecx+ 8]
381 :     pxor mm1, mm1 ; mm1 = 0
382 :     pxor mm4, mm4 ;
383 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
384 :     pcmpgtw mm4, mm3 ;
385 :     pxor mm0, mm1 ; mm0 = |mm0|
386 :     pxor mm3, mm4 ;
387 :     psubw mm0, mm1 ; displace
388 :     psubw mm3, mm4 ;
389 :     psllw mm0, 4
390 :     psllw mm3, 4
391 :     movq mm2, [ebx + 512 + 8*ecx]
392 :     psrlw mm2, 1
393 :     paddw mm0, mm2
394 :     movq mm2, [ebx + 768 + ecx*8]
395 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
396 :     movq mm2, [ebx + 512 + 8*ecx + 8]
397 :     psrlw mm2, 1
398 :     paddw mm3, mm2
399 :     movq mm2, [ebx + 768 + ecx*8 + 8]
400 :     pmulhw mm3, mm2
401 :     psrlw mm0, 2 ; mm0 >>= 1 (/2)
402 :     psrlw mm3, 2 ;
403 :     paddw mm5, mm0 ; sum += mm0
404 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
405 :     paddw mm5, mm3 ;
406 :     pxor mm3, mm4 ;
407 :     psubw mm0, mm1 ; undisplace
408 :     psubw mm3, mm4
409 :     movq [edi + 8*ecx], mm0
410 :     movq [edi + 8*ecx + 8], mm3
411 :    
412 :     add ecx, 2
413 :     cmp ecx, 16
414 :     jnz near .q2loop
415 :    
416 :     jmp .done
417 : Isibaar 1793 ENDFUNC
418 : edgomez 1382
419 :    
420 :     ;-----------------------------------------------------------------------------
421 :     ;
422 :     ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
423 :     ; const int16_t const *coeff,
424 :     ; const uint32_t quant,
425 :     ; const uint32_t dcscalar,
426 :     ; const uint16_t *mpeg_matrices);
427 :     ;
428 :     ;-----------------------------------------------------------------------------
429 :    
430 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
431 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
432 :     ; build a saturating mask. It is non-zero only when an overflow occured.
433 :     ; We thus avoid packing/unpacking toward double-word.
434 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
435 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
436 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
437 :     ; and quant in [1..31].
438 :     ;
439 :     ; The original loop is:
440 :     ;
441 :     %if 0
442 :     movq mm0, [ecx+8*eax + 8*16] ; mm0 = coeff[i]
443 :     pxor mm1, mm1
444 :     pcmpgtw mm1, mm0
445 :     pxor mm0, mm1 ; change sign if negative
446 :     psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
447 :    
448 :     movq mm2, mm7 ; mm2 = quant
449 :     pmullw mm2, [ebx + 8*eax + 8*16 ] ; matrix[i]*quant.
450 :    
451 :     movq mm6, mm2
452 :     pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow)
453 :     pmullw mm0, mm6 ; low of coeff*(matrix*quant)
454 :    
455 :     pxor mm5, mm5
456 :     pcmpgtw mm2, mm5 ; otherflow?
457 :     psrlw mm2, 5 ; =0 if no clamp, 2047 otherwise
458 :     psrlw mm0, 5
459 :     paddw mm0, mm1 ; start restoring sign
460 :     por mm0, mm2 ; saturate to 2047 if needed
461 :     pxor mm0, mm1 ; finish negating back
462 :    
463 :     movq [edx + 8*eax + 8*16], mm0 ; data[i]
464 :     add eax, 1
465 :     %endif
466 :    
467 :     ;********************************************************************
468 :    
469 :     ALIGN 16
470 :     dequant_mpeg_intra_mmx:
471 :    
472 :     push ebx
473 :    
474 :     mov edx, [esp + 4 + 4] ; data
475 :     mov ecx, [esp + 4 + 8] ; coeff
476 :     mov eax, [esp + 4 + 12] ; quant
477 :     mov ebx, [esp + 4 + 20] ; mpeg_quant_matrices
478 :    
479 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
480 :     mov eax, -16 ; to keep ALIGNed, we regularly process coeff[0]
481 :     psllw mm7, 2 ; << 2. See comment.
482 :     pxor mm6, mm6 ; this is a NOP
483 :    
484 :     ALIGN 16
485 : Isibaar 1793 .loop:
486 : edgomez 1382 movq mm0, [ecx+8*eax + 8*16] ; mm0 = c = coeff[i]
487 :     movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
488 :     pxor mm1, mm1
489 :     pxor mm4, mm4
490 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c)
491 :     movq mm2, mm7 ; mm2 = quant
492 :    
493 :     pcmpgtw mm4, mm3 ; mm4 = sgn(c')
494 :     pmullw mm2, [ebx + 8*eax + 8*16 ] ; matrix[i]*quant
495 :    
496 :     pxor mm0, mm1 ; negate if negative
497 :     pxor mm3, mm4 ; negate if negative
498 :    
499 :     psubw mm0, mm1
500 :     psubw mm3, mm4
501 :    
502 :     ; we're short on register, here. Poor pairing...
503 :    
504 :     movq mm5, mm2
505 :     pmullw mm2, mm0 ; low of coeff*(matrix*quant)
506 :    
507 :     pmulhw mm0, mm5 ; high of coeff*(matrix*quant)
508 :     movq mm5, mm7 ; mm2 = quant
509 :    
510 :     pmullw mm5, [ebx + 8*eax + 8*16 +8] ; matrix[i+1]*quant
511 :    
512 :     movq mm6, mm5
513 :     add eax,2 ; z-flag will be tested later
514 :    
515 :     pmullw mm6, mm3 ; low of coeff*(matrix*quant)
516 :     pmulhw mm3, mm5 ; high of coeff*(matrix*quant)
517 :    
518 :     pcmpgtw mm0, [zero]
519 :     paddusw mm2, mm0
520 :     psrlw mm2, 5
521 :    
522 :     pcmpgtw mm3, [zero]
523 :     paddusw mm6, mm3
524 :     psrlw mm6, 5
525 :    
526 :     pxor mm2, mm1 ; start negating back
527 :     pxor mm6, mm4 ; start negating back
528 :    
529 :     psubusw mm1, mm0
530 :     psubusw mm4, mm3
531 :    
532 :     psubw mm2, mm1 ; finish negating back
533 :     psubw mm6, mm4 ; finish negating back
534 :    
535 :     movq [edx + 8*eax + 8*16 -2*8 ], mm2 ; data[i]
536 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm6 ; data[i+1]
537 :    
538 :     jnz near .loop
539 :    
540 :     ; deal with DC
541 :     movd mm0, [ecx]
542 :     pmullw mm0, [esp + 4 + 16] ; dcscalar
543 :     movq mm2, [mmx_32767_minus_2047]
544 :     paddsw mm0, mm2
545 :     psubsw mm0, mm2
546 :     movq mm2, [mmx_32768_minus_2048]
547 :     psubsw mm0, mm2
548 :     paddsw mm0, mm2
549 :     movd eax, mm0
550 :     mov [edx], ax
551 :    
552 :     xor eax, eax
553 :    
554 :     pop ebx
555 :    
556 :     ret
557 : Isibaar 1793 ENDFUNC
558 : edgomez 1382
559 :     ;-----------------------------------------------------------------------------
560 :     ;
561 :     ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
562 :     ; const int16_t * const coeff,
563 :     ; const uint32_t quant,
564 :     ; const uint16_t *mpeg_matrices);
565 :     ;
566 :     ;-----------------------------------------------------------------------------
567 :    
568 :     ; Note: We use (2*c + sgn(c) - sgn(-c)) as multiplier
569 :     ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
570 :     ; sgn(x) is the result of 'pcmpgtw 0,x': 0 if x>=0, -1 if x<0.
571 :     ; It's mixed with the extraction of the absolute value.
572 :    
573 :     ALIGN 16
574 :     dequant_mpeg_inter_mmx:
575 :    
576 :     push ebx
577 :    
578 :     mov edx, [esp + 4 + 4] ; data
579 :     mov ecx, [esp + 4 + 8] ; coeff
580 :     mov eax, [esp + 4 + 12] ; quant
581 :     mov ebx, [esp + 4 + 16] ; mpeg_quant_matrices
582 :    
583 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
584 :     mov eax, -16
585 :     paddw mm7, mm7 ; << 1
586 :     pxor mm6, mm6 ; mismatch sum
587 :    
588 :     ALIGN 16
589 : Isibaar 1793 .loop:
590 : edgomez 1382 movq mm0, [ecx+8*eax + 8*16 ] ; mm0 = coeff[i]
591 :     movq mm2, [ecx+8*eax + 8*16 +8] ; mm2 = coeff[i+1]
592 :     add eax, 2
593 :    
594 :     pxor mm1, mm1
595 :     pxor mm3, mm3
596 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
597 :     pcmpgtw mm3, mm2 ; mm3 = sgn(c') (preserved)
598 :     paddsw mm0, mm1 ; c += sgn(c)
599 :     paddsw mm2, mm3 ; c += sgn(c')
600 :     paddw mm0, mm0 ; c *= 2
601 :     paddw mm2, mm2 ; c'*= 2
602 :    
603 :     pxor mm4, mm4
604 :     pxor mm5, mm5
605 :     psubw mm4, mm0 ; -c
606 :     psubw mm5, mm2 ; -c'
607 :     psraw mm4, 16 ; mm4 = sgn(-c)
608 :     psraw mm5, 16 ; mm5 = sgn(-c')
609 :     psubsw mm0, mm4 ; c -= sgn(-c)
610 :     psubsw mm2, mm5 ; c' -= sgn(-c')
611 :     pxor mm0, mm1 ; finish changing sign if needed
612 :     pxor mm2, mm3 ; finish changing sign if needed
613 :    
614 :     ; we're short on register, here. Poor pairing...
615 :    
616 :     movq mm4, mm7 ; (matrix*quant)
617 :     pmullw mm4, [ebx + 512 + 8*eax + 8*16 -2*8]
618 :     movq mm5, mm4
619 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
620 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
621 :    
622 :     movq mm4, mm7 ; (matrix*quant)
623 :     pmullw mm4, [ebx + 512 + 8*eax + 8*16 -2*8 + 8]
624 :    
625 :     pcmpgtw mm5, [zero]
626 :     paddusw mm0, mm5
627 :     psrlw mm0, 5
628 :     pxor mm0, mm1 ; start restoring sign
629 :     psubusw mm1, mm5
630 :    
631 :     movq mm5, mm4
632 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
633 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
634 :     psubw mm0, mm1 ; finish restoring sign
635 :    
636 :     pcmpgtw mm5, [zero]
637 :     paddusw mm2, mm5
638 :     psrlw mm2, 5
639 :     pxor mm2, mm3 ; start restoring sign
640 :     psubusw mm3, mm5
641 :     psubw mm2, mm3 ; finish restoring sign
642 :    
643 :     pxor mm6, mm0 ; mismatch control
644 :     movq [edx + 8*eax + 8*16 -2*8 ], mm0 ; data[i]
645 :     pxor mm6, mm2 ; mismatch control
646 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm2 ; data[i+1]
647 :    
648 :     jnz near .loop
649 :    
650 :     ; mismatch control
651 :    
652 :     movq mm0, mm6
653 :     psrlq mm0, 48
654 :     movq mm1, mm6
655 :     movq mm2, mm6
656 :     psrlq mm1, 32
657 :     pxor mm6, mm0
658 :     psrlq mm2, 16
659 :     pxor mm6, mm1
660 :     pxor mm6, mm2
661 :     movd eax, mm6
662 :     and eax, 1
663 :     xor eax, 1
664 :     xor word [edx + 2*63], ax
665 :    
666 :     xor eax, eax
667 :    
668 :     pop ebx
669 :    
670 :     ret
671 : Isibaar 1793 ENDFUNC
672 : edgomez 1540
673 : Isibaar 1790
674 :     %ifidn __OUTPUT_FORMAT__,elf
675 :     section ".note.GNU-stack" noalloc noexec nowrite progbits
676 :     %endif
677 :    

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4