Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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