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

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