This commit was manufactured by cvs2svn to create branch 'gomp-branch'.
[official-gcc.git] / zlib / contrib / asm386 / gvmat32.asm
blob28d527f47f885e4cd957e1c2559f0ef74697b5cd
2 ; gvmat32.asm -- Asm portion of the optimized longest_match for 32 bits x86
3 ; Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
4 ; File written by Gilles Vollant, by modifiying the longest_match
5 ; from Jean-loup Gailly in deflate.c
6 ; It need wmask == 0x7fff
7 ; (assembly code is faster with a fixed wmask)
9 ; For Visual C++ 4.2 and ML 6.11c (version in directory \MASM611C of Win95 DDK)
10 ; I compile with : "ml /coff /Zi /c gvmat32.asm"
13 ;uInt longest_match_7fff(s, cur_match)
14 ; deflate_state *s;
15 ; IPos cur_match; /* current match */
17 NbStack equ 76
18 cur_match equ dword ptr[esp+NbStack-0]
19 str_s equ dword ptr[esp+NbStack-4]
20 ; 5 dword on top (ret,ebp,esi,edi,ebx)
21 adrret equ dword ptr[esp+NbStack-8]
22 pushebp equ dword ptr[esp+NbStack-12]
23 pushedi equ dword ptr[esp+NbStack-16]
24 pushesi equ dword ptr[esp+NbStack-20]
25 pushebx equ dword ptr[esp+NbStack-24]
27 chain_length equ dword ptr [esp+NbStack-28]
28 limit equ dword ptr [esp+NbStack-32]
29 best_len equ dword ptr [esp+NbStack-36]
30 window equ dword ptr [esp+NbStack-40]
31 prev equ dword ptr [esp+NbStack-44]
32 scan_start equ word ptr [esp+NbStack-48]
33 wmask equ dword ptr [esp+NbStack-52]
34 match_start_ptr equ dword ptr [esp+NbStack-56]
35 nice_match equ dword ptr [esp+NbStack-60]
36 scan equ dword ptr [esp+NbStack-64]
38 windowlen equ dword ptr [esp+NbStack-68]
39 match_start equ dword ptr [esp+NbStack-72]
40 strend equ dword ptr [esp+NbStack-76]
41 NbStackAdd equ (NbStack-24)
43 .386p
45 name gvmatch
46 .MODEL FLAT
50 ; all the +4 offsets are due to the addition of pending_buf_size (in zlib
51 ; in the deflate_state structure since the asm code was first written
52 ; (if you compile with zlib 1.0.4 or older, remove the +4).
53 ; Note : these value are good with a 8 bytes boundary pack structure
54 dep_chain_length equ 70h+4
55 dep_window equ 2ch+4
56 dep_strstart equ 60h+4
57 dep_prev_length equ 6ch+4
58 dep_nice_match equ 84h+4
59 dep_w_size equ 20h+4
60 dep_prev equ 34h+4
61 dep_w_mask equ 28h+4
62 dep_good_match equ 80h+4
63 dep_match_start equ 64h+4
64 dep_lookahead equ 68h+4
67 _TEXT segment
69 IFDEF NOUNDERLINE
70 public longest_match_7fff
71 ; public match_init
72 ELSE
73 public _longest_match_7fff
74 ; public _match_init
75 ENDIF
77 MAX_MATCH equ 258
78 MIN_MATCH equ 3
79 MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
83 IFDEF NOUNDERLINE
84 ;match_init proc near
85 ; ret
86 ;match_init endp
87 ELSE
88 ;_match_init proc near
89 ; ret
90 ;_match_init endp
91 ENDIF
94 IFDEF NOUNDERLINE
95 longest_match_7fff proc near
96 ELSE
97 _longest_match_7fff proc near
98 ENDIF
100 mov edx,[esp+4]
104 push ebp
105 push edi
106 push esi
107 push ebx
109 sub esp,NbStackAdd
111 ; initialize or check the variables used in match.asm.
112 mov ebp,edx
114 ; chain_length = s->max_chain_length
115 ; if (prev_length>=good_match) chain_length >>= 2
116 mov edx,[ebp+dep_chain_length]
117 mov ebx,[ebp+dep_prev_length]
118 cmp [ebp+dep_good_match],ebx
119 ja noshr
120 shr edx,2
121 noshr:
122 ; we increment chain_length because in the asm, the --chain_lenght is in the beginning of the loop
123 inc edx
124 mov edi,[ebp+dep_nice_match]
125 mov chain_length,edx
126 mov eax,[ebp+dep_lookahead]
127 cmp eax,edi
128 ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
129 jae nolookaheadnicematch
130 mov edi,eax
131 nolookaheadnicematch:
132 ; best_len = s->prev_length
133 mov best_len,ebx
135 ; window = s->window
136 mov esi,[ebp+dep_window]
137 mov ecx,[ebp+dep_strstart]
138 mov window,esi
140 mov nice_match,edi
141 ; scan = window + strstart
142 add esi,ecx
143 mov scan,esi
144 ; dx = *window
145 mov dx,word ptr [esi]
146 ; bx = *(window+best_len-1)
147 mov bx,word ptr [esi+ebx-1]
148 add esi,MAX_MATCH-1
149 ; scan_start = *scan
150 mov scan_start,dx
151 ; strend = scan + MAX_MATCH-1
152 mov strend,esi
153 ; bx = scan_end = *(window+best_len-1)
155 ; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
156 ; s->strstart - (IPos)MAX_DIST(s) : NIL;
158 mov esi,[ebp+dep_w_size]
159 sub esi,MIN_LOOKAHEAD
160 ; here esi = MAX_DIST(s)
161 sub ecx,esi
162 ja nodist
163 xor ecx,ecx
164 nodist:
165 mov limit,ecx
167 ; prev = s->prev
168 mov edx,[ebp+dep_prev]
169 mov prev,edx
172 mov edx,dword ptr [ebp+dep_match_start]
173 mov bp,scan_start
174 mov eax,cur_match
175 mov match_start,edx
177 mov edx,window
178 mov edi,edx
179 add edi,best_len
180 mov esi,prev
181 dec edi
182 ; windowlen = window + best_len -1
183 mov windowlen,edi
185 jmp beginloop2
186 align 4
188 ; here, in the loop
189 ; eax = ax = cur_match
190 ; ecx = limit
191 ; bx = scan_end
192 ; bp = scan_start
193 ; edi = windowlen (window + best_len -1)
194 ; esi = prev
197 ;// here; chain_length <=16
198 normalbeg0add16:
199 add chain_length,16
200 jz exitloop
201 normalbeg0:
202 cmp word ptr[edi+eax],bx
203 je normalbeg2noroll
204 rcontlabnoroll:
205 ; cur_match = prev[cur_match & wmask]
206 and eax,7fffh
207 mov ax,word ptr[esi+eax*2]
208 ; if cur_match > limit, go to exitloop
209 cmp ecx,eax
210 jnb exitloop
211 ; if --chain_length != 0, go to exitloop
212 dec chain_length
213 jnz normalbeg0
214 jmp exitloop
216 normalbeg2noroll:
217 ; if (scan_start==*(cur_match+window)) goto normalbeg2
218 cmp bp,word ptr[edx+eax]
219 jne rcontlabnoroll
220 jmp normalbeg2
222 contloop3:
223 mov edi,windowlen
225 ; cur_match = prev[cur_match & wmask]
226 and eax,7fffh
227 mov ax,word ptr[esi+eax*2]
228 ; if cur_match > limit, go to exitloop
229 cmp ecx,eax
230 jnbexitloopshort1:
231 jnb exitloop
232 ; if --chain_length != 0, go to exitloop
235 ; begin the main loop
236 beginloop2:
237 sub chain_length,16+1
238 ; if chain_length <=16, don't use the unrolled loop
239 jna normalbeg0add16
241 do16:
242 cmp word ptr[edi+eax],bx
243 je normalbeg2dc0
245 maccn MACRO lab
246 and eax,7fffh
247 mov ax,word ptr[esi+eax*2]
248 cmp ecx,eax
249 jnb exitloop
250 cmp word ptr[edi+eax],bx
251 je lab
252 ENDM
254 rcontloop0:
255 maccn normalbeg2dc1
257 rcontloop1:
258 maccn normalbeg2dc2
260 rcontloop2:
261 maccn normalbeg2dc3
263 rcontloop3:
264 maccn normalbeg2dc4
266 rcontloop4:
267 maccn normalbeg2dc5
269 rcontloop5:
270 maccn normalbeg2dc6
272 rcontloop6:
273 maccn normalbeg2dc7
275 rcontloop7:
276 maccn normalbeg2dc8
278 rcontloop8:
279 maccn normalbeg2dc9
281 rcontloop9:
282 maccn normalbeg2dc10
284 rcontloop10:
285 maccn short normalbeg2dc11
287 rcontloop11:
288 maccn short normalbeg2dc12
290 rcontloop12:
291 maccn short normalbeg2dc13
293 rcontloop13:
294 maccn short normalbeg2dc14
296 rcontloop14:
297 maccn short normalbeg2dc15
299 rcontloop15:
300 and eax,7fffh
301 mov ax,word ptr[esi+eax*2]
302 cmp ecx,eax
303 jnb exitloop
305 sub chain_length,16
306 ja do16
307 jmp normalbeg0add16
309 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
311 normbeg MACRO rcontlab,valsub
312 ; if we are here, we know that *(match+best_len-1) == scan_end
313 cmp bp,word ptr[edx+eax]
314 ; if (match != scan_start) goto rcontlab
315 jne rcontlab
316 ; calculate the good chain_length, and we'll compare scan and match string
317 add chain_length,16-valsub
318 jmp iseq
319 ENDM
322 normalbeg2dc11:
323 normbeg rcontloop11,11
325 normalbeg2dc12:
326 normbeg short rcontloop12,12
328 normalbeg2dc13:
329 normbeg short rcontloop13,13
331 normalbeg2dc14:
332 normbeg short rcontloop14,14
334 normalbeg2dc15:
335 normbeg short rcontloop15,15
337 normalbeg2dc10:
338 normbeg rcontloop10,10
340 normalbeg2dc9:
341 normbeg rcontloop9,9
343 normalbeg2dc8:
344 normbeg rcontloop8,8
346 normalbeg2dc7:
347 normbeg rcontloop7,7
349 normalbeg2dc6:
350 normbeg rcontloop6,6
352 normalbeg2dc5:
353 normbeg rcontloop5,5
355 normalbeg2dc4:
356 normbeg rcontloop4,4
358 normalbeg2dc3:
359 normbeg rcontloop3,3
361 normalbeg2dc2:
362 normbeg rcontloop2,2
364 normalbeg2dc1:
365 normbeg rcontloop1,1
367 normalbeg2dc0:
368 normbeg rcontloop0,0
371 ; we go in normalbeg2 because *(ushf*)(match+best_len-1) == scan_end
373 normalbeg2:
374 mov edi,window
376 cmp bp,word ptr[edi+eax]
377 jne contloop3 ; if *(ushf*)match != scan_start, continue
379 iseq:
380 ; if we are here, we know that *(match+best_len-1) == scan_end
381 ; and (match == scan_start)
383 mov edi,edx
384 mov esi,scan ; esi = scan
385 add edi,eax ; edi = window + cur_match = match
387 mov edx,[esi+3] ; compare manually dword at match+3
388 xor edx,[edi+3] ; and scan +3
390 jz begincompare ; if equal, go to long compare
392 ; we will determine the unmatch byte and calculate len (in esi)
393 or dl,dl
394 je eq1rr
395 mov esi,3
396 jmp trfinval
397 eq1rr:
398 or dx,dx
399 je eq1
401 mov esi,4
402 jmp trfinval
403 eq1:
404 and edx,0ffffffh
405 jz eq11
406 mov esi,5
407 jmp trfinval
408 eq11:
409 mov esi,6
410 jmp trfinval
412 begincompare:
413 ; here we now scan and match begin same
414 add edi,6
415 add esi,6
416 mov ecx,(MAX_MATCH-(2+4))/4 ; scan for at most MAX_MATCH bytes
417 repe cmpsd ; loop until mismatch
419 je trfin ; go to trfin if not unmatch
420 ; we determine the unmatch byte
421 sub esi,4
422 mov edx,[edi-4]
423 xor edx,[esi]
425 or dl,dl
426 jnz trfin
427 inc esi
429 or dx,dx
430 jnz trfin
431 inc esi
433 and edx,0ffffffh
434 jnz trfin
435 inc esi
437 trfin:
438 sub esi,scan ; esi = len
439 trfinval:
440 ; here we have finised compare, and esi contain len of equal string
441 cmp esi,best_len ; if len > best_len, go newbestlen
442 ja short newbestlen
443 ; now we restore edx, ecx and esi, for the big loop
444 mov esi,prev
445 mov ecx,limit
446 mov edx,window
447 jmp contloop3
449 newbestlen:
450 mov best_len,esi ; len become best_len
452 mov match_start,eax ; save new position as match_start
453 cmp esi,nice_match ; if best_len >= nice_match, exit
454 jae exitloop
455 mov ecx,scan
456 mov edx,window ; restore edx=window
457 add ecx,esi
458 add esi,edx
460 dec esi
461 mov windowlen,esi ; windowlen = window + best_len-1
462 mov bx,[ecx-1] ; bx = *(scan+best_len-1) = scan_end
464 ; now we restore ecx and esi, for the big loop :
465 mov esi,prev
466 mov ecx,limit
467 jmp contloop3
469 exitloop:
470 ; exit : s->match_start=match_start
471 mov ebx,match_start
472 mov ebp,str_s
473 mov ecx,best_len
474 mov dword ptr [ebp+dep_match_start],ebx
475 mov eax,dword ptr [ebp+dep_lookahead]
476 cmp ecx,eax
477 ja minexlo
478 mov eax,ecx
479 minexlo:
480 ; return min(best_len,s->lookahead)
482 ; restore stack and register ebx,esi,edi,ebp
483 add esp,NbStackAdd
485 pop ebx
486 pop esi
487 pop edi
488 pop ebp
490 InfoAuthor:
491 ; please don't remove this string !
492 ; Your are free use gvmat32 in any fre or commercial apps if you don't remove the string in the binary!
493 db 0dh,0ah,"GVMat32 optimised assembly code written 1996-98 by Gilles Vollant",0dh,0ah
497 IFDEF NOUNDERLINE
498 longest_match_7fff endp
499 ELSE
500 _longest_match_7fff endp
501 ENDIF
504 IFDEF NOUNDERLINE
505 cpudetect32 proc near
506 ELSE
507 _cpudetect32 proc near
508 ENDIF
511 pushfd ; push original EFLAGS
512 pop eax ; get original EFLAGS
513 mov ecx, eax ; save original EFLAGS
514 xor eax, 40000h ; flip AC bit in EFLAGS
515 push eax ; save new EFLAGS value on stack
516 popfd ; replace current EFLAGS value
517 pushfd ; get new EFLAGS
518 pop eax ; store new EFLAGS in EAX
519 xor eax, ecx ; can’t toggle AC bit, processor=80386
520 jz end_cpu_is_386 ; jump if 80386 processor
521 push ecx
522 popfd ; restore AC bit in EFLAGS first
524 pushfd
525 pushfd
526 pop ecx
528 mov eax, ecx ; get original EFLAGS
529 xor eax, 200000h ; flip ID bit in EFLAGS
530 push eax ; save new EFLAGS value on stack
531 popfd ; replace current EFLAGS value
532 pushfd ; get new EFLAGS
533 pop eax ; store new EFLAGS in EAX
534 popfd ; restore original EFLAGS
535 xor eax, ecx ; can’t toggle ID bit,
536 je is_old_486 ; processor=old
538 mov eax,1
539 db 0fh,0a2h ;CPUID
541 exitcpudetect:
544 end_cpu_is_386:
545 mov eax,0300h
546 jmp exitcpudetect
548 is_old_486:
549 mov eax,0400h
550 jmp exitcpudetect
552 IFDEF NOUNDERLINE
553 cpudetect32 endp
554 ELSE
555 _cpudetect32 endp
556 ENDIF
558 _TEXT ends