Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

r_drawa.s (18134B)


      1 //
      2 // r_drawa.s
      3 // x86 assembly-language edge clipping and emission code
      4 //
      5 
      6 #include "qasm.h"
      7 #include "d_ifacea.h"
      8 
      9 #if	id386
     10 
     11 // !!! if these are changed, they must be changed in r_draw.c too !!!
     12 #define FULLY_CLIPPED_CACHED	0x80000000
     13 #define FRAMECOUNT_MASK			0x7FFFFFFF
     14 
     15 	.data
     16 
     17 Ld0:			.single		0.0
     18 Ld1:			.single		0.0
     19 Lstack:			.long		0
     20 Lfp_near_clip:	.single		NEAR_CLIP
     21 Lceilv0:		.long		0
     22 Lv:				.long		0
     23 Lu0:			.long		0
     24 Lv0:			.long		0
     25 Lzi0:			.long		0
     26 
     27 	.text
     28 
     29 //----------------------------------------------------------------------
     30 // edge clipping code
     31 //----------------------------------------------------------------------
     32 
     33 #define pv0		4+12
     34 #define pv1		8+12
     35 #define clip	12+12
     36 
     37 	.align 4
     38 .globl C(R_ClipEdge)
     39 C(R_ClipEdge):
     40 	pushl	%esi				// preserve register variables
     41 	pushl	%edi
     42 	pushl	%ebx
     43 	movl	%esp,Lstack			// for clearing the stack later
     44 
     45 //	float		d0, d1, f;
     46 //	mvertex_t	clipvert;
     47 
     48 	movl	clip(%esp),%ebx
     49 	movl	pv0(%esp),%esi
     50 	movl	pv1(%esp),%edx
     51 
     52 //	if (clip)
     53 //	{
     54 	testl	%ebx,%ebx
     55 	jz		Lemit
     56 
     57 //		do
     58 //		{
     59 
     60 Lcliploop:
     61 
     62 //			d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
     63 //			d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
     64 	flds	mv_position+0(%esi)
     65 	fmuls	cp_normal+0(%ebx)
     66 	flds	mv_position+4(%esi)
     67 	fmuls	cp_normal+4(%ebx)
     68 	flds	mv_position+8(%esi)
     69 	fmuls	cp_normal+8(%ebx)
     70 	fxch	%st(1)
     71 	faddp	%st(0),%st(2)		// d0mul2 | d0add0
     72 
     73 	flds	mv_position+0(%edx)
     74 	fmuls	cp_normal+0(%ebx)
     75 	flds	mv_position+4(%edx)
     76 	fmuls	cp_normal+4(%ebx)
     77 	flds	mv_position+8(%edx)
     78 	fmuls	cp_normal+8(%ebx)
     79 	fxch	%st(1)
     80 	faddp	%st(0),%st(2)		// d1mul2 | d1add0 | d0mul2 | d0add0
     81 	fxch	%st(3)				// d0add0 | d1add0 | d0mul2 | d1mul2
     82 
     83 	faddp	%st(0),%st(2)		// d1add0 | dot0 | d1mul2 
     84 	faddp	%st(0),%st(2)		// dot0 | dot1
     85 
     86 	fsubs	cp_dist(%ebx)		// d0 | dot1
     87 	fxch	%st(1)				// dot1 | d0
     88 	fsubs	cp_dist(%ebx)		// d1 | d0
     89 	fxch	%st(1)
     90 	fstps	Ld0
     91 	fstps	Ld1
     92 
     93 //			if (d0 >= 0)
     94 //			{
     95 	movl	Ld0,%eax
     96 	movl	Ld1,%ecx
     97 	orl		%eax,%ecx
     98 	js		Lp2
     99 
    100 // both points are unclipped
    101 
    102 Lcontinue:
    103 
    104 //
    105 //				R_ClipEdge (&clipvert, pv1, clip->next);
    106 //				return;
    107 //			}
    108 //		} while ((clip = clip->next) != NULL);
    109 	movl	cp_next(%ebx),%ebx
    110 	testl	%ebx,%ebx
    111 	jnz		Lcliploop
    112 
    113 //	}
    114 
    115 //// add the edge
    116 //	R_EmitEdge (pv0, pv1);
    117 Lemit:
    118 
    119 //
    120 // set integer rounding to ceil mode, set to single precision
    121 //
    122 // FIXME: do away with by manually extracting integers from floats?
    123 // FIXME: set less often
    124 	fldcw	ceil_cw
    125 
    126 //	edge_t	*edge, *pcheck;
    127 //	int		u_check;
    128 //	float	u, u_step;
    129 //	vec3_t	local, transformed;
    130 //	float	*world;
    131 //	int		v, v2, ceilv0;
    132 //	float	scale, lzi0, u0, v0;
    133 //	int		side;
    134 
    135 //	if (r_lastvertvalid)
    136 //	{
    137 	cmpl	$0,C(r_lastvertvalid)
    138 	jz		LCalcFirst
    139 
    140 //		u0 = r_u1;
    141 //		v0 = r_v1;
    142 //		lzi0 = r_lzi1;
    143 //		ceilv0 = r_ceilv1;
    144 	movl	C(r_lzi1),%eax
    145 	movl	C(r_u1),%ecx
    146 	movl	%eax,Lzi0
    147 	movl	%ecx,Lu0
    148 	movl	C(r_v1),%ecx
    149 	movl	C(r_ceilv1),%eax
    150 	movl	%ecx,Lv0
    151 	movl	%eax,Lceilv0
    152 	jmp		LCalcSecond
    153 
    154 //	}
    155 
    156 LCalcFirst:
    157 
    158 //	else
    159 //	{
    160 //		world = &pv0->position[0];
    161 
    162 	call	LTransformAndProject	// v0 | lzi0 | u0
    163 
    164 	fsts	Lv0
    165 	fxch	%st(2)					// u0 | lzi0 | v0
    166 	fstps	Lu0						// lzi0 | v0
    167 	fstps	Lzi0					// v0
    168 
    169 //		ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
    170 	fistpl	Lceilv0
    171 
    172 //	}
    173 
    174 LCalcSecond:
    175 
    176 //	world = &pv1->position[0];
    177 	movl	%edx,%esi
    178 
    179 	call	LTransformAndProject	// v1 | lzi1 | u1
    180 
    181 	flds	Lu0						// u0 | v1 | lzi1 | u1
    182 	fxch	%st(3)					// u1 | v1 | lzi1 | u0
    183 	flds	Lzi0					// lzi0 | u1 | v1 | lzi1 | u0
    184 	fxch	%st(3)					// lzi1 | u1 | v1 | lzi0 | u0
    185 	flds	Lv0						// v0 | lzi1 | u1 | v1 | lzi0 | u0
    186 	fxch	%st(3)					// v1 | lzi1 | u1 | v0 | lzi0 | u0
    187 
    188 //	r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
    189 	fistl	C(r_ceilv1)
    190 
    191 	fldcw	single_cw				// put back normal floating-point state
    192 
    193 	fsts	C(r_v1)
    194 	fxch	%st(4)					// lzi0 | lzi1 | u1 | v0 | v1 | u0
    195 
    196 //	if (r_lzi1 > lzi0)
    197 //		lzi0 = r_lzi1;
    198 	fcom	%st(1)
    199 	fnstsw	%ax
    200 	testb	$1,%ah
    201 	jz		LP0
    202 	fstp	%st(0)
    203 	fld		%st(0)
    204 LP0:
    205 
    206 	fxch	%st(1)					// lzi1 | lzi0 | u1 | v0 | v1 | u0
    207 	fstps	C(r_lzi1)				// lzi0 | u1 | v0 | v1 | u0
    208 	fxch	%st(1)
    209 	fsts	C(r_u1)
    210 	fxch	%st(1)
    211 
    212 //	if (lzi0 > r_nearzi)	// for mipmap finding
    213 //		r_nearzi = lzi0;
    214 	fcoms	C(r_nearzi)
    215 	fnstsw	%ax
    216 	testb	$0x45,%ah
    217 	jnz		LP1
    218 	fsts	C(r_nearzi)
    219 LP1:
    220 
    221 // // for right edges, all we want is the effect on 1/z
    222 //	if (r_nearzionly)
    223 //		return;
    224 	movl	C(r_nearzionly),%eax
    225 	testl	%eax,%eax
    226 	jz		LP2
    227 LPop5AndDone:
    228 	movl	C(cacheoffset),%eax
    229 	movl	C(r_framecount),%edx
    230 	cmpl	$0x7FFFFFFF,%eax
    231 	jz		LDoPop
    232 	andl	$(FRAMECOUNT_MASK),%edx
    233 	orl		$(FULLY_CLIPPED_CACHED),%edx
    234 	movl	%edx,C(cacheoffset)
    235 
    236 LDoPop:
    237 	fstp	%st(0)			// u1 | v0 | v1 | u0
    238 	fstp	%st(0)			// v0 | v1 | u0
    239 	fstp	%st(0)			// v1 | u0
    240 	fstp	%st(0)			// u0
    241 	fstp	%st(0)
    242 	jmp		Ldone
    243 
    244 LP2:
    245 
    246 // // create the edge
    247 //	if (ceilv0 == r_ceilv1)
    248 //		return;		// horizontal edge
    249 	movl	Lceilv0,%ebx
    250 	movl	C(edge_p),%edi
    251 	movl	C(r_ceilv1),%ecx
    252 	movl	%edi,%edx
    253 	movl	C(r_pedge),%esi
    254 	addl	$(et_size),%edx
    255 	cmpl	%ecx,%ebx
    256 	jz		LPop5AndDone
    257 
    258 	movl	C(r_pedge),%eax
    259 	movl	%eax,et_owner(%edi)
    260 
    261 //	side = ceilv0 > r_ceilv1;
    262 //
    263 //	edge->nearzi = lzi0;
    264 	fstps	et_nearzi(%edi)		// u1 | v0 | v1 | u0
    265 
    266 //	if (side == 1)
    267 //	{
    268 	jc		LSide0
    269 
    270 LSide1:
    271 
    272 //	// leading edge (go from p2 to p1)
    273 
    274 //		u_step = ((u0 - r_u1) / (v0 - r_v1));
    275 	fsubrp	%st(0),%st(3)		// v0 | v1 | u0-u1
    276 	fsub	%st(1),%st(0)		// v0-v1 | v1 | u0-u1
    277 	fdivrp	%st(0),%st(2)		// v1 | ustep
    278 
    279 //	r_emitted = 1;
    280 	movl	$1,C(r_emitted)
    281 
    282 //	edge = edge_p++;
    283 	movl	%edx,C(edge_p)
    284 
    285 // pretouch next edge
    286 	movl	(%edx),%eax
    287 
    288 //		v2 = ceilv0 - 1;
    289 //		v = r_ceilv1;
    290 	movl	%ecx,%eax
    291 	leal	-1(%ebx),%ecx
    292 	movl	%eax,%ebx
    293 
    294 //		edge->surfs[0] = 0;
    295 //		edge->surfs[1] = surface_p - surfaces;
    296 	movl	C(surface_p),%eax
    297 	movl	C(surfaces),%esi
    298 	subl	%edx,%edx
    299 	subl	%esi,%eax
    300 	shrl	$(SURF_T_SHIFT),%eax
    301 	movl	%edx,et_surfs(%edi)
    302 	movl	%eax,et_surfs+2(%edi)
    303 
    304 	subl	%esi,%esi
    305 
    306 //		u = r_u1 + ((float)v - r_v1) * u_step;
    307 	movl	%ebx,Lv
    308 	fildl	Lv					// v | v1 | ustep
    309 	fsubp	%st(0),%st(1)		// v-v1 | ustep
    310 	fmul	%st(1),%st(0)		// (v-v1)*ustep | ustep
    311 	fadds	C(r_u1)				// u | ustep
    312 
    313 	jmp		LSideDone
    314 
    315 //	}
    316 
    317 LSide0:
    318 
    319 //	else
    320 //	{
    321 //	// trailing edge (go from p1 to p2)
    322 
    323 //		u_step = ((r_u1 - u0) / (r_v1 - v0));
    324 	fsub	%st(3),%st(0)		// u1-u0 | v0 | v1 | u0
    325 	fxch	%st(2)				// v1 | v0 | u1-u0 | u0
    326 	fsub	%st(1),%st(0)		// v1-v0 | v0 | u1-u0 | u0
    327 	fdivrp	%st(0),%st(2)		// v0 | ustep | u0
    328 
    329 //	r_emitted = 1;
    330 	movl	$1,C(r_emitted)
    331 
    332 //	edge = edge_p++;
    333 	movl	%edx,C(edge_p)
    334 
    335 // pretouch next edge
    336 	movl	(%edx),%eax
    337 
    338 //		v = ceilv0;
    339 //		v2 = r_ceilv1 - 1;
    340 	decl	%ecx
    341 
    342 //		edge->surfs[0] = surface_p - surfaces;
    343 //		edge->surfs[1] = 0;
    344 	movl	C(surface_p),%eax
    345 	movl	C(surfaces),%esi
    346 	subl	%edx,%edx
    347 	subl	%esi,%eax
    348 	shrl	$(SURF_T_SHIFT),%eax
    349 	movl	%edx,et_surfs+2(%edi)
    350 	movl	%eax,et_surfs(%edi)
    351 
    352 	movl	$1,%esi
    353 
    354 //		u = u0 + ((float)v - v0) * u_step;
    355 	movl	%ebx,Lv
    356 	fildl	Lv					// v | v0 | ustep | u0
    357 	fsubp	%st(0),%st(1)		// v-v0 | ustep | u0
    358 	fmul	%st(1),%st(0)		// (v-v0)*ustep | ustep | u0
    359 	faddp	%st(0),%st(2)		// ustep | u
    360 	fxch	%st(1)				// u | ustep
    361 
    362 //	}
    363 
    364 LSideDone:
    365 
    366 //	edge->u_step = u_step*0x100000;
    367 //	edge->u = u*0x100000 + 0xFFFFF;
    368 
    369 	fmuls	fp_1m				// u*0x100000 | ustep
    370 	fxch	%st(1)				// ustep | u*0x100000
    371 	fmuls	fp_1m				// ustep*0x100000 | u*0x100000
    372 	fxch	%st(1)				// u*0x100000 | ustep*0x100000
    373 	fadds	fp_1m_minus_1		// u*0x100000 + 0xFFFFF | ustep*0x100000
    374 	fxch	%st(1)				// ustep*0x100000 | u*0x100000 + 0xFFFFF
    375 	fistpl	et_u_step(%edi)		// u*0x100000 + 0xFFFFF
    376 	fistpl	et_u(%edi)
    377 
    378 // // we need to do this to avoid stepping off the edges if a very nearly
    379 // // horizontal edge is less than epsilon above a scan, and numeric error
    380 // // causes it to incorrectly extend to the scan, and the extension of the
    381 // // line goes off the edge of the screen
    382 // // FIXME: is this actually needed?
    383 //	if (edge->u < r_refdef.vrect_x_adj_shift20)
    384 //		edge->u = r_refdef.vrect_x_adj_shift20;
    385 //	if (edge->u > r_refdef.vrectright_adj_shift20)
    386 //		edge->u = r_refdef.vrectright_adj_shift20;
    387 	movl	et_u(%edi),%eax
    388 	movl	C(r_refdef)+rd_vrect_x_adj_shift20,%edx
    389 	cmpl	%edx,%eax
    390 	jl		LP4
    391 	movl	C(r_refdef)+rd_vrectright_adj_shift20,%edx
    392 	cmpl	%edx,%eax
    393 	jng		LP5
    394 LP4:
    395 	movl	%edx,et_u(%edi)
    396 	movl	%edx,%eax
    397 LP5:
    398 
    399 // // sort the edge in normally
    400 //	u_check = edge->u;
    401 //
    402 //	if (edge->surfs[0])
    403 //		u_check++;	// sort trailers after leaders
    404 	addl	%esi,%eax
    405 
    406 //	if (!newedges[v] || newedges[v]->u >= u_check)
    407 //	{
    408 	movl	C(newedges)(,%ebx,4),%esi
    409 	testl	%esi,%esi
    410 	jz		LDoFirst
    411 	cmpl	%eax,et_u(%esi)
    412 	jl		LNotFirst
    413 LDoFirst:
    414 
    415 //		edge->next = newedges[v];
    416 //		newedges[v] = edge;
    417 	movl	%esi,et_next(%edi)
    418 	movl	%edi,C(newedges)(,%ebx,4)
    419 
    420 	jmp		LSetRemove
    421 
    422 //	}
    423 
    424 LNotFirst:
    425 
    426 //	else
    427 //	{
    428 //		pcheck = newedges[v];
    429 //
    430 //		while (pcheck->next && pcheck->next->u < u_check)
    431 //			pcheck = pcheck->next;
    432 LFindInsertLoop:
    433 	movl	%esi,%edx
    434 	movl	et_next(%esi),%esi
    435 	testl	%esi,%esi
    436 	jz		LInsertFound
    437 	cmpl	%eax,et_u(%esi)
    438 	jl		LFindInsertLoop
    439 
    440 LInsertFound:
    441 
    442 //		edge->next = pcheck->next;
    443 //		pcheck->next = edge;
    444 	movl	%esi,et_next(%edi)
    445 	movl	%edi,et_next(%edx)
    446 
    447 //	}
    448 
    449 LSetRemove:
    450 
    451 //	edge->nextremove = removeedges[v2];
    452 //	removeedges[v2] = edge;
    453 	movl	C(removeedges)(,%ecx,4),%eax
    454 	movl	%edi,C(removeedges)(,%ecx,4)
    455 	movl	%eax,et_nextremove(%edi)
    456 
    457 Ldone:
    458 	movl	Lstack,%esp			// clear temporary variables from stack
    459 
    460 	popl	%ebx				// restore register variables
    461 	popl	%edi
    462 	popl	%esi
    463 	ret
    464 
    465 // at least one point is clipped
    466 
    467 Lp2:
    468 	testl	%eax,%eax
    469 	jns		Lp1
    470 
    471 //			else
    472 //			{
    473 //			// point 0 is clipped
    474 
    475 //				if (d1 < 0)
    476 //				{
    477 	movl	Ld1,%eax
    478 	testl	%eax,%eax
    479 	jns		Lp3
    480 
    481 //				// both points are clipped
    482 //				// we do cache fully clipped edges
    483 //					if (!leftclipped)
    484 	movl	C(r_leftclipped),%eax
    485 	movl	C(r_pedge),%ecx
    486 	testl	%eax,%eax
    487 	jnz		Ldone
    488 
    489 //						r_pedge->framecount = r_framecount;
    490 	movl	C(r_framecount),%eax
    491 	andl	$(FRAMECOUNT_MASK),%eax
    492 	orl		$(FULLY_CLIPPED_CACHED),%eax
    493 	movl	%eax,C(cacheoffset)
    494 
    495 //					return;
    496 	jmp		Ldone
    497 
    498 //				}
    499 
    500 Lp1:
    501 
    502 //			// point 0 is unclipped
    503 //				if (d1 >= 0)
    504 //				{
    505 //				// both points are unclipped
    506 //					continue;
    507 
    508 //			// only point 1 is clipped
    509 
    510 //				f = d0 / (d0 - d1);
    511 	flds	Ld0
    512 	flds	Ld1
    513 	fsubr	%st(1),%st(0)
    514 
    515 //			// we don't cache partially clipped edges
    516 	movl	$0x7FFFFFFF,C(cacheoffset)
    517 
    518 	fdivrp	%st(0),%st(1)
    519 
    520 	subl	$(mv_size),%esp			// allocate space for clipvert
    521 
    522 //				clipvert.position[0] = pv0->position[0] +
    523 //						f * (pv1->position[0] - pv0->position[0]);
    524 //				clipvert.position[1] = pv0->position[1] +
    525 //						f * (pv1->position[1] - pv0->position[1]);
    526 //				clipvert.position[2] = pv0->position[2] +
    527 //						f * (pv1->position[2] - pv0->position[2]);
    528 	flds	mv_position+8(%edx)
    529 	fsubs	mv_position+8(%esi)
    530 	flds	mv_position+4(%edx)
    531 	fsubs	mv_position+4(%esi)
    532 	flds	mv_position+0(%edx)
    533 	fsubs	mv_position+0(%esi)		// 0 | 1 | 2
    534 
    535 // replace pv1 with the clip point
    536 	movl	%esp,%edx
    537 	movl	cp_leftedge(%ebx),%eax
    538 	testb	%al,%al
    539 
    540 	fmul	%st(3),%st(0)
    541 	fxch	%st(1)					// 1 | 0 | 2
    542 	fmul	%st(3),%st(0)
    543 	fxch	%st(2)					// 2 | 0 | 1
    544 	fmulp	%st(0),%st(3)			// 0 | 1 | 2
    545 	fadds	mv_position+0(%esi)
    546 	fxch	%st(1)					// 1 | 0 | 2
    547 	fadds	mv_position+4(%esi)
    548 	fxch	%st(2)					// 2 | 0 | 1
    549 	fadds	mv_position+8(%esi)
    550 	fxch	%st(1)					// 0 | 2 | 1
    551 	fstps	mv_position+0(%esp)		// 2 | 1
    552 	fstps	mv_position+8(%esp)		// 1
    553 	fstps	mv_position+4(%esp)
    554 
    555 //				if (clip->leftedge)
    556 //				{
    557 	jz		Ltestright
    558 
    559 //					r_leftclipped = true;
    560 //					r_leftexit = clipvert;
    561 	movl	$1,C(r_leftclipped)
    562 	movl	mv_position+0(%esp),%eax
    563 	movl	%eax,C(r_leftexit)+mv_position+0
    564 	movl	mv_position+4(%esp),%eax
    565 	movl	%eax,C(r_leftexit)+mv_position+4
    566 	movl	mv_position+8(%esp),%eax
    567 	movl	%eax,C(r_leftexit)+mv_position+8
    568 
    569 	jmp		Lcontinue
    570 
    571 //				}
    572 
    573 Ltestright:
    574 //				else if (clip->rightedge)
    575 //				{
    576 	testb	%ah,%ah
    577 	jz		Lcontinue
    578 
    579 //					r_rightclipped = true;
    580 //					r_rightexit = clipvert;
    581 	movl	$1,C(r_rightclipped)
    582 	movl	mv_position+0(%esp),%eax
    583 	movl	%eax,C(r_rightexit)+mv_position+0
    584 	movl	mv_position+4(%esp),%eax
    585 	movl	%eax,C(r_rightexit)+mv_position+4
    586 	movl	mv_position+8(%esp),%eax
    587 	movl	%eax,C(r_rightexit)+mv_position+8
    588 
    589 //				}
    590 //
    591 //				R_ClipEdge (pv0, &clipvert, clip->next);
    592 //				return;
    593 //			}
    594 	jmp		Lcontinue
    595 
    596 //			}
    597 
    598 Lp3:
    599 
    600 //			// only point 0 is clipped
    601 //				r_lastvertvalid = false;
    602 
    603 	movl	$0,C(r_lastvertvalid)
    604 
    605 //				f = d0 / (d0 - d1);
    606 	flds	Ld0
    607 	flds	Ld1
    608 	fsubr	%st(1),%st(0)
    609 
    610 //			// we don't cache partially clipped edges
    611 	movl	$0x7FFFFFFF,C(cacheoffset)
    612 
    613 	fdivrp	%st(0),%st(1)
    614 
    615 	subl	$(mv_size),%esp			// allocate space for clipvert
    616 
    617 //				clipvert.position[0] = pv0->position[0] +
    618 //						f * (pv1->position[0] - pv0->position[0]);
    619 //				clipvert.position[1] = pv0->position[1] +
    620 //						f * (pv1->position[1] - pv0->position[1]);
    621 //				clipvert.position[2] = pv0->position[2] +
    622 //						f * (pv1->position[2] - pv0->position[2]);
    623 	flds	mv_position+8(%edx)
    624 	fsubs	mv_position+8(%esi)
    625 	flds	mv_position+4(%edx)
    626 	fsubs	mv_position+4(%esi)
    627 	flds	mv_position+0(%edx)
    628 	fsubs	mv_position+0(%esi)		// 0 | 1 | 2
    629 
    630 	movl	cp_leftedge(%ebx),%eax
    631 	testb	%al,%al
    632 
    633 	fmul	%st(3),%st(0)
    634 	fxch	%st(1)					// 1 | 0 | 2
    635 	fmul	%st(3),%st(0)
    636 	fxch	%st(2)					// 2 | 0 | 1
    637 	fmulp	%st(0),%st(3)			// 0 | 1 | 2
    638 	fadds	mv_position+0(%esi)
    639 	fxch	%st(1)					// 1 | 0 | 2
    640 	fadds	mv_position+4(%esi)
    641 	fxch	%st(2)					// 2 | 0 | 1
    642 	fadds	mv_position+8(%esi)
    643 	fxch	%st(1)					// 0 | 2 | 1
    644 	fstps	mv_position+0(%esp)		// 2 | 1
    645 	fstps	mv_position+8(%esp)		// 1
    646 	fstps	mv_position+4(%esp)
    647 
    648 // replace pv0 with the clip point
    649 	movl	%esp,%esi
    650 
    651 //				if (clip->leftedge)
    652 //				{
    653 	jz		Ltestright2
    654 
    655 //					r_leftclipped = true;
    656 //					r_leftenter = clipvert;
    657 	movl	$1,C(r_leftclipped)
    658 	movl	mv_position+0(%esp),%eax
    659 	movl	%eax,C(r_leftenter)+mv_position+0
    660 	movl	mv_position+4(%esp),%eax
    661 	movl	%eax,C(r_leftenter)+mv_position+4
    662 	movl	mv_position+8(%esp),%eax
    663 	movl	%eax,C(r_leftenter)+mv_position+8
    664 
    665 	jmp		Lcontinue
    666 
    667 //				}
    668 
    669 Ltestright2:
    670 //				else if (clip->rightedge)
    671 //				{
    672 	testb	%ah,%ah
    673 	jz		Lcontinue
    674 
    675 //					r_rightclipped = true;
    676 //					r_rightenter = clipvert;
    677 	movl	$1,C(r_rightclipped)
    678 	movl	mv_position+0(%esp),%eax
    679 	movl	%eax,C(r_rightenter)+mv_position+0
    680 	movl	mv_position+4(%esp),%eax
    681 	movl	%eax,C(r_rightenter)+mv_position+4
    682 	movl	mv_position+8(%esp),%eax
    683 	movl	%eax,C(r_rightenter)+mv_position+8
    684 
    685 //				}
    686 	jmp		Lcontinue
    687 
    688 // %esi = vec3_t point to transform and project
    689 // %edx preserved
    690 LTransformAndProject:
    691 
    692 //	// transform and project
    693 //		VectorSubtract (world, modelorg, local);
    694 	flds	mv_position+0(%esi)
    695 	fsubs	C(modelorg)+0
    696 	flds	mv_position+4(%esi)
    697 	fsubs	C(modelorg)+4
    698 	flds	mv_position+8(%esi)	
    699 	fsubs	C(modelorg)+8
    700 	fxch	%st(2)				// local[0] | local[1] | local[2]
    701 
    702 //		TransformVector (local, transformed);
    703 //	
    704 //		if (transformed[2] < NEAR_CLIP)
    705 //			transformed[2] = NEAR_CLIP;
    706 //	
    707 //		lzi0 = 1.0 / transformed[2];
    708 	fld		%st(0)				// local[0] | local[0] | local[1] | local[2]
    709 	fmuls	C(vpn)+0			// zm0 | local[0] | local[1] | local[2]
    710 	fld		%st(1)				// local[0] | zm0 | local[0] | local[1] |
    711 								//  local[2]
    712 	fmuls	C(vright)+0			// xm0 | zm0 | local[0] | local[1] | local[2]
    713 	fxch	%st(2)				// local[0] | zm0 | xm0 | local[1] | local[2]
    714 	fmuls	C(vup)+0			// ym0 |  zm0 | xm0 | local[1] | local[2]
    715 	fld		%st(3)				// local[1] | ym0 |  zm0 | xm0 | local[1] |
    716 								//  local[2]
    717 	fmuls	C(vpn)+4			// zm1 | ym0 | zm0 | xm0 | local[1] |
    718 								//  local[2]
    719 	fld		%st(4)				// local[1] | zm1 | ym0 | zm0 | xm0 |
    720 								//  local[1] | local[2]
    721 	fmuls	C(vright)+4			// xm1 | zm1 | ym0 |  zm0 | xm0 |
    722 								//  local[1] | local[2]
    723 	fxch	%st(5)				// local[1] | zm1 | ym0 | zm0 | xm0 |
    724 								//  xm1 | local[2]
    725 	fmuls	C(vup)+4			// ym1 | zm1 | ym0 | zm0 | xm0 |
    726 								//  xm1 | local[2]
    727 	fxch	%st(1)				// zm1 | ym1 | ym0 | zm0 | xm0 |
    728 								//  xm1 | local[2]
    729 	faddp	%st(0),%st(3)		// ym1 | ym0 | zm2 | xm0 | xm1 | local[2]
    730 	fxch	%st(3)				// xm0 | ym0 | zm2 | ym1 | xm1 | local[2]
    731 	faddp	%st(0),%st(4)		// ym0 | zm2 | ym1 | xm2 | local[2]
    732 	faddp	%st(0),%st(2)		// zm2 | ym2 | xm2 | local[2]
    733 	fld		%st(3)				// local[2] | zm2 | ym2 | xm2 | local[2]
    734 	fmuls	C(vpn)+8			// zm3 | zm2 | ym2 | xm2 | local[2]
    735 	fld		%st(4)				// local[2] | zm3 | zm2 | ym2 | xm2 | local[2]
    736 	fmuls	C(vright)+8			// xm3 | zm3 | zm2 | ym2 | xm2 | local[2]
    737 	fxch	%st(5)				// local[2] | zm3 | zm2 | ym2 | xm2 | xm3
    738 	fmuls	C(vup)+8			// ym3 | zm3 | zm2 | ym2 | xm2 | xm3
    739 	fxch	%st(1)				// zm3 | ym3 | zm2 | ym2 | xm2 | xm3
    740 	faddp	%st(0),%st(2)		// ym3 | zm4 | ym2 | xm2 | xm3
    741 	fxch	%st(4)				// xm3 | zm4 | ym2 | xm2 | ym3
    742 	faddp	%st(0),%st(3)		// zm4 | ym2 | xm4 | ym3
    743 	fxch	%st(1)				// ym2 | zm4 | xm4 | ym3
    744 	faddp	%st(0),%st(3)		// zm4 | xm4 | ym4
    745 
    746 	fcoms	Lfp_near_clip
    747 	fnstsw	%ax
    748 	testb	$1,%ah
    749 	jz		LNoClip
    750 	fstp	%st(0)
    751 	flds	Lfp_near_clip
    752 
    753 LNoClip:
    754 
    755 	fdivrs	float_1				// lzi0 | x | y
    756 	fxch	%st(1)				// x | lzi0 | y
    757 
    758 //	// FIXME: build x/yscale into transform?
    759 //		scale = xscale * lzi0;
    760 //		u0 = (xcenter + scale*transformed[0]);
    761 	flds	C(xscale)			// xscale | x | lzi0 | y
    762 	fmul	%st(2),%st(0)		// scale | x | lzi0 | y
    763 	fmulp	%st(0),%st(1)		// scale*x | lzi0 | y
    764 	fadds	C(xcenter)			// u0 | lzi0 | y
    765 
    766 //		if (u0 < r_refdef.fvrectx_adj)
    767 //			u0 = r_refdef.fvrectx_adj;
    768 //		if (u0 > r_refdef.fvrectright_adj)
    769 //			u0 = r_refdef.fvrectright_adj;
    770 // FIXME: use integer compares of floats?
    771 	fcoms	C(r_refdef)+rd_fvrectx_adj
    772 	fnstsw	%ax
    773 	testb	$1,%ah
    774 	jz		LClampP0
    775 	fstp	%st(0)
    776 	flds	C(r_refdef)+rd_fvrectx_adj
    777 LClampP0:
    778 	fcoms	C(r_refdef)+rd_fvrectright_adj
    779 	fnstsw	%ax
    780 	testb	$0x45,%ah
    781 	jnz		LClampP1
    782 	fstp	%st(0)
    783 	flds	C(r_refdef)+rd_fvrectright_adj
    784 LClampP1:
    785 
    786 	fld		%st(1)				// lzi0 | u0 | lzi0 | y
    787 
    788 //		scale = yscale * lzi0;
    789 //		v0 = (ycenter - scale*transformed[1]);
    790 	fmuls	C(yscale)			// scale | u0 | lzi0 | y
    791 	fmulp	%st(0),%st(3)		// u0 | lzi0 | scale*y
    792 	fxch	%st(2)				// scale*y | lzi0 | u0
    793 	fsubrs	C(ycenter)			// v0 | lzi0 | u0
    794 
    795 //		if (v0 < r_refdef.fvrecty_adj)
    796 //			v0 = r_refdef.fvrecty_adj;
    797 //		if (v0 > r_refdef.fvrectbottom_adj)
    798 //			v0 = r_refdef.fvrectbottom_adj;
    799 // FIXME: use integer compares of floats?
    800 	fcoms	C(r_refdef)+rd_fvrecty_adj
    801 	fnstsw	%ax
    802 	testb	$1,%ah
    803 	jz		LClampP2
    804 	fstp	%st(0)
    805 	flds	C(r_refdef)+rd_fvrecty_adj
    806 LClampP2:
    807 	fcoms	C(r_refdef)+rd_fvrectbottom_adj
    808 	fnstsw	%ax
    809 	testb	$0x45,%ah
    810 	jnz		LClampP3
    811 	fstp	%st(0)
    812 	flds	C(r_refdef)+rd_fvrectbottom_adj
    813 LClampP3:
    814 	ret
    815 
    816 #endif	// id386
    817