2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
22 // x86 assembly-language edge-processing code.
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
39 //--------------------------------------------------------------------
41 #define edgestoadd 4+8 // note odd stack offsets because of interleaving
42 #define edgelist 8+12 // with pushes
44 .globl C(R_EdgeCodeStart)
47 .globl C(R_InsertNewEdges)
50 pushl
%esi
// preserve register variables
51 movl edgestoadd
(%esp
),%edx
53 movl edgelist
(%esp
),%ecx
61 movl et_next
(%ecx
),%esi
65 movl et_next
(%esi
),%ecx
69 movl et_next
(%ecx
),%esi
73 movl et_next
(%esi
),%ecx
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
)
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
)
103 popl
%ebx
// restore register variables
109 //--------------------------------------------------------------------
113 .globl C(R_RemoveEdges)
116 movl predge
(%esp
),%eax
119 movl et_next
(%eax
),%ecx
120 movl et_nextremove
(%eax
),%ebx
121 movl et_prev
(%eax
),%edx
123 movl
%edx
,et_prev
(%ecx
)
125 movl
%ecx
,et_next
(%edx
)
127 movl et_next
(%ebx
),%ecx
128 movl et_prev
(%ebx
),%edx
129 movl et_nextremove
(%ebx
),%eax
130 movl
%edx
,et_prev
(%ecx
)
132 movl
%ecx
,et_next
(%edx
)
139 movl
%ecx
,et_next
(%edx
)
144 //--------------------------------------------------------------------
146 #define pedgelist 4+4 // note odd stack offset because of interleaving
149 .globl C(R_StepActiveU)
152 movl pedgelist
(%esp
),%edx
153 pushl
%esi
// preserve register variables
156 movl et_prev
(%edx
),%esi
163 movl et_u_step
(%edx
),%ebx
165 movl et_next
(%edx
),%esi
171 movl et_u_step
(%esi
),%ebx
173 movl et_next
(%esi
),%edx
179 movl et_u_step
(%edx
),%ebx
181 movl et_next
(%edx
),%esi
187 movl et_u_step
(%esi
),%ebx
189 movl et_next
(%esi
),%edx
201 // push it back to keep it sorted
202 movl et_prev
(%edx
),%ecx
203 movl et_next
(%edx
),%ebx
205 // done if the
-1 in edge_aftertail triggered this
206 cmpl $
(C
(edge_aftertail
)),%edx
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
)
214 // find out where the edge goes in the edge list
216 movl et_prev
(%edi
),%ecx
221 movl et_prev
(%ecx
),%edi
228 // put the edge back into the edge list
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
)
237 movl et_prev
(%esi
),%esi
239 cmpl $
(C
(edge_tail
)),%edx
243 popl
%ebx
// restore register variables
249 //--------------------------------------------------------------------
251 #define surf 4 // note this is loaded before any pushes
255 movl st_spanstate
(%esi
),%eax
// check for edge inversion
259 movl
%eax
,st_spanstate
(%esi
)
260 movl st_insubmodel
(%esi
),%ecx
261 movl
0x12345678,%edx
// surfaces
[1].st_next
263 movl C
(r_bmodelactive
),%eax
266 movl
%eax
,C
(r_bmodelactive
)
267 jnz LNoEmit
// surface isn
't on top, just remove
269 // emit a span (current top going away)
271 shrl $20,%eax // iu = integral pixel u
272 movl st_last_u(%esi),%edx
273 movl st_next(%esi),%ecx
275 jle LNoEmit2 // iu <= surf->last_u, so nothing to emit
277 movl %eax,st_last_u(%ecx) // surf->next->last_u = iu;
279 movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
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
289 movl st_next(%esi),%edx // remove the surface from the surface
290 movl st_prev(%esi),%esi // stack
292 movl %edx,st_next(%esi)
293 movl %esi,st_prev(%edx)
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
301 movl %edx,st_next(%esi)
302 movl %esi,st_prev(%edx)
306 movl st_next(%esi),%edx // remove the surface from the surface
307 movl st_prev(%esi),%esi // stack
309 movl %edx,st_next(%esi)
310 movl %esi,st_prev(%edx)
314 movl %eax,st_spanstate(%esi)
317 //--------------------------------------------------------------------
319 // trailing edge only
325 .globl C(R_GenerateSpans)
327 pushl %ebp // preserve caller's stack frame
329 pushl
%esi
// preserve register variables
332 // clear active surfaces to just the background surface
333 movl C
(surfaces
),%eax
334 movl C
(edge_head_u_shift20
),%edx
336 // %ebp
= span_p throughout
339 movl $
0,C
(r_bmodelactive
)
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
347 cmpl $
(C
(edge_tail
)),%ebx
// done if empty list
352 movl et_surfs
(%ebx
),%edi
353 movl C
(surfaces
),%eax
355 andl $
0xFFFF0000,%edi
357 jz Lgs_leading
// not a trailing edge
359 // it has
a left surface
, so
a surface is going away for this span
360 shll $
(SURF_T_SHIFT
),%esi
365 // both leading
and trailing
367 movl C
(surfaces
),%eax
369 // ---------------------------------------------------------------
370 // handle
a leading edge
371 // ---------------------------------------------------------------
374 shrl $
16-SURF_T_SHIFT
,%edi
375 movl C
(surfaces
),%eax
377 movl
0x12345678,%esi
// surf2
= surfaces
[1].next;
379 movl st_spanstate
(%edi
),%edx
380 movl st_insubmodel
(%edi
),%eax
384 // handle
a leading non-bmodel edge
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
)
392 // if
(surf-
>key
< surf2-
>key
)
395 movl st_key
(%edi
),%eax
396 movl
%edx
,st_spanstate
(%edi
)
397 movl st_key
(%esi
),%ecx
401 // main sorting loop to search through surface stack until insertion point
402 // found. Always terminates because background surface is sentinel
405 // surf2
= surf2-
>next;
406 // } while
(surf-
>key
>= surf2-
>key
);
408 movl st_next
(%esi
),%esi
409 movl st_key
(%esi
),%ecx
416 // handle
a leading bmodel edge
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
)
425 movl C
(r_bmodelactive
),%ecx
428 movl
%edx
,st_spanstate
(%edi
)
429 movl
%ecx
,C
(r_bmodelactive
)
431 // if
(surf-
>key
< surf2-
>key
)
433 movl st_key
(%edi
),%eax
434 movl st_key
(%esi
),%ecx
438 // if
((surf-
>key
== surf2-
>key
) && surf-
>insubmodel
)
440 jz Lzcheck_for_newtop
442 // main sorting loop to search through surface stack until insertion point
443 // found. Always terminates because background surface is sentinel
446 // surf2
= surf2-
>next;
447 // } while
(surf-
>key
> surf2-
>key
);
449 movl st_next
(%esi
),%esi
450 movl st_key
(%esi
),%ecx
456 // Do
1/z sorting to see if we
've arrived in the right position
462 fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
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
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
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
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 |
497 faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
498 fxch %st(1) // newzibottom | testzi | newzi | fu
500 // if (newzibottom >= testzi)
501 // goto Lgotposition;
503 fcomp %st(1) // testzi | newzi | fu
505 fxch %st(1) // newzi | testzi | fu
506 fmuls float_1_point_001 // newzitop | testzi | fu
507 fxch %st(1) // testzi | newzitop | fu
511 jz Lgotposition_fpop3
513 // if (newzitop >= testzi)
516 fcomp %st(1) // newzitop | fu
521 // if (surf->d_zistepu >= surf2->d_zistepu)
524 flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop| fu
525 fcomps st_d_zistepu(%esi) // newzitop | fu
528 jz Lgotposition_fpop2
530 fstp %st(0) // clear the FPstack
532 movl st_key(%edi),%eax
544 // emit a span (obscures current top)
551 movl st_key(%edi),%eax // reload the sorting key
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;
559 jle LInsertAndExit // iu <= surf->last_u, so nothing to emit
562 movl %edx,espan_t_u(%ebp) // span->u = surf->last_u;
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
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;
580 // ---------------------------------------------------------------
582 // ---------------------------------------------------------------
584 // ---------------------------------------------------------------
585 // see if there are any more edges
586 // ---------------------------------------------------------------
589 movl et_next(%ebx),%ebx
590 cmpl $(C(edge_tail)),%ebx
593 // clean up at the right edge
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
600 movl C
(edge_tail_u_shift20
),%eax
602 movl st_last_u
(%esi
),%edx
604 jle Lgs_resetspanstate
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
615 // reset spanstate for all surfaces in the surface stack
617 movl
%ecx
,st_spanstate
(%esi
)
618 movl st_next
(%esi
),%esi
619 cmpl $
0x12345678,%esi
// &surfaces
[1]
621 jnz Lgs_resetspanstate
623 // store the final span_p
626 popl
%ebx
// restore register variables
629 popl
%ebp
// restore the caller
's stack frame
633 // ---------------------------------------------------------------
634 // 1/z sorting for bmodels in the same leaf
635 // ---------------------------------------------------------------
639 movl %edx,st_spanstate(%edi)
651 fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
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
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
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
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 |
686 faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu
687 fxch %st(1) // newzibottom | testzi | newzi | fu
689 // if (newzibottom >= testzi)
692 fcomp %st(1) // testzi | newzi | fu
694 fxch %st(1) // newzi | testzi | fu
695 fmuls float_1_point_001 // newzitop | testzi | fu
696 fxch %st(1) // testzi | newzitop | fu
702 // if (newzitop >= testzi)
705 fcomp %st(1) // newzitop | fu
710 // if (surf->d_zistepu >= surf2->d_zistepu)
713 flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop | fu
714 fcomps st_d_zistepu(%esi) // newzitop | fu
720 fstp %st(0) // clear the FP stack
722 movl st_key(%edi),%eax
726 .globl C(R_EdgeCodeEnd)
730 //----------------------------------------------------------------------
731 // Surface array address code patching routine
732 //----------------------------------------------------------------------
735 .globl C(R_SurfacePatch)
738 movl C(surfaces),%eax