[svn] / branches / dev-api-4 / xvidcore / src / quant / x86_asm / quantize_mpeg_mmx.asm Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/src/quant/x86_asm/quantize_mpeg_mmx.asm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1176 - (view) (download)

1 : edgomez 1176 ;/**************************************************************************
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 :     ; * $Id: quantize_mpeg_mmx.asm,v 1.1.2.2 2003-10-09 18:50:22 edgomez Exp $
25 :     ; *
26 :     ; *************************************************************************/
27 : edgomez 1174
28 :     ; data/text alignment
29 :     %define ALIGN 8
30 :    
31 :     %define SATURATE
32 :    
33 :     bits 32
34 :    
35 :     %macro cglobal 1
36 :     %ifdef PREFIX
37 :     global _%1
38 :     %define %1 _%1
39 :     %else
40 :     global %1
41 :     %endif
42 :     %endmacro
43 :    
44 :     %macro cextern 1
45 :     %ifdef PREFIX
46 :     extern _%1
47 :     %define %1 _%1
48 :     %else
49 :     extern %1
50 :     %endif
51 :     %endmacro
52 :    
53 : edgomez 1176 ;***************************************************************************
54 :     ; Local data
55 :     ;***************************************************************************
56 : edgomez 1174
57 : edgomez 1176 %ifdef FORMAT_COFF
58 :     SECTION .data data
59 :     %else
60 :     SECTION .data data align=8
61 :     %endif
62 :    
63 :     mmx_one:
64 :     times 4 dw 1
65 :    
66 : edgomez 1174 ;===========================================================================
67 :     ;
68 :     ; divide by 2Q table
69 :     ;
70 :     ;===========================================================================
71 :    
72 : edgomez 1176 align 16
73 :     mmx_div:
74 :     %assign quant 1
75 :     %rep 31
76 :     times 4 dw (1<<17) / (quant*2) + 1
77 :     %assign quant quant+1
78 :     %endrep
79 : edgomez 1174
80 :     ;===========================================================================
81 :     ;
82 :     ; intra matrix
83 :     ;
84 :     ;===========================================================================
85 :    
86 :     cextern intra_matrix
87 :     cextern intra_matrix_fix
88 :    
89 :     ;===========================================================================
90 :     ;
91 :     ; inter matrix
92 :     ;
93 :     ;===========================================================================
94 :    
95 :     cextern inter_matrix
96 :     cextern inter_matrix_fix
97 :    
98 :    
99 :     %define VM18P 3
100 :     %define VM18Q 4
101 :    
102 :    
103 :     ;===========================================================================
104 :     ;
105 :     ; quantd table
106 :     ;
107 :     ;===========================================================================
108 :    
109 : edgomez 1176 quantd:
110 :     %assign quant 1
111 :     %rep 31
112 :     times 4 dw ((VM18P*quant) + (VM18Q/2)) / VM18Q
113 :     %assign quant quant+1
114 :     %endrep
115 : edgomez 1174
116 :     ;===========================================================================
117 :     ;
118 :     ; multiple by 2Q table
119 :     ;
120 :     ;===========================================================================
121 :    
122 : edgomez 1176 mmx_mul_quant:
123 :     %assign quant 1
124 :     %rep 31
125 :     times 4 dw quant
126 :     %assign quant quant+1
127 :     %endrep
128 : edgomez 1174
129 :     ;===========================================================================
130 :     ;
131 :     ; saturation limits
132 :     ;
133 :     ;===========================================================================
134 :    
135 :     align 16
136 :    
137 : edgomez 1176 mmx_32767_minus_2047:
138 :     times 4 dw (32767-2047)
139 :     mmx_32768_minus_2048:
140 :     times 4 dw (32768-2048)
141 :     mmx_2047:
142 :     times 4 dw 2047
143 :     mmx_minus_2048:
144 :     times 4 dw (-2048)
145 :     zero:
146 :     times 4 dw 0
147 : edgomez 1174
148 : edgomez 1176 ;***************************************************************************
149 :     ; Local data
150 :     ;***************************************************************************
151 :    
152 : edgomez 1174 section .text
153 :    
154 :     ;===========================================================================
155 :     ;
156 : edgomez 1176 ; uint32_t quant_mpeg_intra_mmx(int16_t * coeff,
157 :     ; const int16_t const * data,
158 :     ; const uint32_t quant,
159 :     ; const uint32_t dcscalar);
160 : edgomez 1174 ;
161 :     ;===========================================================================
162 :    
163 :     align ALIGN
164 :     cglobal quant_mpeg_intra_mmx
165 :     quant_mpeg_intra_mmx:
166 :    
167 : edgomez 1176 push ecx
168 :     push esi
169 :     push edi
170 : edgomez 1174
171 : edgomez 1176 mov edi, [esp + 12 + 4] ; coeff
172 :     mov esi, [esp + 12 + 8] ; data
173 :     mov eax, [esp + 12 + 12] ; quant
174 : edgomez 1174
175 : edgomez 1176 movq mm5, [quantd + eax * 8 - 8] ; quantd -> mm5
176 : edgomez 1174
177 : edgomez 1176 xor ecx, ecx
178 :     cmp al, 1
179 :     jz near .q1loop
180 : edgomez 1174
181 : edgomez 1176 cmp al, 2
182 :     jz near .q2loop
183 : edgomez 1174
184 : edgomez 1176 movq mm7, [mmx_div + eax * 8 - 8] ; multipliers[quant] -> mm7
185 : edgomez 1174
186 :     align ALIGN
187 :     .loop
188 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
189 :     movq mm3, [esi + 8*ecx + 8] ;
190 : edgomez 1174
191 : edgomez 1176 pxor mm1, mm1 ; mm1 = 0
192 :     pxor mm4, mm4
193 : edgomez 1174
194 : edgomez 1176 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
195 :     pcmpgtw mm4, mm3
196 : edgomez 1174
197 : edgomez 1176 pxor mm0, mm1 ; mm0 = |mm0|
198 :     pxor mm3, mm4 ;
199 :     psubw mm0, mm1 ; displace
200 :     psubw mm3, mm4 ;
201 : edgomez 1174
202 : edgomez 1176 psllw mm0, 4 ; level << 4
203 :     psllw mm3, 4 ;
204 : edgomez 1174
205 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx]
206 :     psrlw mm2, 1 ; intra_matrix[i]>>1
207 :     paddw mm0, mm2
208 : edgomez 1174
209 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8]
210 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
211 : edgomez 1174
212 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx + 8]
213 :     psrlw mm2, 1
214 :     paddw mm3, mm2
215 : edgomez 1174
216 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8 + 8]
217 :     pmulhw mm3, mm2
218 : edgomez 1174
219 : edgomez 1176 paddw mm0, mm5 ; + quantd
220 :     paddw mm3, mm5
221 :     pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
222 :     pmulhw mm3, mm7 ;
223 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
224 :     psrlw mm3, 1
225 : edgomez 1174
226 : edgomez 1176 pxor mm0, mm1 ; mm0 *= sign(mm0)
227 :     pxor mm3, mm4 ;
228 :     psubw mm0, mm1 ; undisplace
229 :     psubw mm3, mm4 ;
230 : edgomez 1174
231 : edgomez 1176 movq [edi + 8*ecx], mm0
232 :     movq [edi + 8*ecx + 8], mm3
233 : edgomez 1174
234 : edgomez 1176 add ecx,2
235 :     cmp ecx,16
236 :     jnz near .loop
237 : edgomez 1174
238 :     .done
239 :     ; caclulate data[0] // (int32_t)dcscalar)
240 :    
241 : edgomez 1176 mov ecx, [esp + 12 + 16] ; dcscalar
242 :     mov edx, ecx
243 :     movsx eax, word [esi] ; data[0]
244 :     shr edx, 1 ; edx = dcscalar /2
245 :     cmp eax, 0
246 :     jg .gtzero
247 : edgomez 1174
248 : edgomez 1176 sub eax, edx
249 :     jmp short .mul
250 : edgomez 1174 .gtzero
251 : edgomez 1176 add eax, edx
252 : edgomez 1174 .mul
253 : edgomez 1176 cdq ; expand eax -> edx:eax
254 :     idiv ecx ; eax = edx:eax / dcscalar
255 : edgomez 1174
256 : edgomez 1176 mov [edi], ax ; coeff[0] = ax
257 : edgomez 1174
258 : edgomez 1176 pop edi
259 :     pop esi
260 :     pop ecx
261 : edgomez 1174
262 : edgomez 1176 xor eax, eax ; return(0);
263 :     ret
264 : edgomez 1174
265 :     align ALIGN
266 :     .q1loop
267 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
268 :     movq mm3, [esi + 8*ecx + 8] ;
269 : edgomez 1174
270 : edgomez 1176 pxor mm1, mm1 ; mm1 = 0
271 :     pxor mm4, mm4 ;
272 : edgomez 1174
273 : edgomez 1176 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
274 :     pcmpgtw mm4, mm3 ;
275 : edgomez 1174
276 : edgomez 1176 pxor mm0, mm1 ; mm0 = |mm0|
277 :     pxor mm3, mm4 ;
278 :     psubw mm0, mm1 ; displace
279 :     psubw mm3, mm4 ;
280 : edgomez 1174
281 : edgomez 1176 psllw mm0, 4
282 :     psllw mm3, 4
283 : edgomez 1174
284 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx]
285 :     psrlw mm2, 1
286 :     paddw mm0, mm2
287 : edgomez 1174
288 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8]
289 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
290 : edgomez 1174
291 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx + 8]
292 :     psrlw mm2, 1
293 :     paddw mm3, mm2
294 : edgomez 1174
295 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8 + 8]
296 :     pmulhw mm3, mm2
297 : edgomez 1174
298 : edgomez 1176 paddw mm0, mm5
299 :     paddw mm3, mm5
300 : edgomez 1174
301 : edgomez 1176 psrlw mm0, 1 ; mm0 >>= 1 (/2)
302 :     psrlw mm3, 1 ;
303 : edgomez 1174
304 : edgomez 1176 pxor mm0, mm1 ; mm0 *= sign(mm0)
305 :     pxor mm3, mm4 ;
306 :     psubw mm0, mm1 ; undisplace
307 :     psubw mm3, mm4 ;
308 : edgomez 1174
309 : edgomez 1176 movq [edi + 8*ecx], mm0
310 :     movq [edi + 8*ecx + 8], mm3
311 : edgomez 1174
312 : edgomez 1176 add ecx, 2
313 :     cmp ecx, 16
314 :     jnz near .q1loop
315 :     jmp near .done
316 : edgomez 1174
317 :    
318 :     align ALIGN
319 :     .q2loop
320 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
321 :     movq mm3, [esi + 8*ecx + 8] ;
322 : edgomez 1174
323 : edgomez 1176 pxor mm1, mm1 ; mm1 = 0
324 :     pxor mm4, mm4 ;
325 : edgomez 1174
326 : edgomez 1176 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
327 :     pcmpgtw mm4, mm3 ;
328 : edgomez 1174
329 : edgomez 1176 pxor mm0, mm1 ; mm0 = |mm0|
330 :     pxor mm3, mm4 ;
331 :     psubw mm0, mm1 ; displace
332 :     psubw mm3, mm4 ;
333 : edgomez 1174
334 : edgomez 1176 psllw mm0, 4
335 :     psllw mm3, 4
336 : edgomez 1174
337 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx]
338 :     psrlw mm2, 1
339 :     paddw mm0, mm2
340 : edgomez 1174
341 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8]
342 :     pmulhw mm0, mm2 ; (level<<4 + intra_matrix[i]>>1) / intra_matrix[i]
343 : edgomez 1174
344 : edgomez 1176 movq mm2, [intra_matrix + 8*ecx + 8]
345 :     psrlw mm2, 1
346 :     paddw mm3, mm2
347 : edgomez 1174
348 : edgomez 1176 movq mm2, [intra_matrix_fix + ecx*8 + 8]
349 :     pmulhw mm3, mm2
350 : edgomez 1174
351 : edgomez 1176 paddw mm0, mm5
352 :     paddw mm3, mm5
353 : edgomez 1174
354 : edgomez 1176 psrlw mm0, 2 ; mm0 >>= 1 (/4)
355 :     psrlw mm3, 2 ;
356 : edgomez 1174
357 : edgomez 1176 pxor mm0, mm1 ; mm0 *= sign(mm0)
358 :     pxor mm3, mm4 ;
359 :     psubw mm0, mm1 ; undisplace
360 :     psubw mm3, mm4 ;
361 : edgomez 1174
362 : edgomez 1176 movq [edi + 8*ecx], mm0
363 :     movq [edi + 8*ecx + 8], mm3
364 : edgomez 1174
365 : edgomez 1176 add ecx,2
366 :     cmp ecx,16
367 :     jnz near .q2loop
368 :     jmp near .done
369 : edgomez 1174
370 :    
371 :     ;===========================================================================
372 :     ;
373 : edgomez 1176 ; uint32_t quant_mpeg_inter_mmx(int16_t * coeff,
374 :     ; const int16_t const * data,
375 :     ; const uint32_t quant);
376 : edgomez 1174 ;
377 :     ;===========================================================================
378 :    
379 :     align ALIGN
380 :     cglobal quant_mpeg_inter_mmx
381 :     quant_mpeg_inter_mmx:
382 :    
383 : edgomez 1176 push ecx
384 :     push esi
385 :     push edi
386 : edgomez 1174
387 : edgomez 1176 mov edi, [esp + 12 + 4] ; coeff
388 :     mov esi, [esp + 12 + 8] ; data
389 :     mov eax, [esp + 12 + 12] ; quant
390 : edgomez 1174
391 : edgomez 1176 xor ecx, ecx
392 : edgomez 1174
393 : edgomez 1176 pxor mm5, mm5 ; sum
394 : edgomez 1174
395 : edgomez 1176 cmp al, 1
396 :     jz near .q1loop
397 : edgomez 1174
398 : edgomez 1176 cmp al, 2
399 :     jz near .q2loop
400 : edgomez 1174
401 : edgomez 1176 movq mm7, [mmx_div + eax * 8 - 8] ; divider
402 : edgomez 1174
403 :     align ALIGN
404 :     .loop
405 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
406 :     movq mm3, [esi + 8*ecx + 8] ;
407 :     pxor mm1, mm1 ; mm1 = 0
408 :     pxor mm4, mm4 ;
409 :     pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
410 :     pcmpgtw mm4, mm3 ;
411 :     pxor mm0, mm1 ; mm0 = |mm0|
412 :     pxor mm3, mm4 ;
413 :     psubw mm0, mm1 ; displace
414 :     psubw mm3, mm4 ;
415 : edgomez 1174
416 : edgomez 1176 psllw mm0, 4
417 :     psllw mm3, 4
418 : edgomez 1174
419 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx]
420 :     psrlw mm2, 1
421 :     paddw mm0, mm2
422 : edgomez 1174
423 : edgomez 1176 movq mm2, [inter_matrix_fix + ecx*8]
424 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
425 : edgomez 1174
426 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx + 8]
427 :     psrlw mm2, 1
428 :     paddw mm3, mm2
429 : edgomez 1174
430 : edgomez 1176 movq mm2, [inter_matrix_fix + ecx*8 + 8]
431 :     pmulhw mm3, mm2
432 : edgomez 1174
433 : edgomez 1176 pmulhw mm0, mm7 ; mm0 = (mm0 / 2Q) >> 16
434 :     pmulhw mm3, mm7 ;
435 :     psrlw mm0, 1 ; additional shift by 1 => 16 + 1 = 17
436 :     psrlw mm3, 1
437 : edgomez 1174
438 : edgomez 1176 paddw mm5, mm0 ; sum += mm0
439 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
440 :     paddw mm5, mm3 ;
441 :     pxor mm3, mm4 ;
442 :     psubw mm0, mm1 ; undisplace
443 :     psubw mm3, mm4
444 :     movq [edi + 8*ecx], mm0
445 :     movq [edi + 8*ecx + 8], mm3
446 : edgomez 1174
447 : edgomez 1176 add ecx, 2
448 :     cmp ecx, 16
449 :     jnz near .loop
450 : edgomez 1174
451 :     .done
452 : edgomez 1176 pmaddwd mm5, [mmx_one]
453 :     movq mm0, mm5
454 :     psrlq mm5, 32
455 :     paddd mm0, mm5
456 :     movd eax, mm0 ; return sum
457 : edgomez 1174
458 : edgomez 1176 pop edi
459 :     pop esi
460 :     pop ecx
461 : edgomez 1174
462 : edgomez 1176 ret
463 : edgomez 1174
464 :     align ALIGN
465 :     .q1loop
466 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
467 :     movq mm3, [esi + 8*ecx+ 8]
468 : edgomez 1174 ;
469 : edgomez 1176 pxor mm1, mm1 ; mm1 = 0
470 :     pxor mm4, mm4 ;
471 : edgomez 1174
472 : edgomez 1176 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
473 :     pcmpgtw mm4, mm3 ;
474 : edgomez 1174
475 : edgomez 1176 pxor mm0, mm1 ; mm0 = |mm0|
476 :     pxor mm3, mm4 ;
477 :     psubw mm0, mm1 ; displace
478 :     psubw mm3, mm4 ;
479 : edgomez 1174
480 : edgomez 1176 psllw mm0, 4
481 :     psllw mm3, 4
482 : edgomez 1174
483 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx]
484 :     psrlw mm2, 1
485 :     paddw mm0, mm2
486 : edgomez 1174
487 : edgomez 1176 movq mm2, [inter_matrix_fix + ecx*8]
488 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
489 : edgomez 1174
490 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx + 8]
491 :     psrlw mm2, 1
492 :     paddw mm3, mm2
493 :    
494 :     movq mm2, [inter_matrix_fix + ecx*8 + 8]
495 :     pmulhw mm3, mm2
496 : edgomez 1174
497 : edgomez 1176 psrlw mm0, 1 ; mm0 >>= 1 (/2)
498 :     psrlw mm3, 1 ;
499 : edgomez 1174
500 : edgomez 1176 paddw mm5, mm0 ; sum += mm0
501 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
502 :     paddw mm5, mm3 ;
503 :     pxor mm3, mm4 ;
504 :     psubw mm0, mm1 ; undisplace
505 :     psubw mm3, mm4
506 : edgomez 1174
507 : edgomez 1176 movq [edi + 8*ecx], mm0
508 :     movq [edi + 8*ecx + 8], mm3
509 : edgomez 1174
510 : edgomez 1176 add ecx, 2
511 :     cmp ecx, 16
512 :     jnz near .q1loop
513 : edgomez 1174
514 : edgomez 1176 jmp .done
515 : edgomez 1174
516 :    
517 :     align ALIGN
518 :     .q2loop
519 : edgomez 1176 movq mm0, [esi + 8*ecx] ; mm0 = [1st]
520 :     movq mm3, [esi + 8*ecx+ 8]
521 : edgomez 1174 ;
522 : edgomez 1176 pxor mm1, mm1 ; mm1 = 0
523 :     pxor mm4, mm4 ;
524 : edgomez 1174
525 : edgomez 1176 pcmpgtw mm1, mm0 ; mm1 = (0 > mm0)
526 :     pcmpgtw mm4, mm3 ;
527 : edgomez 1174
528 : edgomez 1176 pxor mm0, mm1 ; mm0 = |mm0|
529 :     pxor mm3, mm4 ;
530 :     psubw mm0, mm1 ; displace
531 :     psubw mm3, mm4 ;
532 : edgomez 1174
533 : edgomez 1176 psllw mm0, 4
534 :     psllw mm3, 4
535 : edgomez 1174
536 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx]
537 :     psrlw mm2, 1
538 :     paddw mm0, mm2
539 : edgomez 1174
540 : edgomez 1176 movq mm2, [inter_matrix_fix + ecx*8]
541 :     pmulhw mm0, mm2 ; (level<<4 + inter_matrix[i]>>1) / inter_matrix[i]
542 : edgomez 1174
543 : edgomez 1176 movq mm2, [inter_matrix + 8*ecx + 8]
544 :     psrlw mm2, 1
545 :     paddw mm3, mm2
546 : edgomez 1174
547 : edgomez 1176 movq mm2, [inter_matrix_fix + ecx*8 + 8]
548 :     pmulhw mm3, mm2
549 : edgomez 1174
550 : edgomez 1176 psrlw mm0, 2 ; mm0 >>= 1 (/2)
551 :     psrlw mm3, 2 ;
552 : edgomez 1174
553 : edgomez 1176 paddw mm5, mm0 ; sum += mm0
554 :     pxor mm0, mm1 ; mm0 *= sign(mm0)
555 :     paddw mm5, mm3 ;
556 :     pxor mm3, mm4 ;
557 :     psubw mm0, mm1 ; undisplace
558 :     psubw mm3, mm4
559 : edgomez 1174
560 : edgomez 1176 movq [edi + 8*ecx], mm0
561 :     movq [edi + 8*ecx + 8], mm3
562 : edgomez 1174
563 : edgomez 1176 add ecx, 2
564 :     cmp ecx, 16
565 :     jnz near .q2loop
566 : edgomez 1174
567 : edgomez 1176 jmp .done
568 : edgomez 1174
569 :    
570 :     ;===========================================================================
571 :     ;
572 : edgomez 1176 ; uint32_t dequant_mpeg_intra_mmx(int16_t *data,
573 :     ; const int16_t const *coeff,
574 :     ; const uint32_t quant,
575 :     ; const uint32_t dcscalar);
576 : edgomez 1174 ;
577 :     ;===========================================================================
578 :    
579 :     ; Note: in order to saturate 'easily', we pre-shift the quantifier
580 :     ; by 4. Then, the high-word of (coeff[]*matrix[i]*quant) are used to
581 :     ; build a saturating mask. It is non-zero only when an overflow occured.
582 :     ; We thus avoid packing/unpacking toward double-word.
583 :     ; Moreover, we perform the mult (matrix[i]*quant) first, instead of, e.g.,
584 :     ; (coeff[i]*matrix[i]). This is less prone to overflow if coeff[] are not
585 :     ; checked. Input ranges are: coeff in [-127,127], inter_matrix in [1..255],a
586 :     ; and quant in [1..31].
587 :     ;
588 :     ; The original loop is:
589 :     ;
590 :     %if 0
591 : edgomez 1176 movq mm0, [ecx+8*eax + 8*16] ; mm0 = coeff[i]
592 :     pxor mm1, mm1
593 :     pcmpgtw mm1, mm0
594 :     pxor mm0, mm1 ; change sign if negative
595 :     psubw mm0, mm1 ; -> mm0 = abs(coeff[i]), mm1 = sign of coeff[i]
596 : edgomez 1174
597 : edgomez 1176 movq mm2, mm7 ; mm2 = quant
598 :     pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant.
599 : edgomez 1174
600 : edgomez 1176 movq mm6, mm2
601 :     pmulhw mm2, mm0 ; high of coeff*(matrix*quant) (should be 0 if no overflow)
602 :     pmullw mm0, mm6 ; low of coeff*(matrix*quant)
603 : edgomez 1174
604 : edgomez 1176 pxor mm5, mm5
605 :     pcmpgtw mm2, mm5 ; otherflow?
606 :     psrlw mm2, 5 ; =0 if no clamp, 2047 otherwise
607 :     psrlw mm0, 5
608 :     paddw mm0, mm1 ; start restoring sign
609 :     por mm0, mm2 ; saturate to 2047 if needed
610 :     pxor mm0, mm1 ; finish negating back
611 : edgomez 1174
612 : edgomez 1176 movq [edx + 8*eax + 8*16], mm0 ; data[i]
613 :     add eax, 1
614 : edgomez 1174 %endif
615 :    
616 :     ;********************************************************************
617 :    
618 :     align 16
619 :     cglobal dequant_mpeg_intra_mmx
620 :     dequant_mpeg_intra_mmx:
621 :    
622 : edgomez 1176 mov edx, [esp+4] ; data
623 :     mov ecx, [esp+8] ; coeff
624 :     mov eax, [esp+12] ; quant
625 : edgomez 1174
626 : edgomez 1176 movq mm7, [mmx_mul_quant + eax*8 - 8]
627 :     mov eax, -16 ; to keep aligned, we regularly process coeff[0]
628 :     psllw mm7, 2 ; << 2. See comment.
629 :     pxor mm6, mm6 ; this is a NOP
630 : edgomez 1174
631 :     align 16
632 :     .loop
633 : edgomez 1176 movq mm0, [ecx+8*eax + 8*16] ; mm0 = c = coeff[i]
634 :     movq mm3, [ecx+8*eax + 8*16 +8]; mm3 = c' = coeff[i+1]
635 :     pxor mm1, mm1
636 :     pxor mm4, mm4
637 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c)
638 :     movq mm2, mm7 ; mm2 = quant
639 : edgomez 1174
640 : edgomez 1176 pcmpgtw mm4, mm3 ; mm4 = sgn(c')
641 :     pmullw mm2, [intra_matrix + 8*eax + 8*16 ] ; matrix[i]*quant
642 : edgomez 1174
643 : edgomez 1176 pxor mm0, mm1 ; negate if negative
644 :     pxor mm3, mm4 ; negate if negative
645 : edgomez 1174
646 : edgomez 1176 psubw mm0, mm1
647 :     psubw mm3, mm4
648 : edgomez 1174
649 :     ; we're short on register, here. Poor pairing...
650 :    
651 : edgomez 1176 movq mm5, mm2
652 :     pmullw mm2, mm0 ; low of coeff*(matrix*quant)
653 : edgomez 1174
654 : edgomez 1176 pmulhw mm0, mm5 ; high of coeff*(matrix*quant)
655 :     movq mm5, mm7 ; mm2 = quant
656 : edgomez 1174
657 : edgomez 1176 pmullw mm5, [intra_matrix + 8*eax + 8*16 +8] ; matrix[i+1]*quant
658 : edgomez 1174
659 : edgomez 1176 movq mm6, mm5
660 :     add eax,2 ; z-flag will be tested later
661 : edgomez 1174
662 : edgomez 1176 pmullw mm6, mm3 ; low of coeff*(matrix*quant)
663 :     pmulhw mm3, mm5 ; high of coeff*(matrix*quant)
664 : edgomez 1174
665 : edgomez 1176 pcmpgtw mm0, [zero]
666 :     paddusw mm2, mm0
667 :     psrlw mm2, 5
668 : edgomez 1174
669 : edgomez 1176 pcmpgtw mm3, [zero]
670 :     paddusw mm6, mm3
671 :     psrlw mm6, 5
672 : edgomez 1174
673 : edgomez 1176 pxor mm2, mm1 ; start negating back
674 :     pxor mm6, mm4 ; start negating back
675 : edgomez 1174
676 : edgomez 1176 psubusw mm1, mm0
677 :     psubusw mm4, mm3
678 : edgomez 1174
679 : edgomez 1176 psubw mm2, mm1 ; finish negating back
680 :     psubw mm6, mm4 ; finish negating back
681 : edgomez 1174
682 : edgomez 1176 movq [edx + 8*eax + 8*16 -2*8 ], mm2 ; data[i]
683 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm6 ; data[i+1]
684 : edgomez 1174
685 : edgomez 1176 jnz near .loop
686 : edgomez 1174
687 :     ; deal with DC
688 :    
689 : edgomez 1176 movd mm0, [ecx]
690 :     pmullw mm0, [esp+16] ; dcscalar
691 :     movq mm2, [mmx_32767_minus_2047]
692 :     paddsw mm0, mm2
693 :     psubsw mm0, mm2
694 :     movq mm2, [mmx_32768_minus_2048]
695 :     psubsw mm0, mm2
696 :     paddsw mm0, mm2
697 :     movd eax, mm0
698 :     mov [edx], ax
699 : edgomez 1174
700 : edgomez 1176 xor eax, eax
701 :     ret
702 : edgomez 1174
703 :     ;===========================================================================
704 :     ;
705 : edgomez 1176 ; uint32_t dequant_mpeg_inter_mmx(int16_t * data,
706 :     ; const int16_t * const coeff,
707 :     ; const uint32_t quant);
708 : edgomez 1174 ;
709 :     ;===========================================================================
710 :    
711 :     ; Note: We use (2*c + sgn(c) - sgn(-c)) as multiplier
712 :     ; so we handle the 3 cases: c<0, c==0, and c>0 in one shot.
713 :     ; sgn(x) is the result of 'pcmpgtw 0,x': 0 if x>=0, -1 if x<0.
714 :     ; It's mixed with the extraction of the absolute value.
715 :    
716 :     align 16
717 :     cglobal dequant_mpeg_inter_mmx
718 :     dequant_mpeg_inter_mmx:
719 :    
720 : edgomez 1176 mov edx, [esp+ 4] ; data
721 :     mov ecx, [esp+ 8] ; coeff
722 :     mov eax, [esp+12] ; quant
723 :     movq mm7, [mmx_mul_quant + eax*8 - 8]
724 :     mov eax, -16
725 :     paddw mm7, mm7 ; << 1
726 :     pxor mm6, mm6 ; mismatch sum
727 : edgomez 1174
728 :     align 16
729 :     .loop
730 : edgomez 1176 movq mm0, [ecx+8*eax + 8*16 ] ; mm0 = coeff[i]
731 :     movq mm2, [ecx+8*eax + 8*16 +8] ; mm2 = coeff[i+1]
732 :     add eax, 2
733 : edgomez 1174
734 : edgomez 1176 pxor mm1, mm1
735 :     pxor mm3, mm3
736 :     pcmpgtw mm1, mm0 ; mm1 = sgn(c) (preserved)
737 :     pcmpgtw mm3, mm2 ; mm3 = sgn(c') (preserved)
738 :     paddsw mm0, mm1 ; c += sgn(c)
739 :     paddsw mm2, mm3 ; c += sgn(c')
740 :     paddw mm0, mm0 ; c *= 2
741 :     paddw mm2, mm2 ; c'*= 2
742 : edgomez 1174
743 : edgomez 1176 pxor mm4, mm4
744 :     pxor mm5, mm5
745 :     psubw mm4, mm0 ; -c
746 :     psubw mm5, mm2 ; -c'
747 :     psraw mm4, 16 ; mm4 = sgn(-c)
748 :     psraw mm5, 16 ; mm5 = sgn(-c')
749 :     psubsw mm0, mm4 ; c -= sgn(-c)
750 :     psubsw mm2, mm5 ; c' -= sgn(-c')
751 :     pxor mm0, mm1 ; finish changing sign if needed
752 :     pxor mm2, mm3 ; finish changing sign if needed
753 : edgomez 1174
754 :     ; we're short on register, here. Poor pairing...
755 :    
756 : edgomez 1176 movq mm4, mm7 ; (matrix*quant)
757 :     pmullw mm4, [inter_matrix + 8*eax + 8*16 -2*8]
758 :     movq mm5, mm4
759 :     pmulhw mm5, mm0 ; high of c*(matrix*quant)
760 :     pmullw mm0, mm4 ; low of c*(matrix*quant)
761 : edgomez 1174
762 : edgomez 1176 movq mm4, mm7 ; (matrix*quant)
763 :     pmullw mm4, [inter_matrix + 8*eax + 8*16 -2*8 + 8]
764 : edgomez 1174
765 : edgomez 1176 pcmpgtw mm5, [zero]
766 :     paddusw mm0, mm5
767 :     psrlw mm0, 5
768 :     pxor mm0, mm1 ; start restoring sign
769 :     psubusw mm1, mm5
770 : edgomez 1174
771 : edgomez 1176 movq mm5, mm4
772 :     pmulhw mm5, mm2 ; high of c*(matrix*quant)
773 :     pmullw mm2, mm4 ; low of c*(matrix*quant)
774 :     psubw mm0, mm1 ; finish restoring sign
775 : edgomez 1174
776 : edgomez 1176 pcmpgtw mm5, [zero]
777 :     paddusw mm2, mm5
778 :     psrlw mm2, 5
779 :     pxor mm2, mm3 ; start restoring sign
780 :     psubusw mm3, mm5
781 :     psubw mm2, mm3 ; finish restoring sign
782 : edgomez 1174
783 : edgomez 1176 pxor mm6, mm0 ; mismatch control
784 :     movq [edx + 8*eax + 8*16 -2*8 ], mm0 ; data[i]
785 :     pxor mm6, mm2 ; mismatch control
786 :     movq [edx + 8*eax + 8*16 -2*8 +8], mm2 ; data[i+1]
787 : edgomez 1174
788 : edgomez 1176 jnz near .loop
789 : edgomez 1174
790 :     ; mismatch control
791 :    
792 : edgomez 1176 movq mm0, mm6
793 :     psrlq mm0, 48
794 :     movq mm1, mm6
795 :     movq mm2, mm6
796 :     psrlq mm1, 32
797 :     pxor mm6, mm0
798 :     psrlq mm2, 16
799 :     pxor mm6, mm1
800 :     pxor mm6, mm2
801 :     movd eax, mm6
802 :     and eax, 1
803 :     xor eax, 1
804 :     xor word [edx + 2*63], ax
805 : edgomez 1174
806 : edgomez 1176 xor eax, eax
807 :     ret

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