initial commit
[goodguy/cinelerra.git] / cinelerra-5.1 / mpeg2enc / mblock_sad_mmxe.s
1 ;;; 
2 ;;;  mblock_sad_mmxe.s:  
3 ;;; 
4 ;;; Enhanced MMX optimized Sum Absolute Differences routines for macroblocks
5 ;;; (interpolated, 1-pel, 2*2 sub-sampled pel and 4*4 sub-sampled pel)
6 ;
7 ;  dist1_* Original Copyright (C) 2000 Chris Atenasio <chris@crud.net>
8 ;  Enhancements and rest Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
9
10                 ;; Yes, I tried prefetch-ing.  It makes no difference or makes
11                 ;; stuff *slower*.
12
13 ;
14 ;  This program is free software; you can reaxstribute it and/or
15 ;  modify it under the terms of the GNU General Public License
16 ;  as published by the Free Software Foundation; either version 2
17 ;  of the License, or (at your option) any later version.
18 ;
19 ;  This program is distributed in the hope that it will be useful,
20 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;  GNU General Public License for more details.
23 ;
24 ;  You should have received a copy of the GNU General Public License
25 ;  along with this program; if not, write to the Free Software
26 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27 ;
28 ;
29 ;
30
31
32 global dist1_00_mmxe
33
34 ; int dist1_00(char *blk1,char *blk2,int lx,int h,int distlim);
35 ; distlim unused - costs more to check than the savings of
36 ; aborting the computation early from time to time...
37 ; eax = p1
38 ; ebx = p2
39 ; ecx = rowsleft
40 ; edx = lx;
41
42 ; mm0 = distance accumulator
43 ; mm1 = temp
44 ; mm2 = temp
45 ; mm3 = temp
46 ; mm4 = temp
47 ; mm5 = temp
48 ; mm6 = temp
49
50
51 align 32
52 dist1_00_mmxe:
53         push ebp                                        ; save frame pointer
54         mov ebp, esp                            ; link
55
56         push ebx
57         push ecx
58         push edx
59
60         pxor mm0, mm0           ; zero acculumator
61
62         mov eax, [ebp+8]        ; get p1
63 dist1_00_0misalign:             
64         mov ebx, [ebp+12]       ; get p2
65         mov edx, [ebp+16]       ; get lx
66
67         mov ecx, [ebp+20]       ; get rowsleft
68         jmp nextrow00sse
69 align 32
70 nextrow00sse:
71         movq mm4, [eax]         ; load first 8 bytes of p1 (row 1)
72         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 (row 1)
73         movq mm5, [eax+8]       ; load next 8 bytes of p1 (row 1)
74         add eax, edx            ; update pointer to next row
75         paddd mm0, mm4          ; accumulate difference
76         
77         psadbw mm5, [ebx+8]     ; compare to next 8 bytes of p2 (row 1)
78         add ebx, edx            ; ditto
79         paddd mm0, mm5          ; accumulate difference
80
81
82         movq mm6, [eax]         ; load first 8 bytes of p1 (row 2)
83         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
84         movq mm4, [eax+8]       ; load next 8 bytes of p1 (row 2)
85         add eax, edx            ; update pointer to next row
86         paddd mm0, mm6          ; accumulate difference
87         
88         psadbw mm4, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
89         add ebx, edx            ; ditto
90         paddd mm0, mm4          ; accumulate difference
91
92         ;psubd mm2, mm3         ; decrease rowsleft
93         ;movq mm5, mm1          ; copy distlim
94         ;pcmpgtd mm5, mm0       ; distlim > dist?
95         ;pand mm2, mm5          ; mask rowsleft with answer
96         ;movd ecx, mm2          ; move rowsleft to ecx
97
98         ;add eax, edx           ; update pointer to next row
99         ;add ebx, edx           ; ditto
100         
101         ;test ecx, ecx          ; check rowsleft
102         sub  ecx, 2
103         jnz nextrow00sse
104
105         movd eax, mm0           ; store return value
106         
107         pop edx 
108         pop ecx 
109         pop ebx 
110
111         pop ebp 
112         emms
113         ret     
114
115
116                                 
117
118 global dist1_00_Ammxe
119                 ;; This is a special version that only does aligned accesses...
120                 ;; Wonder if it'll make it faster on a P-III
121                 ;; ANSWER:               NO its slower hence no longer used.
122
123 ; int dist1_00(char *blk1,char *blk2,int lx,int h,int distlim);
124 ; distlim unused - costs more to check than the savings of
125 ; aborting the computation early from time to time...
126 ; eax = p1
127 ; ebx = p2
128 ; ecx = rowsleft
129 ; edx = lx;
130
131 ; mm0 = distance accumulator
132 ; mm1 = temp
133 ; mm2 = right shift to adjust for mis-align
134 ; mm3 = left shift to adjust for mis-align
135 ; mm4 = temp
136 ; mm5 = temp
137 ; mm6 = temp
138
139
140 align 32
141 dist1_00_Ammxe:
142         push ebp                                        ; save frame pointer
143         mov ebp, esp                            ; link
144
145         push ebx
146         push ecx
147         push edx
148                 
149         pxor mm0, mm0           ; zero acculumator
150
151         mov eax, [ebp+8]        ; get p1
152         mov ebx, eax
153         and ebx, 7                                      ; Misalignment!
154         cmp ebx, 0
155         jz      near dist1_00_0misalign
156         sub eax, ebx                            ; Align eax
157         mov ecx, 8                                      ; ecx = 8-misalignment
158         sub ecx, ebx
159         shl ebx, 3                                      ; Convert into bit-shifts...
160         shl ecx, 3                                      
161         movd mm2, ebx                           ; mm2 = shift to start msb
162         movd mm3, ecx                           ; mm3 = shift to end lsb
163
164         mov ebx, [ebp+12]       ; get p2
165         mov edx, [ebp+16]       ; get lx
166         mov ecx, [ebp+20]       ; get rowsleft
167         jmp nextrow00ssea
168 align 32
169 nextrow00ssea:
170         movq mm4, [eax]                         ; load first 8 bytes of aligned p1 (row 1)
171         movq mm5, [eax+8]                       ; load next 8 bytes of aligned p1 (row 1)
172         movq mm6, mm5
173         psrlq mm4, mm2                          ; mm4 first 8 bytes of p1 proper
174         psllq mm5, mm3
175         por       mm4, mm5
176         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 
177
178         movq mm7, [eax+16]                      ; load last 8 bytes of aligned p1
179         add eax, edx            ; update pointer to next row
180         psrlq mm6, mm2                          ; mm6 2nd 8 bytes of p1 proper
181         psllq mm7, mm3
182         por   mm6, mm7
183
184
185         paddd mm0, mm4          ; accumulate difference
186         
187         psadbw mm6, [ebx+8]     ; compare to next 8 bytes of p2 (row 1)
188         add ebx, edx            ; ditto
189         paddd mm0, mm6          ; accumulate difference
190
191         sub  ecx, 1
192         jnz nextrow00ssea
193
194         movd eax, mm0           ; store return value
195
196         pop edx 
197         pop ecx 
198         pop ebx 
199
200         pop ebp 
201         emms
202         ret     
203
204
205 global dist1_01_mmxe
206
207 ; int dist1_01(char *blk1,char *blk2,int lx,int h);
208
209 ; eax = p1
210 ; ebx = p2
211 ; ecx = counter temp
212 ; edx = lx;
213
214 ; mm0 = distance accumulator
215 ; mm1 = distlim
216 ; mm2 = rowsleft
217 ; mm3 = 2 (rows per loop)
218 ; mm4 = temp
219 ; mm5 = temp
220 ; mm6 = temp
221
222
223 align 32
224 dist1_01_mmxe:
225         push ebp        
226         mov ebp, esp
227
228         push ebx
229         push ecx
230         push edx
231
232         pxor mm0, mm0           ; zero acculumator
233
234         mov eax, [ebp+8]        ; get p1
235         mov ebx, [ebp+12]       ; get p2
236         mov edx, [ebp+16]       ; get lx
237
238         mov ecx, [ebp+20]       ; get rowsleft
239         jmp nextrow01           ; snap to it
240 align 32
241 nextrow01:
242         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
243         pavgb mm4, [eax+1]                      ; Interpolate...
244         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
245         paddd mm0, mm4                          ; accumulate difference
246
247         movq mm5, [eax+8]                       ; load next 8 bytes of p1 (row 1)
248         pavgb mm5, [eax+9]                      ; Interpolate
249         psadbw mm5, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
250         paddd mm0, mm5                          ; accumulate difference
251
252         add eax, edx                            ; update pointer to next row
253         add ebx, edx                            ; ditto
254
255         movq mm6, [eax]                         ; load first 8 bytes of p1 (row 2)
256         pavgb mm6, [eax+1]                      ; Interpolate
257         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
258         paddd mm0, mm6          ; accumulate difference
259         
260         movq mm7, [eax+8]       ; load next 8 bytes of p1 (row 2)
261         pavgb mm7, [eax+9]
262         psadbw mm7, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
263         paddd mm0, mm7          ; accumulate difference
264
265         add eax, edx            ; update pointer to next row
266         add ebx, edx            ; ditto
267         
268         sub ecx, 2                      ; check rowsleft
269         jnz nextrow01           ; rinse and repeat
270
271         movd eax, mm0           ; store return value
272         
273         pop edx 
274         pop ecx         
275         pop ebx 
276
277         pop ebp                 ; restore stack pointer
278
279         emms                    ; clear mmx registers
280         ret                     ; we now return you to your regular programming
281
282
283 global dist1_10_mmxe
284
285 ; int dist1_10(char *blk1,char *blk2,int lx,int h);
286
287 ; eax = p1
288 ; ebx = p2
289 ; ecx = counter temp
290 ; edx = lx;
291 ; edi = p1+lx  
292
293 ; mm0 = distance accumulator
294 ; mm2 = rowsleft
295 ; mm3 = 2 (rows per loop)
296 ; mm4 = temp
297 ; mm5 = temp
298 ; mm6 = temp
299
300
301 align 32
302 dist1_10_mmxe:
303         push ebp                ; save stack pointer
304         mov ebp, esp
305
306         push ebx
307         push ecx
308         push edx
309         push edi
310
311         pxor mm0, mm0           ; zero acculumator
312
313         mov eax, [ebp+8]        ; get p1
314         mov ebx, [ebp+12]       ; get p2
315         mov edx, [ebp+16]       ; get lx
316         mov edi, eax
317         add edi, edx
318         mov ecx, [ebp+20]       ; get rowsleft
319         jmp nextrow10           ; snap to it
320 align 32
321 nextrow10:
322         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
323         pavgb mm4, [edi]                        ; Interpolate...
324         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
325         paddd mm0, mm4                          ; accumulate difference
326
327         movq mm5, [eax+8]                       ; load next 8 bytes of p1 (row 1)
328         pavgb mm5, [edi+8]                      ; Interpolate
329         psadbw mm5, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
330         paddd mm0, mm5                          ; accumulate difference
331
332         add eax, edx                            ; update pointer to next row
333         add ebx, edx                            ; ditto
334         add edi, edx
335
336         movq mm6, [eax]                         ; load first 8 bytes of p1 (row 2)
337         pavgb mm6, [edi]                        ; Interpolate
338         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
339         paddd mm0, mm6          ; accumulate difference
340         
341         movq mm7, [eax+8]       ; load next 8 bytes of p1 (row 2)
342         pavgb mm7, [edi+8]
343         psadbw mm7, [ebx+8]     ; compare to next 8 bytes of p2 (row 2)
344         paddd mm0, mm7          ; accumulate difference
345
346         psubd mm2, mm3          ; decrease rowsleft
347
348         add eax, edx            ; update pointer to next row
349         add ebx, edx            ; ditto
350         add edi, edx
351         
352         sub ecx, 2                      ; check rowsleft (we're doing 2 at a time)
353         jnz nextrow10           ; rinse and repeat
354
355         movd eax, mm0           ; store return value
356         
357         pop edi
358         pop edx 
359         pop ecx 
360         pop ebx 
361
362         pop ebp                 ; restore stack pointer
363
364         emms                    ; clear mmx registers
365         ret                     ; we now return you to your regular programming
366
367
368 global dist1_11_mmxe
369
370 ; int dist1_11(char *blk1,char *blk2,int lx,int h);
371
372 ; eax = p1
373 ; ebx = p2
374 ; ecx = counter temp
375 ; edx = lx;
376 ; edi = p1+lx  
377
378                   
379 ; mm0 = distance accumulator
380 ; mm2 = rowsleft
381 ; mm3 = 2 (rows per loop)
382 ; mm4 = temp
383 ; mm5 = temp
384 ; mm6 = temp
385
386
387 align 32
388 dist1_11_mmxe:
389         push ebp                ; save stack pointer
390         mov ebp, esp            ; so that we can do this
391
392         push ebx                ; save the pigs
393         push ecx                ; make them squeal
394         push edx                ; lets have pigs for every meal
395         push edi
396
397         pxor mm0, mm0           ; zero acculumator
398
399         mov eax, [ebp+8]        ; get p1
400         mov ebx, [ebp+12]       ; get p2
401         mov edx, [ebp+16]       ; get lx
402         mov edi, eax
403         add edi, edx
404         mov ecx, [ebp+20]       ; get rowsleft
405         jmp nextrow11           ; snap to it
406 align 32
407 nextrow11:
408         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
409         pavgb mm4, [edi]                        ; Interpolate...
410         movq mm5, [eax+1]
411         pavgb mm5, [edi+1]
412         pavgb mm4, mm5
413         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
414         paddd mm0, mm4                          ; accumulate difference
415
416         movq mm6, [eax+8]                       ; load next 8 bytes of p1 (row 1)
417         pavgb mm6, [edi+8]                      ; Interpolate
418         movq mm7, [eax+9]
419         pavgb mm7, [edi+9]
420         pavgb mm6, mm7
421         psadbw mm6, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
422         paddd mm0, mm6                          ; accumulate difference
423
424         add eax, edx                            ; update pointer to next row
425         add ebx, edx                            ; ditto
426         add edi, edx
427
428         movq mm4, [eax]                         ; load first 8 bytes of p1 (row 1)
429         pavgb mm4, [edi]                        ; Interpolate...
430         movq mm5, [eax+1]
431         pavgb mm5, [edi+1]
432         pavgb mm4, mm5
433         psadbw mm4, [ebx]                       ; compare to first 8 bytes of p2 (row 1)
434         paddd mm0, mm4                          ; accumulate difference
435
436         movq mm6, [eax+8]                       ; load next 8 bytes of p1 (row 1)
437         pavgb mm6, [edi+8]                      ; Interpolate
438         movq mm7, [eax+9]
439         pavgb mm7, [edi+9]
440         pavgb mm6, mm7
441         psadbw mm6, [ebx+8]                     ; compare to next 8 bytes of p2 (row 1)
442         paddd mm0, mm6                          ; accumulate difference
443                 
444         add eax, edx            ; update pointer to next row
445         add ebx, edx            ; ditto
446         add edi, edx
447
448                         
449         sub ecx, 2                              ; check rowsleft
450         jnz near nextrow11                      ; rinse and repeat
451
452         movd eax, mm0                           ; store return value
453         
454         pop edi
455         pop edx 
456         pop ecx         
457         pop ebx                 
458         
459         pop ebp                 ; restore stack pointer
460
461         emms                    ; clear mmx registers
462         ret                     ; we now return you to your regular programming
463
464 global dist22_mmxe
465
466 ; int dist22_mmxe(unsigned char *blk1,unsigned char *blk2,int flx,int fh);
467
468 ; eax = p1
469 ; ebx = p2
470 ; ecx = counter temp
471 ; edx = flx;
472
473 ; mm0 = distance accumulator
474 ; mm2 = rowsleft
475 ; mm3 = 2 (rows per loop)
476 ; mm4 = temp
477 ; mm5 = temp
478 ; mm6 = temp
479
480
481 align 32
482 dist22_mmxe:
483         push ebp                ; save frame pointer
484         mov ebp, esp
485
486         push ebx        
487         push ecx
488         push edx        
489
490         pxor mm0, mm0           ; zero acculumator
491
492         mov eax, [ebp+8]        ; get p1
493         mov ebx, [ebp+12]       ; get p2
494         mov edx, [ebp+16]       ; get lx
495
496         mov ecx, [ebp+20]
497         jmp nextrowfd
498 align 32
499 nextrowfd:
500         movq   mm4, [eax]        ; load first 8 bytes of p1 (row 1) 
501         add eax, edx            ; update pointer to next row
502         psadbw mm4, [ebx]       ; compare to first 8 bytes of p2 (row 1)
503         add ebx, edx            ; ditto
504         paddd  mm0, mm4         ; accumulate difference
505         
506
507         movq mm6, [eax]         ; load first 8 bytes of p1 (row 2)
508         add eax, edx            ; update pointer to next row
509         psadbw mm6, [ebx]       ; compare to first 8 bytes of p2 (row 2)
510         add ebx, edx            ; ditto
511         paddd mm0, mm6          ; accumulate difference
512         
513
514         sub ecx, 2
515         jnz nextrowfd
516
517         movd eax, mm0
518         
519         pop edx 
520         pop ecx 
521         pop ebx 
522
523         pop ebp
524
525         emms
526         ret
527
528
529
530
531
532 global dist44_mmxe
533
534 ; int dist44_mmxe(unsigned char *blk1,unsigned char *blk2,int qlx,int qh);
535
536 ; eax = p1
537 ; ebx = p2
538 ; ecx = temp
539 ; edx = qlx;
540 ; esi = rowsleft
541
542 ; mm0 = distance accumulator left block p1
543 ; mm1 = distance accumulator right block p1
544 ; mm2 = 0
545 ; mm3 = 0
546 ; mm4 = temp
547 ; mm5 = temp
548 ; mm6 = temp
549
550
551 align 32
552 dist44_mmxe:
553         push ebp
554         mov ebp, esp
555
556         push ebx
557         push ecx
558         push edx
559         push esi     
560
561         pxor mm0, mm0           ; zero acculumator
562         pxor mm1, mm1                           
563         pxor mm2, mm2
564         mov eax, [ebp+8]        ; get p1
565         mov ebx, [ebp+12]       ; get p2
566         mov edx, [ebp+16]       ; get qlx
567
568         mov esi, [ebp+20]       ; get rowsleft
569         jmp nextrowqd           ; snap to it
570 align 32
571 nextrowqd: 
572         movq mm4, [eax]                         ; load 8 bytes of p1 (two blocks!)
573         add eax, edx            ; update pointer to next row
574         movq mm6, mm4                             ;
575         mov  ecx, [ebx]       ; load 4 bytes of p2
576     punpcklbw mm4, mm2                  ; mm4 = bytes 0..3 p1 (spaced out)
577         movd mm5, ecx
578         punpcklbw mm5, mm2      ; mm5 = bytes 0..3 p2  (spaced out)
579         psadbw mm4, mm5                 ; compare to left block
580         add ebx, edx            ; ditto
581
582 ;       punpckhbw mm6, mm2          ; mm6 = bytes 4..7 p1 (spaced out)
583
584         paddd mm0, mm4                          ; accumulate difference left block
585
586 ;       psadbw mm6,mm5                          ; compare to right block
587         
588
589 ;       paddd mm1, mm6                          ; accumulate difference right block
590                 
591         sub esi, 1
592         jnz nextrowqd
593
594         movd eax, mm0
595 ;       movd ebx, mm1                           
596 ;       sal  ebx, 16
597 ;       or   eax, ebx
598         
599         pop esi
600         pop edx
601         pop ecx
602         pop ebx
603
604         pop ebp                 ; restore stack pointer
605
606         emms                    ; clear mmx registers
607         ret                     ; we now return you to your regular programming