Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_edgea.s (17166B)


      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
     11 Ltemp:					.long	0
     12 float_1_div_0100000h:	.long	0x35800000	// 1.0/(float)0x100000
     13 float_point_999:		.single	0.999
     14 float_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)
     24 C(R_EdgeCodeStart):
     25 
     26 .globl C(R_InsertNewEdges)
     27 C(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 
     34 LDoNextEdge:
     35 	movl	et_u(%edx),%eax
     36 	movl	%edx,%edi
     37 
     38 LContinueSearch:
     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 
     56 LAddedge2:
     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
     70 LAddedge:
     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 
     81 LDone:
     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)
     93 C(R_RemoveEdges):
     94 	pushl	%ebx
     95 	movl	predge(%esp),%eax
     96 
     97 Lre_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 
    117 Lre_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)
    129 C(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 
    137 LNewEdge:
    138 	movl	et_u(%esi),%edi
    139 
    140 LNextEdge:
    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 
    173 LPushBack2:
    174 	movl	%edx,%ebx
    175 	movl	%edi,%eax
    176 	movl	%esi,%edx
    177 	movl	%ebx,%esi
    178 
    179 LPushBack:
    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
    194 LPushBackLoop:
    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
    208 LPushBackFound:
    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 
    221 LUDone:
    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
    233 TrailingEdge:
    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
    241 LPatch0:
    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 
    275 LNoEmit2:
    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 
    284 LNoEmit:
    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 
    292 LInverted:
    293 	movl	%eax,st_spanstate(%esi)
    294 	ret
    295 
    296 //--------------------------------------------------------------------
    297 
    298 // trailing edge only
    299 Lgs_trailing:
    300 	pushl	$Lgs_nextedge
    301 	jmp		TrailingEdge
    302 
    303 
    304 .globl C(R_GenerateSpans)
    305 C(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 
    329 Lgs_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 
    352 Lgs_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;
    357 LPatch2:
    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);
    386 Lsortloopnb:
    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
    397 Lbmodel_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);
    427 Lsortloop:
    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 
    515 Lgotposition_fpop3:
    516 	fstp	%st(0)
    517 Lgotposition_fpop2:
    518 	fstp	%st(0)
    519 	fstp	%st(0)
    520 	jmp		LInsertAndExit
    521 
    522 
    523 // emit a span (obscures current top)
    524 
    525 Lnewtop_fpop3:
    526 	fstp	%st(0)
    527 Lnewtop_fpop2:
    528 	fstp	%st(0)
    529 	fstp	%st(0)
    530 	movl	st_key(%edi),%eax		// reload the sorting key
    531 
    532 Lnewtop:
    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 
    551 LInsertAndExit:
    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 
    567 Lgs_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
    573 Lgs_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
    578 LPatch3:
    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
    595 Lgs_resetspanstate:
    596 	movl	%ecx,st_spanstate(%esi)
    597 	movl	st_next(%esi),%esi
    598 	cmpl	$0x12345678,%esi		// &surfaces[1]
    599 LPatch4:
    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
    616 Lxl_done:
    617 	incl	%edx
    618 	movl	%edx,st_spanstate(%edi)
    619 
    620 	jmp		Lgs_nextedge
    621 
    622 
    623 	.align	4
    624 Lzcheck_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 
    698 Lsortloop_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)
    706 C(R_EdgeCodeEnd):
    707 
    708 
    709 //----------------------------------------------------------------------
    710 // Surface array address code patching routine
    711 //----------------------------------------------------------------------
    712 
    713 	.align 4
    714 .globl C(R_SurfacePatch)
    715 C(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