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
17Ld0:			.single		0.0
18Ld1:			.single		0.0
19Lstack:			.long		0
20Lfp_near_clip:	.single		NEAR_CLIP
21Lceilv0:		.long		0
22Lv:				.long		0
23Lu0:			.long		0
24Lv0:			.long		0
25Lzi0:			.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)
39C(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
60Lcliploop:
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
102Lcontinue:
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);
117Lemit:
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
156LCalcFirst:
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
174LCalcSecond:
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)
204LP0:
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)
219LP1:
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
227LPop5AndDone:
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
236LDoPop:
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
244LP2:
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
270LSide1:
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
317LSide0:
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
364LSideDone:
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
394LP4:
395	movl	%edx,et_u(%edi)
396	movl	%edx,%eax
397LP5:
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
413LDoFirst:
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
424LNotFirst:
425
426//	else
427//	{
428//		pcheck = newedges[v];
429//
430//		while (pcheck->next && pcheck->next->u < u_check)
431//			pcheck = pcheck->next;
432LFindInsertLoop:
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
440LInsertFound:
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
449LSetRemove:
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
457Ldone:
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
467Lp2:
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
500Lp1:
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
573Ltestright:
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
598Lp3:
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
669Ltestright2:
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
690LTransformAndProject:
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
753LNoClip:
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
777LClampP0:
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
784LClampP1:
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
806LClampP2:
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
813LClampP3:
814	ret
815
816#endif	// id386
817
818