1//
2// r_edgea.s
3// x86 assembly-language edge-processing code.
4//
5
6#include "qasm.h"
7
8#if	id386
9
10	.data
11Ltemp:					.long	0
12float_1_div_0100000h:	.long	0x35800000	// 1.0/(float)0x100000
13float_point_999:		.single	0.999
14float_1_point_001:		.single	1.001
15
16	.text
17
18//--------------------------------------------------------------------
19
20#define edgestoadd	4+8		// note odd stack offsets because of interleaving
21#define edgelist	8+12	// with pushes
22
23.globl C(R_EdgeCodeStart)
24C(R_EdgeCodeStart):
25
26.globl C(R_InsertNewEdges)
27C(R_InsertNewEdges):
28	pushl	%edi
29	pushl	%esi				// preserve register variables
30	movl	edgestoadd(%esp),%edx
31	pushl	%ebx
32	movl	edgelist(%esp),%ecx
33
34LDoNextEdge:
35	movl	et_u(%edx),%eax
36	movl	%edx,%edi
37
38LContinueSearch:
39	movl	et_u(%ecx),%ebx
40	movl	et_next(%ecx),%esi
41	cmpl	%ebx,%eax
42	jle		LAddedge
43	movl	et_u(%esi),%ebx
44	movl	et_next(%esi),%ecx
45	cmpl	%ebx,%eax
46	jle		LAddedge2
47	movl	et_u(%ecx),%ebx
48	movl	et_next(%ecx),%esi
49	cmpl	%ebx,%eax
50	jle		LAddedge
51	movl	et_u(%esi),%ebx
52	movl	et_next(%esi),%ecx
53	cmpl	%ebx,%eax
54	jg		LContinueSearch
55
56LAddedge2:
57	movl	et_next(%edx),%edx
58	movl	et_prev(%esi),%ebx
59	movl	%esi,et_next(%edi)
60	movl	%ebx,et_prev(%edi)
61	movl	%edi,et_next(%ebx)
62	movl	%edi,et_prev(%esi)
63	movl	%esi,%ecx
64
65	cmpl	$0,%edx
66	jnz		LDoNextEdge
67	jmp		LDone
68
69	.align 4
70LAddedge:
71	movl	et_next(%edx),%edx
72	movl	et_prev(%ecx),%ebx
73	movl	%ecx,et_next(%edi)
74	movl	%ebx,et_prev(%edi)
75	movl	%edi,et_next(%ebx)
76	movl	%edi,et_prev(%ecx)
77
78	cmpl	$0,%edx
79	jnz		LDoNextEdge
80
81LDone:
82	popl	%ebx				// restore register variables
83	popl	%esi
84	popl	%edi
85
86	ret
87
88//--------------------------------------------------------------------
89
90#define predge	4+4
91
92.globl C(R_RemoveEdges)
93C(R_RemoveEdges):
94	pushl	%ebx
95	movl	predge(%esp),%eax
96
97Lre_loop:
98	movl	et_next(%eax),%ecx
99	movl	et_nextremove(%eax),%ebx
100	movl	et_prev(%eax),%edx
101	testl	%ebx,%ebx
102	movl	%edx,et_prev(%ecx)
103	jz		Lre_done
104	movl	%ecx,et_next(%edx)
105
106	movl	et_next(%ebx),%ecx
107	movl	et_prev(%ebx),%edx
108	movl	et_nextremove(%ebx),%eax
109	movl	%edx,et_prev(%ecx)
110	testl	%eax,%eax
111	movl	%ecx,et_next(%edx)
112	jnz		Lre_loop
113
114	popl	%ebx
115	ret
116
117Lre_done:
118	movl	%ecx,et_next(%edx)
119	popl	%ebx
120
121	ret
122
123//--------------------------------------------------------------------
124
125#define pedgelist	4+4		// note odd stack offset because of interleaving
126							// with pushes
127
128.globl C(R_StepActiveU)
129C(R_StepActiveU):
130	pushl	%edi
131	movl	pedgelist(%esp),%edx
132	pushl	%esi				// preserve register variables
133	pushl	%ebx
134
135	movl	et_prev(%edx),%esi
136
137LNewEdge:
138	movl	et_u(%esi),%edi
139
140LNextEdge:
141	movl	et_u(%edx),%eax
142	movl	et_u_step(%edx),%ebx
143	addl	%ebx,%eax
144	movl	et_next(%edx),%esi
145	movl	%eax,et_u(%edx)
146	cmpl	%edi,%eax
147	jl		LPushBack
148
149	movl	et_u(%esi),%edi
150	movl	et_u_step(%esi),%ebx
151	addl	%ebx,%edi
152	movl	et_next(%esi),%edx
153	movl	%edi,et_u(%esi)
154	cmpl	%eax,%edi
155	jl		LPushBack2
156
157	movl	et_u(%edx),%eax
158	movl	et_u_step(%edx),%ebx
159	addl	%ebx,%eax
160	movl	et_next(%edx),%esi
161	movl	%eax,et_u(%edx)
162	cmpl	%edi,%eax
163	jl		LPushBack
164
165	movl	et_u(%esi),%edi
166	movl	et_u_step(%esi),%ebx
167	addl	%ebx,%edi
168	movl	et_next(%esi),%edx
169	movl	%edi,et_u(%esi)
170	cmpl	%eax,%edi
171	jnl		LNextEdge
172
173LPushBack2:
174	movl	%edx,%ebx
175	movl	%edi,%eax
176	movl	%esi,%edx
177	movl	%ebx,%esi
178
179LPushBack:
180// push it back to keep it sorted
181	movl	et_prev(%edx),%ecx
182	movl	et_next(%edx),%ebx
183
184// done if the -1 in edge_aftertail triggered this
185	cmpl	$(C(edge_aftertail)),%edx
186	jz		LUDone
187
188// pull the edge out of the edge list
189	movl	et_prev(%ecx),%edi
190	movl	%ecx,et_prev(%esi)
191	movl	%ebx,et_next(%ecx)
192
193// find out where the edge goes in the edge list
194LPushBackLoop:
195	movl	et_prev(%edi),%ecx
196	movl	et_u(%edi),%ebx
197	cmpl	%ebx,%eax
198	jnl		LPushBackFound
199
200	movl	et_prev(%ecx),%edi
201	movl	et_u(%ecx),%ebx
202	cmpl	%ebx,%eax
203	jl		LPushBackLoop
204
205	movl	%ecx,%edi
206
207// put the edge back into the edge list
208LPushBackFound:
209	movl	et_next(%edi),%ebx
210	movl	%edi,et_prev(%edx)
211	movl	%ebx,et_next(%edx)
212	movl	%edx,et_next(%edi)
213	movl	%edx,et_prev(%ebx)
214
215	movl	%esi,%edx
216	movl	et_prev(%esi),%esi
217
218	cmpl	$(C(edge_tail)),%edx
219	jnz		LNewEdge
220
221LUDone:
222	popl	%ebx				// restore register variables
223	popl	%esi
224	popl	%edi
225
226	ret
227
228//--------------------------------------------------------------------
229
230#define surf	4		// note this is loaded before any pushes
231
232	.align 4
233TrailingEdge:
234	movl	st_spanstate(%esi),%eax	// check for edge inversion
235	decl	%eax
236	jnz		LInverted
237
238	movl	%eax,st_spanstate(%esi)
239	movl	st_insubmodel(%esi),%ecx
240	movl	0x12345678,%edx		// surfaces[1].st_next
241LPatch0:
242	movl	C(r_bmodelactive),%eax
243	subl	%ecx,%eax
244	cmpl	%esi,%edx
245	movl	%eax,C(r_bmodelactive)
246	jnz		LNoEmit				// surface isn't on top, just remove
247
248// emit a span (current top going away)
249	movl	et_u(%ebx),%eax
250	shrl	$20,%eax				// iu = integral pixel u
251	movl	st_last_u(%esi),%edx
252	movl	st_next(%esi),%ecx
253	cmpl	%edx,%eax
254	jle		LNoEmit2				// iu <= surf->last_u, so nothing to emit
255
256	movl	%eax,st_last_u(%ecx)	// surf->next->last_u = iu;
257	subl	%edx,%eax
258	movl	%edx,espan_t_u(%ebp)		// span->u = surf->last_u;
259
260	movl	%eax,espan_t_count(%ebp)	// span->count = iu - span->u;
261	movl	C(current_iv),%eax
262	movl	%eax,espan_t_v(%ebp)		// span->v = current_iv;
263	movl	st_spans(%esi),%eax
264	movl	%eax,espan_t_pnext(%ebp)	// span->pnext = surf->spans;
265	movl	%ebp,st_spans(%esi)			// surf->spans = span;
266	addl	$(espan_t_size),%ebp
267
268	movl	st_next(%esi),%edx		// remove the surface from the surface
269	movl	st_prev(%esi),%esi		// stack
270
271	movl	%edx,st_next(%esi)
272	movl	%esi,st_prev(%edx)
273	ret
274
275LNoEmit2:
276	movl	%eax,st_last_u(%ecx)	// surf->next->last_u = iu;
277	movl	st_next(%esi),%edx		// remove the surface from the surface
278	movl	st_prev(%esi),%esi		// stack
279
280	movl	%edx,st_next(%esi)
281	movl	%esi,st_prev(%edx)
282	ret
283
284LNoEmit:
285	movl	st_next(%esi),%edx		// remove the surface from the surface
286	movl	st_prev(%esi),%esi		// stack
287
288	movl	%edx,st_next(%esi)
289	movl	%esi,st_prev(%edx)
290	ret
291
292LInverted:
293	movl	%eax,st_spanstate(%esi)
294	ret
295
296//--------------------------------------------------------------------
297
298// trailing edge only
299Lgs_trailing:
300	pushl	$Lgs_nextedge
301	jmp		TrailingEdge
302
303
304.globl C(R_GenerateSpans)
305C(R_GenerateSpans):
306	pushl	%ebp				// preserve caller's stack frame
307	pushl	%edi
308	pushl	%esi				// preserve register variables
309	pushl	%ebx
310
311// clear active surfaces to just the background surface
312	movl	C(surfaces),%eax
313	movl	C(edge_head_u_shift20),%edx
314	addl	$(st_size),%eax
315// %ebp = span_p throughout
316	movl	C(span_p),%ebp
317
318	movl	$0,C(r_bmodelactive)
319
320	movl	%eax,st_next(%eax)
321	movl	%eax,st_prev(%eax)
322	movl	%edx,st_last_u(%eax)
323	movl	C(edge_head)+et_next,%ebx		// edge=edge_head.next
324
325// generate spans
326	cmpl	$(C(edge_tail)),%ebx		// done if empty list
327	jz		Lgs_lastspan
328
329Lgs_edgeloop:
330
331	movl	et_surfs(%ebx),%edi
332	movl	C(surfaces),%eax
333	movl	%edi,%esi
334	andl	$0xFFFF0000,%edi
335	andl	$0xFFFF,%esi
336	jz		Lgs_leading		// not a trailing edge
337
338// it has a left surface, so a surface is going away for this span
339	shll	$(SURF_T_SHIFT),%esi
340	addl	%eax,%esi
341	testl	%edi,%edi
342	jz		Lgs_trailing
343
344// both leading and trailing
345	call	TrailingEdge
346	movl	C(surfaces),%eax
347
348// ---------------------------------------------------------------
349// handle a leading edge
350// ---------------------------------------------------------------
351
352Lgs_leading:
353	shrl	$16-SURF_T_SHIFT,%edi
354	movl	C(surfaces),%eax
355	addl	%eax,%edi
356	movl	0x12345678,%esi		// surf2 = surfaces[1].next;
357LPatch2:
358	movl	st_spanstate(%edi),%edx
359	movl	st_insubmodel(%edi),%eax
360	testl	%eax,%eax
361	jnz		Lbmodel_leading
362
363// handle a leading non-bmodel edge
364
365// don't start a span if this is an inverted span, with the end edge preceding
366// the start edge (that is, we've already seen the end edge)
367	testl	%edx,%edx
368	jnz		Lxl_done
369
370
371// if (surf->key < surf2->key)
372//		goto newtop;
373	incl	%edx
374	movl	st_key(%edi),%eax
375	movl	%edx,st_spanstate(%edi)
376	movl	st_key(%esi),%ecx
377	cmpl	%ecx,%eax
378	jl		Lnewtop
379
380// main sorting loop to search through surface stack until insertion point
381// found. Always terminates because background surface is sentinel
382// do
383// {
384// 		surf2 = surf2->next;
385// } while (surf->key >= surf2->key);
386Lsortloopnb:
387	movl	st_next(%esi),%esi
388	movl	st_key(%esi),%ecx
389	cmpl	%ecx,%eax
390	jge		Lsortloopnb
391
392	jmp		LInsertAndExit
393
394
395// handle a leading bmodel edge
396	.align	4
397Lbmodel_leading:
398
399// don't start a span if this is an inverted span, with the end edge preceding
400// the start edge (that is, we've already seen the end edge)
401	testl	%edx,%edx
402	jnz		Lxl_done
403
404	movl	C(r_bmodelactive),%ecx
405	incl	%edx
406	incl	%ecx
407	movl	%edx,st_spanstate(%edi)
408	movl	%ecx,C(r_bmodelactive)
409
410// if (surf->key < surf2->key)
411//		goto newtop;
412	movl	st_key(%edi),%eax
413	movl	st_key(%esi),%ecx
414	cmpl	%ecx,%eax
415	jl		Lnewtop
416
417// if ((surf->key == surf2->key) && surf->insubmodel)
418// {
419	jz		Lzcheck_for_newtop
420
421// main sorting loop to search through surface stack until insertion point
422// found. Always terminates because background surface is sentinel
423// do
424// {
425// 		surf2 = surf2->next;
426// } while (surf->key > surf2->key);
427Lsortloop:
428	movl	st_next(%esi),%esi
429	movl	st_key(%esi),%ecx
430	cmpl	%ecx,%eax
431	jg		Lsortloop
432
433	jne		LInsertAndExit
434
435// Do 1/z sorting to see if we've arrived in the right position
436	movl	et_u(%ebx),%eax
437	subl	$0xFFFFF,%eax
438	movl	%eax,Ltemp
439	fildl	Ltemp
440
441	fmuls	float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
442								//      (1.0 / 0x100000);
443
444	fld		%st(0)				// fu | fu
445	fmuls	st_d_zistepu(%edi)	// fu*surf->d_zistepu | fu
446	flds	C(fv)					// fv | fu*surf->d_zistepu | fu
447	fmuls	st_d_zistepv(%edi)	// fv*surf->d_zistepv | fu*surf->d_zistepu | fu
448	fxch	%st(1)				// fu*surf->d_zistepu | fv*surf->d_zistepv | fu
449	fadds	st_d_ziorigin(%edi)	// fu*surf->d_zistepu + surf->d_ziorigin |
450								//  fv*surf->d_zistepv | fu
451
452	flds	st_d_zistepu(%esi)	// surf2->d_zistepu |
453								//  fu*surf->d_zistepu + surf->d_ziorigin |
454								//  fv*surf->d_zistepv | fu
455	fmul	%st(3),%st(0)		// fu*surf2->d_zistepu |
456								//  fu*surf->d_zistepu + surf->d_ziorigin |
457								//  fv*surf->d_zistepv | fu
458	fxch	%st(1)				// fu*surf->d_zistepu + surf->d_ziorigin |
459								//  fu*surf2->d_zistepu |
460								//  fv*surf->d_zistepv | fu
461	faddp	%st(0),%st(2)		// fu*surf2->d_zistepu | newzi | fu
462
463	flds	C(fv)					// fv | fu*surf2->d_zistepu | newzi | fu
464	fmuls	st_d_zistepv(%esi)	// fv*surf2->d_zistepv |
465								//  fu*surf2->d_zistepu | newzi | fu
466	fld		%st(2)				// newzi | fv*surf2->d_zistepv |
467								//  fu*surf2->d_zistepu | newzi | fu
468	fmuls	float_point_999		// newzibottom | fv*surf2->d_zistepv |
469								//  fu*surf2->d_zistepu | newzi | fu
470
471	fxch	%st(2)				// fu*surf2->d_zistepu | fv*surf2->d_zistepv |
472								//  newzibottom | newzi | fu
473	fadds	st_d_ziorigin(%esi)	// fu*surf2->d_zistepu + surf2->d_ziorigin |
474								//  fv*surf2->d_zistepv | newzibottom | newzi |
475								//  fu
476	faddp	%st(0),%st(1)		// testzi | newzibottom | newzi | fu
477	fxch	%st(1)				// newzibottom | testzi | newzi | fu
478
479// if (newzibottom >= testzi)
480//     goto Lgotposition;
481
482	fcomp	%st(1)				// testzi | newzi | fu
483
484	fxch	%st(1)				// newzi | testzi | fu
485	fmuls	float_1_point_001	// newzitop | testzi | fu
486	fxch	%st(1)				// testzi | newzitop | fu
487
488	fnstsw	%ax
489	testb	$0x01,%ah
490	jz		Lgotposition_fpop3
491
492// if (newzitop >= testzi)
493// {
494
495	fcomp	%st(1)				// newzitop | fu
496	fnstsw	%ax
497	testb	$0x45,%ah
498	jz		Lsortloop_fpop2
499
500// if (surf->d_zistepu >= surf2->d_zistepu)
501//     goto newtop;
502
503	flds	st_d_zistepu(%edi)	// surf->d_zistepu | newzitop| fu
504	fcomps	st_d_zistepu(%esi)	// newzitop | fu
505	fnstsw	%ax
506	testb	$0x01,%ah
507	jz		Lgotposition_fpop2
508
509	fstp	%st(0)				// clear the FPstack
510	fstp	%st(0)
511	movl	st_key(%edi),%eax
512	jmp		Lsortloop
513
514
515Lgotposition_fpop3:
516	fstp	%st(0)
517Lgotposition_fpop2:
518	fstp	%st(0)
519	fstp	%st(0)
520	jmp		LInsertAndExit
521
522
523// emit a span (obscures current top)
524
525Lnewtop_fpop3:
526	fstp	%st(0)
527Lnewtop_fpop2:
528	fstp	%st(0)
529	fstp	%st(0)
530	movl	st_key(%edi),%eax		// reload the sorting key
531
532Lnewtop:
533	movl	et_u(%ebx),%eax
534	movl	st_last_u(%esi),%edx
535	shrl	$20,%eax				// iu = integral pixel u
536	movl	%eax,st_last_u(%edi)	// surf->last_u = iu;
537	cmpl	%edx,%eax
538	jle		LInsertAndExit			// iu <= surf->last_u, so nothing to emit
539
540	subl	%edx,%eax
541	movl	%edx,espan_t_u(%ebp)		// span->u = surf->last_u;
542
543	movl	%eax,espan_t_count(%ebp)	// span->count = iu - span->u;
544	movl	C(current_iv),%eax
545	movl	%eax,espan_t_v(%ebp)		// span->v = current_iv;
546	movl	st_spans(%esi),%eax
547	movl	%eax,espan_t_pnext(%ebp)	// span->pnext = surf->spans;
548	movl	%ebp,st_spans(%esi)			// surf->spans = span;
549	addl	$(espan_t_size),%ebp
550
551LInsertAndExit:
552// insert before surf2
553	movl	%esi,st_next(%edi)		// surf->next = surf2;
554	movl	st_prev(%esi),%eax
555	movl	%eax,st_prev(%edi)		// surf->prev = surf2->prev;
556	movl	%edi,st_prev(%esi)		// surf2->prev = surf;
557	movl	%edi,st_next(%eax)		// surf2->prev->next = surf;
558
559// ---------------------------------------------------------------
560// leading edge done
561// ---------------------------------------------------------------
562
563// ---------------------------------------------------------------
564// see if there are any more edges
565// ---------------------------------------------------------------
566
567Lgs_nextedge:
568	movl	et_next(%ebx),%ebx
569	cmpl	$(C(edge_tail)),%ebx
570	jnz		Lgs_edgeloop
571
572// clean up at the right edge
573Lgs_lastspan:
574
575// now that we've reached the right edge of the screen, we're done with any
576// unfinished surfaces, so emit a span for whatever's on top
577	movl	0x12345678,%esi		// surfaces[1].st_next
578LPatch3:
579	movl	C(edge_tail_u_shift20),%eax
580	xorl	%ecx,%ecx
581	movl	st_last_u(%esi),%edx
582	subl	%edx,%eax
583	jle		Lgs_resetspanstate
584
585	movl	%edx,espan_t_u(%ebp)
586	movl	%eax,espan_t_count(%ebp)
587	movl	C(current_iv),%eax
588	movl	%eax,espan_t_v(%ebp)
589	movl	st_spans(%esi),%eax
590	movl	%eax,espan_t_pnext(%ebp)
591	movl	%ebp,st_spans(%esi)
592	addl	$(espan_t_size),%ebp
593
594// reset spanstate for all surfaces in the surface stack
595Lgs_resetspanstate:
596	movl	%ecx,st_spanstate(%esi)
597	movl	st_next(%esi),%esi
598	cmpl	$0x12345678,%esi		// &surfaces[1]
599LPatch4:
600	jnz		Lgs_resetspanstate
601
602// store the final span_p
603	movl	%ebp,C(span_p)
604
605	popl	%ebx				// restore register variables
606	popl	%esi
607	popl	%edi
608	popl	%ebp				// restore the caller's stack frame
609	ret
610
611
612// ---------------------------------------------------------------
613// 1/z sorting for bmodels in the same leaf
614// ---------------------------------------------------------------
615	.align	4
616Lxl_done:
617	incl	%edx
618	movl	%edx,st_spanstate(%edi)
619
620	jmp		Lgs_nextedge
621
622
623	.align	4
624Lzcheck_for_newtop:
625	movl	et_u(%ebx),%eax
626	subl	$0xFFFFF,%eax
627	movl	%eax,Ltemp
628	fildl	Ltemp
629
630	fmuls	float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
631								//      (1.0 / 0x100000);
632
633	fld		%st(0)				// fu | fu
634	fmuls	st_d_zistepu(%edi)	// fu*surf->d_zistepu | fu
635	flds	C(fv)				// fv | fu*surf->d_zistepu | fu
636	fmuls	st_d_zistepv(%edi)	// fv*surf->d_zistepv | fu*surf->d_zistepu | fu
637	fxch	%st(1)				// fu*surf->d_zistepu | fv*surf->d_zistepv | fu
638	fadds	st_d_ziorigin(%edi)	// fu*surf->d_zistepu + surf->d_ziorigin |
639								//  fv*surf->d_zistepv | fu
640
641	flds	st_d_zistepu(%esi)	// surf2->d_zistepu |
642								//  fu*surf->d_zistepu + surf->d_ziorigin |
643								//  fv*surf->d_zistepv | fu
644	fmul	%st(3),%st(0)		// fu*surf2->d_zistepu |
645								//  fu*surf->d_zistepu + surf->d_ziorigin |
646								//  fv*surf->d_zistepv | fu
647	fxch	%st(1)				// fu*surf->d_zistepu + surf->d_ziorigin |
648								//  fu*surf2->d_zistepu |
649								//  fv*surf->d_zistepv | fu
650	faddp	%st(0),%st(2)		// fu*surf2->d_zistepu | newzi | fu
651
652	flds	C(fv)				// fv | fu*surf2->d_zistepu | newzi | fu
653	fmuls	st_d_zistepv(%esi)	// fv*surf2->d_zistepv |
654								//  fu*surf2->d_zistepu | newzi | fu
655	fld		%st(2)				// newzi | fv*surf2->d_zistepv |
656								//  fu*surf2->d_zistepu | newzi | fu
657	fmuls	float_point_999		// newzibottom | fv*surf2->d_zistepv |
658								//  fu*surf2->d_zistepu | newzi | fu
659
660	fxch	%st(2)				// fu*surf2->d_zistepu | fv*surf2->d_zistepv |
661								//  newzibottom | newzi | fu
662	fadds	st_d_ziorigin(%esi)	// fu*surf2->d_zistepu + surf2->d_ziorigin |
663								//  fv*surf2->d_zistepv | newzibottom | newzi |
664								//  fu
665	faddp	%st(0),%st(1)		// testzi | newzibottom | newzi | fu
666	fxch	%st(1)				// newzibottom | testzi | newzi | fu
667
668// if (newzibottom >= testzi)
669//     goto newtop;
670
671	fcomp	%st(1)				// testzi | newzi | fu
672
673	fxch	%st(1)				// newzi | testzi | fu
674	fmuls	float_1_point_001	// newzitop | testzi | fu
675	fxch	%st(1)				// testzi | newzitop | fu
676
677	fnstsw	%ax
678	testb	$0x01,%ah
679	jz		Lnewtop_fpop3
680
681// if (newzitop >= testzi)
682// {
683
684	fcomp	%st(1)				// newzitop | fu
685	fnstsw	%ax
686	testb	$0x45,%ah
687	jz		Lsortloop_fpop2
688
689// if (surf->d_zistepu >= surf2->d_zistepu)
690//     goto newtop;
691
692	flds	st_d_zistepu(%edi)	// surf->d_zistepu | newzitop | fu
693	fcomps	st_d_zistepu(%esi)	// newzitop | fu
694	fnstsw	%ax
695	testb	$0x01,%ah
696	jz		Lnewtop_fpop2
697
698Lsortloop_fpop2:
699	fstp	%st(0)				// clear the FP stack
700	fstp	%st(0)
701	movl	st_key(%edi),%eax
702	jmp		Lsortloop
703
704
705.globl C(R_EdgeCodeEnd)
706C(R_EdgeCodeEnd):
707
708
709//----------------------------------------------------------------------
710// Surface array address code patching routine
711//----------------------------------------------------------------------
712
713	.align 4
714.globl C(R_SurfacePatch)
715C(R_SurfacePatch):
716
717	movl	C(surfaces),%eax
718	addl	$(st_size),%eax
719	movl	%eax,LPatch4-4
720
721	addl	$(st_next),%eax
722	movl	%eax,LPatch0-4
723	movl	%eax,LPatch2-4
724	movl	%eax,LPatch3-4
725
726	ret
727
728#endif	// id386
729
730