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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1198 - (view) (download)

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

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