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

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