First set of 50 GPL attribution for CV-Contributors added
[goodguy/cinelerra.git] / cinelerra-5.1 / mpeg2enc / mblock_sad_mmx.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 ;
11 ;  This program is free software; you can redistribute it and/or
12 ;  modify it under the terms of the GNU General Public License
13 ;  as published by the Free Software Foundation; either version 2
14 ;  of the License, or (at your option) any later version.
15 ;
16 ;  This program is distributed in the hope that it will be useful,
17 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;  GNU General Public License for more details.
20 ;
21 ;  You should have received a copy of the GNU General Public License
22 ;  along with this program; if not, write to the Free Software
23 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24 ;
25 ;
26 ;
27
28
29 global dist1_00_mmx
30
31 ; int dist1_mmx(unsigned char *blk1,unsigned char *blk2,int lx,int h, int distlim);
32 ; N.b. distlim is *ignored* as testing for it is more expensive than the
33 ; occasional saving by aborting the computionation early...
34 ; esi = p1 (init:               blk1)
35 ; edi = p2 (init:               blk2)
36 ; ebx = distlim  
37 ; ecx = rowsleft (init:  h)
38 ; edx = lx;
39
40 ; mm0 = distance accumulators (4 words)
41 ; mm1 = temp 
42 ; mm2 = temp 
43 ; mm3 = temp
44 ; mm4 = temp
45 ; mm5 = temp 
46 ; mm6 = 0
47 ; mm7 = temp
48
49
50 SECTION .text
51 align 32
52 dist1_00_mmx:
53         push ebp                ; save frame pointer
54         mov ebp, esp
55
56         push ebx                ; Saves registers (called saves convention in
57         push ecx                ; x86 GCC it seems)
58         push edx                ; 
59         push esi
60         push edi
61                 
62         pxor mm0, mm0                           ; zero acculumators
63         pxor mm6, mm6
64         mov esi, [ebp+8]                        ; get p1
65         mov edi, [ebp+12]                       ; get p2
66         mov edx, [ebp+16]                       ; get lx
67         mov  ecx, [ebp+20]                      ; get rowsleft
68         ;mov ebx, [ebp+24]              ; distlim
69         jmp nextrowmm00
70 align 32
71 nextrowmm00:
72         movq mm4, [esi]         ; load first 8 bytes of p1 row 
73         movq mm5, [edi]         ; load first 8 bytes of p2 row
74                 
75         movq mm7, mm4       ; mm5 = abs(mm4-mm5)
76         psubusb mm7, mm5
77         psubusb mm5, mm4
78         paddb   mm5, mm7
79
80         ;;  Add the abs(mm4-mm5) bytes to the accumulators
81         movq mm2, [esi+8]               ; load second 8 bytes of p1 row (interleaved)
82         movq  mm7,mm5                           ; mm7 := [i :   B0..3, mm1]W
83         punpcklbw mm7,mm6
84         movq mm3, [edi+8]               ; load second 8 bytes of p2 row (interleaved)
85         paddw mm0, mm7
86         punpckhbw mm5,mm6
87         paddw mm0, mm5
88
89                 ;; This is logically where the mm2, mm3 loads would go...
90                 
91         movq mm7, mm2       ; mm3 = abs(mm2-mm3)
92         psubusb mm7, mm3
93         psubusb mm3, mm2
94         paddb   mm3, mm7
95
96         ;;  Add the abs(mm4-mm5) bytes to the accumulators
97         movq  mm7,mm3                           ; mm7 := [i :   B0..3, mm1]W
98         punpcklbw mm7,mm6
99         punpckhbw mm3,mm6
100         paddw mm0, mm7
101         
102         add esi, edx            ; update pointer to next row
103         add edi, edx            ; ditto 
104
105         paddw mm0, mm3
106
107
108
109         sub  ecx,1
110         jnz near nextrowmm00
111                 
112 returnmm00:     
113
114                 ;; Sum the Accumulators
115         movq  mm5, mm0                          ; mm5 := [W0+W2,W1+W3, mm0
116         psrlq mm5, 32
117         movq  mm4, mm0
118         paddw mm4, mm5
119
120         movq  mm7, mm4              ; mm6 := [W0+W2+W1+W3, mm0]
121         psrlq mm7, 16
122         paddw mm4, mm7
123         movd eax, mm4           ; store return value
124         and  eax, 0xffff
125
126         pop edi
127         pop esi 
128         pop edx 
129         pop ecx 
130         pop ebx 
131
132         pop ebp 
133
134         emms                    ; clear mmx registers
135         ret     
136 ;
137 ;;;  dist1_01_mmx.s:  mmx1 optimised 7bit*8 word absolute difference sum
138 ;;;     We're reduce to seven bits as otherwise we also have to mess
139 ;;;     horribly with carries and signed only comparisons make the code
140 ;;;     simply enormous (and probably barely faster than a simple loop).
141 ;;;     Since signals with a bona-fide 8bit res will be rare we simply
142 ;;;     take the precision hit...
143 ;;;     Actually we don't worry about carries from the low-order bits
144 ;;;     either so 1/4 of the time we'll be 1 too low...
145 ;;; 
146 ;  Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
147
148 ;
149 ;  This program is free software; you can redistribute it and/or
150 ;  modify it under the terms of the GNU General Public License
151 ;  as published by the Free Software Foundation; either version 2
152 ;  of the License, or (at your option) any later version.
153 ;
154 ;  This program is distributed in the hope that it will be useful,
155 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
156 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157 ;  GNU General Public License for more details.
158 ;
159 ;  You should have received a copy of the GNU General Public License
160 ;  along with this program; if not, write to the Free Software
161 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
162 ;
163 ;
164 ;
165
166
167 global dist1_01_mmx
168
169 ; int dist1_01_mmx(unsigned char *p1,unsigned char *p2,int lx,int h);
170
171 ; esi = p1 (init:               blk1)
172 ; edi = p2 (init:               blk2)
173 ; ecx = rowsleft (init:  h)
174 ; edx = lx;
175
176 ; mm0 = distance accumulators (4 words)
177 ; mm1 = bytes p2
178 ; mm2 = bytes p1
179 ; mm3 = bytes p1+1
180 ; mm4 = temp 4 bytes in words interpolating p1, p1+1
181 ; mm5 = temp 4 bytes in words from p2
182 ; mm6 = temp comparison bit mask p1,p2
183 ; mm7 = temp comparison bit mask p2,p1
184
185
186 align 32
187 dist1_01_mmx:
188         push ebp                ; save stack pointer
189         mov ebp, esp    ; so that we can do this
190
191         push ebx                ; Saves registers (called saves convention in
192         push ecx                ; x86 GCC it seems)
193         push edx                ; 
194         push esi
195         push edi
196                 
197         pxor mm0, mm0                           ; zero acculumators
198
199         mov esi, [ebp+8]                        ; get p1
200         mov edi, [ebp+12]                       ; get p2
201         mov edx, [ebp+16]                       ; get lx
202         mov ecx, [ebp+20]                       ; rowsleft := h
203         jmp nextrowmm01                                 ; snap to it
204 align 32
205 nextrowmm01:
206
207                 ;; 
208                 ;; First 8 bytes of row
209                 ;; 
210                 
211                 ;; First 4 bytes of 8
212
213         movq mm4, [esi]             ; mm4 := first 4 bytes p1
214         pxor mm7, mm7
215         movq mm2, mm4                           ;  mm2 records all 8 bytes
216         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
217         
218         movq mm6, [esi+1]                       ;  mm6 := first 4 bytes p1+1
219         movq mm3, mm6               ;  mm3 records all 8 bytes
220         punpcklbw mm6, mm7
221         paddw mm4, mm6              ;  mm4 := First 4 bytes interpolated in words
222         psrlw mm4, 1
223                 
224         movq mm5, [edi]                         ; mm5:=first 4 bytes of p2 in words
225         movq mm1, mm5
226         punpcklbw mm5, mm7
227                         
228         movq  mm7,mm4
229         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
230
231         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
232         psubw mm6,mm5
233         pand  mm6, mm7
234
235         paddw mm0, mm6                          ; Add to accumulator
236
237         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
238         pcmpgtw mm6,mm4     
239         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
240         pand  mm5, mm6          
241
242         paddw mm0, mm5                          ; Add to accumulator
243
244                 ;; Second 4 bytes of 8
245         
246         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
247         pxor  mm7, mm7
248         punpckhbw mm4, mm7                      
249         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
250         punpckhbw mm6, mm7
251                 
252         paddw mm4, mm6          ;  mm4 := First 4 Interpolated bytes in words
253         psrlw mm4, 1
254
255         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
256         punpckhbw mm5, mm7
257                         
258         movq  mm7,mm4
259         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
260
261         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
262         psubw mm6,mm5
263         pand  mm6, mm7
264
265         paddw mm0, mm6                          ; Add to accumulator
266
267         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
268         pcmpgtw mm6,mm4     
269         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
270         pand  mm5, mm6          
271
272         paddw mm0, mm5                          ; Add to accumulator
273
274
275                 ;;
276                 ;; Second 8 bytes of row
277                 ;; 
278                 ;; First 4 bytes of 8
279
280         movq mm4, [esi+8]             ; mm4 := first 4 bytes p1+8
281         pxor mm7, mm7
282         movq mm2, mm4                           ;  mm2 records all 8 bytes
283         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
284         
285         movq mm6, [esi+9]                       ;  mm6 := first 4 bytes p1+9
286         movq mm3, mm6               ;  mm3 records all 8 bytes
287         punpcklbw mm6, mm7
288         paddw mm4, mm6              ;  mm4 := First 4 bytes interpolated in words
289         psrlw mm4, 1
290                 
291         movq mm5, [edi+8]                               ; mm5:=first 4 bytes of p2+8 in words
292         movq mm1, mm5
293         punpcklbw mm5, mm7
294                         
295         movq  mm7,mm4
296         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
297
298         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
299         psubw mm6,mm5
300         pand  mm6, mm7
301
302         paddw mm0, mm6                          ; Add to accumulator
303
304         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
305         pcmpgtw mm6,mm4     
306         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
307         pand  mm5, mm6          
308
309         paddw mm0, mm5                          ; Add to accumulator
310
311                 ;; Second 4 bytes of 8
312         
313         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
314         pxor  mm7, mm7
315         punpckhbw mm4, mm7                      
316         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
317         punpckhbw mm6, mm7
318                 
319         paddw mm4, mm6          ;  mm4 := First 4 Interpolated bytes in words
320         psrlw mm4, 1
321
322         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
323         punpckhbw mm5, mm7
324                         
325         movq  mm7,mm4
326         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
327
328         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
329         psubw mm6,mm5
330         pand  mm6, mm7
331
332         paddw mm0, mm6                          ; Add to accumulator
333
334         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
335         pcmpgtw mm6,mm4     
336         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
337         pand  mm5, mm6          
338
339         paddw mm0, mm5                          ; Add to accumulator
340
341
342                 ;;
343                 ;;      Loop termination condition... and stepping
344                 ;;              
345
346         add esi, edx            ; update pointer to next row
347         add edi, edx            ; ditto
348                         
349         sub  ecx,1
350         test ecx, ecx           ; check rowsleft
351         jnz near nextrowmm01
352                 
353
354                 ;; Sum the Accumulators
355         movq  mm4, mm0
356         psrlq mm4, 32
357         paddw mm0, mm4
358         movq  mm6, mm0
359         psrlq mm6, 16
360         paddw mm0, mm6
361         movd eax, mm0           ; store return value
362         and  eax, 0xffff
363
364         pop edi
365         pop esi 
366         pop edx                 
367         pop ecx                 
368         pop ebx                 
369
370         pop ebp                 ; restore stack pointer
371
372         emms                    ; clear mmx registers
373         ret                     ; we now return you to your regular programming
374 ;
375 ;;;  dist1_01_mmx.s:  mmx1 optimised 7bit*8 word absolute difference sum
376 ;;;     We're reduce to seven bits as otherwise we also have to mess
377 ;;;     horribly with carries and signed only comparisons make the code
378 ;;;     simply enormous (and probably barely faster than a simple loop).
379 ;;;     Since signals with a bona-fide 8bit res will be rare we simply
380 ;;;     take the precision hit...
381 ;;;     Actually we don't worry about carries from the low-order bits
382 ;;;     either so 1/4 of the time we'll be 1 too low...
383 ;;; 
384 ;  Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
385
386 ;
387 ;  This program is free software; you can redistribute it and/or
388 ;  modify it under the terms of the GNU General Public License
389 ;  as published by the Free Software Foundation; either version 2
390 ;  of the License, or (at your option) any later version.
391 ;
392 ;  This program is distributed in the hope that it will be useful,
393 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
394 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
395 ;  GNU General Public License for more details.
396 ;
397 ;  You should have received a copy of the GNU General Public License
398 ;  along with this program; if not, write to the Free Software
399 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
400 ;
401 ;
402 ;
403
404
405 global dist1_10_mmx
406
407 ; int dist1_10_mmx(unsigned char *p1,unsigned char *p2,int lx,int h);
408
409 ; esi = p1 (init:               blk1)
410 ; edi = p2 (init:               blk2)
411 ; ebx = p1+lx
412 ; ecx = rowsleft (init:  h)
413 ; edx = lx;
414
415 ; mm0 = distance accumulators (4 words)
416 ; mm1 = bytes p2
417 ; mm2 = bytes p1
418 ; mm3 = bytes p1+1
419 ; mm4 = temp 4 bytes in words interpolating p1, p1+1
420 ; mm5 = temp 4 bytes in words from p2
421 ; mm6 = temp comparison bit mask p1,p2
422 ; mm7 = temp comparison bit mask p2,p1
423
424
425 align 32
426 dist1_10_mmx:
427         push ebp                ; save stack pointer
428         mov ebp, esp    ; so that we can do this
429
430         push ebx                ; Saves registers (called saves convention in
431         push ecx                ; x86 GCC it seems)
432         push edx                ; 
433         push esi
434         push edi
435                 
436         pxor mm0, mm0                           ; zero acculumators
437
438         mov esi, [ebp+8]                        ; get p1
439         mov edi, [ebp+12]                       ; get p2
440         mov edx, [ebp+16]                       ; get lx
441         mov ecx, [ebp+20]                       ; rowsleft := h
442         mov ebx, esi
443     add ebx, edx                
444         jmp nextrowmm10                                 ; snap to it
445 align 32
446 nextrowmm10:
447
448                 ;; 
449                 ;; First 8 bytes of row
450                 ;; 
451                 
452                 ;; First 4 bytes of 8
453
454         movq mm4, [esi]             ; mm4 := first 4 bytes p1
455         pxor mm7, mm7
456         movq mm2, mm4                           ;  mm2 records all 8 bytes
457         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
458         
459         movq mm6, [ebx]                     ;  mm6 := first 4 bytes p1+lx
460         movq mm3, mm6               ;  mm3 records all 8 bytes
461         punpcklbw mm6, mm7
462         paddw mm4, mm6              ;  mm4 := First 4 bytes interpolated in words
463         psrlw mm4, 1
464                 
465         movq mm5, [edi]                         ; mm5:=first 4 bytes of p2 in words
466         movq mm1, mm5
467         punpcklbw mm5, mm7
468                         
469         movq  mm7,mm4
470         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
471
472         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
473         psubw mm6,mm5
474         pand  mm6, mm7
475
476         paddw mm0, mm6                          ; Add to accumulator
477
478         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
479         pcmpgtw mm6,mm4     
480         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
481         pand  mm5, mm6          
482
483         paddw mm0, mm5                          ; Add to accumulator
484
485                 ;; Second 4 bytes of 8
486         
487         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
488         pxor  mm7, mm7
489         punpckhbw mm4, mm7                      
490         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
491         punpckhbw mm6, mm7
492                 
493         paddw mm4, mm6          ;  mm4 := First 4 Interpolated bytes in words
494         psrlw mm4, 1
495
496         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
497         punpckhbw mm5, mm7
498                         
499         movq  mm7,mm4
500         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
501
502         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
503         psubw mm6,mm5
504         pand  mm6, mm7
505
506         paddw mm0, mm6                          ; Add to accumulator
507
508         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
509         pcmpgtw mm6,mm4     
510         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
511         pand  mm5, mm6          
512
513         paddw mm0, mm5                          ; Add to accumulator
514
515
516                 ;;
517                 ;; Second 8 bytes of row
518                 ;; 
519                 ;; First 4 bytes of 8
520
521         movq mm4, [esi+8]             ; mm4 := first 4 bytes p1+8
522         pxor mm7, mm7
523         movq mm2, mm4                           ;  mm2 records all 8 bytes
524         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
525         
526         movq mm6, [ebx+8]                       ;  mm6 := first 4 bytes p1+lx+8
527         movq mm3, mm6               ;  mm3 records all 8 bytes
528         punpcklbw mm6, mm7
529         paddw mm4, mm6              ;  mm4 := First 4 bytes interpolated in words
530         psrlw mm4, 1
531                 
532         movq mm5, [edi+8]                               ; mm5:=first 4 bytes of p2+8 in words
533         movq mm1, mm5
534         punpcklbw mm5, mm7
535                         
536         movq  mm7,mm4
537         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
538
539         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
540         psubw mm6,mm5
541         pand  mm6, mm7
542
543         paddw mm0, mm6                          ; Add to accumulator
544
545         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
546         pcmpgtw mm6,mm4     
547         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
548         pand  mm5, mm6          
549
550         paddw mm0, mm5                          ; Add to accumulator
551
552                 ;; Second 4 bytes of 8
553         
554         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
555         pxor  mm7, mm7
556         punpckhbw mm4, mm7                      
557         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
558         punpckhbw mm6, mm7
559                 
560         paddw mm4, mm6          ;  mm4 := First 4 Interpolated bytes in words
561         psrlw mm4, 1
562
563         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
564         punpckhbw mm5, mm7
565                         
566         movq  mm7,mm4
567         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
568
569         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
570         psubw mm6,mm5
571         pand  mm6, mm7
572
573         paddw mm0, mm6                          ; Add to accumulator
574
575         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
576         pcmpgtw mm6,mm4     
577         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
578         pand  mm5, mm6          
579
580         paddw mm0, mm5                          ; Add to accumulator
581
582
583                 ;;
584                 ;;      Loop termination condition... and stepping
585                 ;;              
586
587         add esi, edx            ; update pointer to next row
588         add edi, edx            ; ditto
589         add ebx, edx
590
591         sub  ecx,1
592         test ecx, ecx           ; check rowsleft
593         jnz near nextrowmm10
594                 
595                 ;; Sum the Accumulators
596         movq  mm4, mm0
597         psrlq mm4, 32
598         paddw mm0, mm4
599         movq  mm6, mm0
600         psrlq mm6, 16
601         paddw mm0, mm6
602         movd eax, mm0           ; store return value
603         and  eax, 0xffff
604
605                 
606         pop edi
607         pop esi 
608         pop edx                 
609         pop ecx                 
610         pop ebx                 
611
612         pop ebp                 ; restore stack pointer
613
614         emms                    ; clear mmx registers
615         ret                     ; we now return you to your regular programming
616 ;
617 ;;;  dist1_01_mmx.s:  
618 ;;; 
619 ;  Copyright (C) 2000 Andrew Stevens <as@comlab.ox.ac.uk>
620
621 ;
622 ;  This program is free software; you can redistribute it and/or
623 ;  modify it under the terms of the GNU General Public License
624 ;  as published by the Free Software Foundation; either version 2
625 ;  of the License, or (at your option) any later version.
626 ;
627 ;  This program is distributed in the hope that it will be useful,
628 ;  but WITHOUT ANY WARRANTY; without even the implied warranty of
629 ;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
630 ;  GNU General Public License for more details.
631 ;
632 ;  You should have received a copy of the GNU General Public License
633 ;  along with this program; if not, write to the Free Software
634 ;  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
635 ;
636 ;
637 ;
638
639
640 global dist1_11_mmx
641
642 ; int dist1_11_mmx(unsigned char *p1,unsigned char *p2,int lx,int h);
643
644 ; esi = p1 (init:               blk1)
645 ; edi = p2 (init:               blk2)
646 ; ebx = p1+lx
647 ; ecx = rowsleft (init:  h)
648 ; edx = lx;
649
650 ; mm0 = distance accumulators (4 words)
651 ; mm1 = bytes p2
652 ; mm2 = bytes p1
653 ; mm3 = bytes p1+lx
654 ; I'd love to find someplace to stash p1+1 and p1+lx+1's bytes
655 ; but I don't think thats going to happen in iA32-land...
656 ; mm4 = temp 4 bytes in words interpolating p1, p1+1
657 ; mm5 = temp 4 bytes in words from p2
658 ; mm6 = temp comparison bit mask p1,p2
659 ; mm7 = temp comparison bit mask p2,p1
660
661
662 align 32
663 dist1_11_mmx:
664         push ebp                ; save stack pointer
665         mov ebp, esp    ; so that we can do this
666
667         push ebx                ; Saves registers (called saves convention in
668         push ecx                ; x86 GCC it seems)
669         push edx                ; 
670         push esi
671         push edi
672                 
673         pxor mm0, mm0                           ; zero acculumators
674
675         mov esi, [ebp+8]                        ; get p1
676         mov edi, [ebp+12]                       ; get p2
677         mov edx, [ebp+16]                       ; get lx
678         mov ecx, [ebp+20]                       ; rowsleft := h
679         mov ebx, esi
680     add ebx, edx                
681         jmp nextrowmm11                                 ; snap to it
682 align 32
683 nextrowmm11:
684
685                 ;; 
686                 ;; First 8 bytes of row
687                 ;; 
688                 
689                 ;; First 4 bytes of 8
690
691         movq mm4, [esi]             ; mm4 := first 4 bytes p1
692         pxor mm7, mm7
693         movq mm2, mm4                           ;  mm2 records all 8 bytes
694         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
695         
696         movq mm6, [ebx]                     ;  mm6 := first 4 bytes p1+lx
697         movq mm3, mm6               ;  mm3 records all 8 bytes
698         punpcklbw mm6, mm7
699         paddw mm4, mm6              
700
701
702         movq mm5, [esi+1]                       ; mm5 := first 4 bytes p1+1
703         punpcklbw mm5, mm7            ;  First 4 bytes p1 in Words...
704         paddw mm4, mm5          
705         movq mm6, [ebx+1]           ;  mm6 := first 4 bytes p1+lx+1
706         punpcklbw mm6, mm7
707         paddw mm4, mm6
708
709         psrlw mm4, 2                ; mm4 := First 4 bytes interpolated in words
710                 
711         movq mm5, [edi]                         ; mm5:=first 4 bytes of p2 in words
712         movq mm1, mm5
713         punpcklbw mm5, mm7
714                         
715         movq  mm7,mm4
716         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
717
718         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
719         psubw mm6,mm5
720         pand  mm6, mm7
721
722         paddw mm0, mm6                          ; Add to accumulator
723
724         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
725         pcmpgtw mm6,mm4     
726         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
727         pand  mm5, mm6          
728
729         paddw mm0, mm5                          ; Add to accumulator
730
731                 ;; Second 4 bytes of 8
732         
733         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
734         pxor  mm7, mm7
735         punpckhbw mm4, mm7                      
736         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
737         punpckhbw mm6, mm7
738         paddw mm4, mm6          
739
740         movq mm5, [esi+1]                       ; mm5 := first 4 bytes p1+1
741         punpckhbw mm5, mm7          ;  First 4 bytes p1 in Words...
742         paddw mm4, mm5
743         movq mm6, [ebx+1]           ;  mm6 := first 4 bytes p1+lx+1
744         punpckhbw mm6, mm7
745         paddw mm4, mm6
746
747         psrlw mm4, 2                ; mm4 := First 4 bytes interpolated in words
748                 
749         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
750         punpckhbw mm5, mm7
751                         
752         movq  mm7,mm4
753         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
754
755         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
756         psubw mm6,mm5
757         pand  mm6, mm7
758
759         paddw mm0, mm6                          ; Add to accumulator
760
761         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
762         pcmpgtw mm6,mm4     
763         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
764         pand  mm5, mm6          
765
766         paddw mm0, mm5                          ; Add to accumulator
767
768
769                 ;;
770                 ;; Second 8 bytes of row
771                 ;; 
772                 ;; First 4 bytes of 8
773
774         movq mm4, [esi+8]             ; mm4 := first 4 bytes p1+8
775         pxor mm7, mm7
776         movq mm2, mm4                           ;  mm2 records all 8 bytes
777         punpcklbw mm4, mm7            ;  First 4 bytes p1 in Words...
778         
779         movq mm6, [ebx+8]                           ;  mm6 := first 4 bytes p1+lx+8
780         movq mm3, mm6               ;  mm3 records all 8 bytes
781         punpcklbw mm6, mm7
782         paddw mm4, mm6              
783
784
785         movq mm5, [esi+9]                       ; mm5 := first 4 bytes p1+9
786         punpcklbw mm5, mm7            ;  First 4 bytes p1 in Words...
787         paddw mm4, mm5
788         movq mm6, [ebx+9]           ;  mm6 := first 4 bytes p1+lx+9
789         punpcklbw mm6, mm7
790         paddw mm4, mm6
791
792         psrlw mm4, 2                ; mm4 := First 4 bytes interpolated in words
793                 
794         movq mm5, [edi+8]                               ; mm5:=first 4 bytes of p2+8 in words
795         movq mm1, mm5
796         punpcklbw mm5, mm7
797                         
798         movq  mm7,mm4
799         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
800
801         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
802         psubw mm6,mm5
803         pand  mm6, mm7
804
805         paddw mm0, mm6                          ; Add to accumulator
806
807         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
808         pcmpgtw mm6,mm4     
809         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
810         pand  mm5, mm6          
811
812         paddw mm0, mm5                          ; Add to accumulator
813
814                 ;; Second 4 bytes of 8
815         
816         movq mm4, mm2               ; mm4 := Second 4 bytes p1 in words
817         pxor  mm7, mm7
818         punpckhbw mm4, mm7                      
819         movq mm6, mm3                   ; mm6 := Second 4 bytes p1+1 in words  
820         punpckhbw mm6, mm7
821         paddw mm4, mm6          
822
823         movq mm5, [esi+9]                       ; mm5 := first 4 bytes p1+1
824         punpckhbw mm5, mm7          ;  First 4 bytes p1 in Words...
825         paddw mm4, mm5  
826         movq mm6, [ebx+9]           ;  mm6 := first 4 bytes p1+lx+1
827         punpckhbw mm6, mm7
828         paddw mm4, mm6
829                 
830         psrlw mm4, 2                ; mm4 := First 4 bytes interpolated in words
831
832         movq mm5, mm1                   ; mm5:= second 4 bytes of p2 in words
833         punpckhbw mm5, mm7
834                         
835         movq  mm7,mm4
836         pcmpgtw mm7,mm5         ; mm7 := [i : W0..3,mm4>mm5]
837
838         movq  mm6,mm4           ; mm6 := [i : W0..3, (mm4-mm5)*(mm4-mm5 > 0)]
839         psubw mm6,mm5
840         pand  mm6, mm7
841
842         paddw mm0, mm6                          ; Add to accumulator
843
844         movq  mm6,mm5       ; mm6 := [i : W0..3,mm5>mm4]
845         pcmpgtw mm6,mm4     
846         psubw mm5,mm4           ; mm5 := [i : B0..7, (mm5-mm4)*(mm5-mm4 > 0)]
847         pand  mm5, mm6          
848
849         paddw mm0, mm5                          ; Add to accumulator
850
851
852                 ;;
853                 ;;      Loop termination condition... and stepping
854                 ;;              
855
856         add esi, edx            ; update pointer to next row
857         add edi, edx            ; ditto
858         add ebx, edx
859
860         sub  ecx,1
861         test ecx, ecx           ; check rowsleft
862         jnz near nextrowmm11
863                 
864                 ;; Sum the Accumulators
865         movq  mm4, mm0
866         psrlq mm4, 32
867         paddw mm0, mm4
868         movq  mm6, mm0
869         psrlq mm6, 16
870         paddw mm0, mm6
871         movd eax, mm0           ; store return value
872         and  eax, 0xffff
873                 
874         pop edi
875         pop esi 
876         pop edx                 
877         pop ecx                 
878         pop ebx                 
879
880         pop ebp                 ; restore stack pointer
881
882         emms                    ; clear mmx registers
883         ret                     ; we now return you to your regular programming
884
885
886 global dist22_mmx
887
888 ; int dist22_mmx(unsigned char *blk1,unsigned char *blk2,int lx,int h);
889
890 ; eax = p1 (init:               blk1)
891 ; ebx = p2 (init:                blk2)
892 ; ecx = rowsleft (init:  h)
893 ; edx = lx;
894
895 ; mm0 = distance accumulators (4 words)
896 ; mm1 = temp 
897 ; mm2 = temp 
898 ; mm3 = temp
899 ; mm4 = temp
900 ; mm5 = temp 
901 ; mm6 = 0
902 ; mm7 = temp
903
904
905 align 32
906 dist22_mmx:
907         push ebp                ; save stack pointer
908         mov ebp, esp    ; so that we can do this
909
910         push ebx                ; Saves registers (called saves convention in
911         push ecx                ; x86 GCC it seems)
912         push edx                ; 
913
914         pxor mm0, mm0                           ; zero acculumators
915         pxor mm6, mm6
916         mov eax, [ebp+8]                        ; get p1
917         mov ebx, [ebp+12]                       ; get p2
918         mov edx, [ebp+16]                       ; get lx
919
920         mov  ecx, [ebp+20]                      ; get rowsleft
921
922         jmp nextrow                                     ; snap to it
923 align 32
924 nextrow:
925         movq mm4, [eax]         ; load 8 bytes of p1 
926         movq mm5, [ebx]         ; load 8 bytes of p2
927                 
928         movq mm7, mm4       ; mm5 = abs(*p1-*p2)
929         psubusb mm7, mm5
930         psubusb mm5, mm4
931         add eax, edx            ; update pointer to next row
932         paddb   mm5,mm7 
933
934                 ;;  Add the mm5 bytes to the accumulatores
935         movq  mm7,mm5                   
936         punpcklbw mm7,mm6
937         paddw mm0, mm7
938         punpckhbw mm5,mm6
939         add ebx, edx            ; update pointer to next row
940         paddw mm0, mm5
941         
942         movq mm4, [eax]         ; load 8 bytes of p1 (next row) 
943         movq mm5, [ebx]         ; load 8 bytes of p2 (next row)
944                 
945         movq mm7, mm4       ; mm5 = abs(*p1-*p2)
946         psubusb mm7, mm5
947         psubusb mm5, mm4
948         add eax, edx            ; update pointer to next row
949         paddb   mm5,mm7 
950
951                 ;;  Add the mm5 bytes to the accumulatores
952         movq  mm7,mm5                           
953         punpcklbw mm7,mm6
954         add ebx, edx            ; update pointer to next row
955         paddw mm0, mm7              
956         punpckhbw mm5,mm6
957         sub  ecx,2
958         paddw mm0, mm5
959
960
961         jnz nextrow
962
963                 ;; Sum the Accumulators
964         movq  mm1, mm0
965         psrlq mm1, 16
966         movq  mm2, mm0
967         psrlq mm2, 32
968         movq  mm3, mm0
969         psrlq mm3, 48
970         paddw mm0, mm1
971         paddw mm2, mm3
972         paddw mm0, mm2
973                 
974         movd eax, mm0           ; store return value
975         and  eax, 0xffff
976         
977         pop edx                 ; pop pop
978         pop ecx                 ; fizz fizz
979         pop ebx                 ; ia86 needs a fizz instruction
980
981         pop ebp                 ; restore stack pointer
982
983         emms                    ; clear mmx registers
984         ret                     ; we now return you to your regular programming
985
986
987
988
989 global dist44_mmx
990
991 ; int dist44_mmx(unsigned char *blk1,unsigned char *blk2,int qlx,int qh);
992
993 ; eax = p1
994 ; ebx = p2
995 ; ecx = temp
996 ; edx = qlx;
997 ; esi = rowsleft
998
999 ; mm0 = distance accumulator left block p1
1000 ; mm1 = distance accumulator right block p1
1001 ; mm2 = 0
1002 ; mm3 = right block of p1
1003 ; mm4 = left block of p1
1004 ; mm5 = p2
1005 ; mm6 = temp
1006 ; mm7 = temp
1007
1008 align 32
1009 dist44_mmx:
1010         push ebp                ; save stack pointer
1011         mov ebp, esp            ; so that we can do this
1012
1013         push ebx
1014         push ecx
1015         push edx
1016         push esi     
1017
1018         pxor mm0, mm0           ; zero acculumator
1019         pxor mm1, mm1
1020         pxor mm2, mm2
1021         mov eax, [ebp+8]        ; get p1
1022         mov ebx, [ebp+12]       ; get p2
1023         mov edx, [ebp+16]       ; get qlx
1024         mov esi, [ebp+20]       ; get rowsleft
1025         jmp nextrowqd           ; snap to it
1026 align 32
1027 nextrowqd:
1028
1029                 ;;
1030                 ;; Beware loop obfuscated by interleaving to try to
1031                 ;; hide latencies...
1032                 ;; 
1033         movq mm4, [eax]                         ; mm4 =  first 4 bytes of p1 in words
1034         movq mm5, [ebx]             ; mm5 = 4 bytes of p2 in words
1035         movq mm3, mm4
1036         punpcklbw mm4, mm2                      
1037         punpcklbw mm5, mm2
1038         
1039         movq mm7, mm4
1040         movq mm6, mm5
1041         psubusw mm7, mm5
1042         psubusw mm6, mm4
1043         
1044         add eax, edx                    ; update a pointer to next row
1045 ;       punpckhbw mm3, mm2                      ; mm3 = 2nd 4 bytes of p1 in words
1046
1047         paddw   mm7, mm6
1048         paddw mm0, mm7                          ; Add absolute differences to left block accumulators
1049                 
1050 ;       movq mm7,mm3
1051 ;       psubusw mm7, mm5
1052 ;       psubusw mm5, mm3
1053
1054         add ebx, edx            ; update a pointer to next row
1055         sub   esi, 1
1056
1057 ;       paddw   mm7, mm5
1058 ;       paddw mm1, mm7                          ; Add absolute differences to right block accumulators
1059         
1060
1061                 
1062         jnz nextrowqd           
1063
1064                 ;;              Sum the accumulators
1065
1066         movq  mm4, mm0
1067         psrlq mm4, 32
1068         paddw mm0, mm4
1069         movq  mm6, mm0
1070         psrlq mm6, 16
1071         paddw mm0, mm6
1072         movd eax, mm0           ; store return value
1073
1074 ;       movq  mm4, mm1
1075 ;       psrlq mm4, 32
1076 ;       paddw mm1, mm4
1077 ;       movq  mm6, mm1
1078 ;       psrlq mm6, 16
1079 ;       paddw mm1, mm6
1080 ;       movd ebx, mm1
1081
1082         and  eax, 0xffff                
1083 ;       sal  ebx, 16
1084 ;       or   eax, ebx
1085                 
1086         pop esi
1087         pop edx
1088         pop ecx
1089         pop ebx
1090
1091         pop ebp                 ; restore stack pointer
1092
1093         emms                    ; clear mmx registers
1094         ret                     ; we now return you to your regular programming