Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  751.