| /*
|
| Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
| This program is free software; you can redistribute it and/or
|
| modify it under the terms of the GNU General Public License
|
| as published by the Free Software Foundation; either version 2
|
| of the License, or (at your option) any later version.
|
|
|
| This program is distributed in the hope that it will be useful,
|
| but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
| See the GNU General Public License for more details.
|
|
|
| You should have received a copy of the GNU General Public License
|
| along with this program; if not, write to the Free Software
|
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
| */
|
| // |
| // r_edgea.s |
| // x86 assembly-language edge-processing code. |
| // |
| |
| #include "asm_i386.h" |
| #include "quakeasm.h" |
| #include "asm_draw.h" |
| |
| #if id386 |
| |
| .data |
| Ltemp: .long 0 |
| float_1_div_0100000h: .long 0x35800000 // 1.0/(float)0x100000 |
| float_point_999: .single 0.999 |
| float_1_point_001: .single 1.001 |
| |
| .text |
| |
| //-------------------------------------------------------------------- |
| |
| #define edgestoadd 4+8 // note odd stack offsets because of interleaving |
| #define edgelist 8+12 // with pushes |
| |
| .globl C(R_EdgeCodeStart) |
| C(R_EdgeCodeStart): |
| |
| .globl C(R_InsertNewEdges) |
| C(R_InsertNewEdges): |
| pushl %edi |
| pushl %esi // preserve register variables |
| movl edgestoadd(%esp),%edx |
| pushl %ebx |
| movl edgelist(%esp),%ecx |
| |
| LDoNextEdge: |
| movl et_u(%edx),%eax |
| movl %edx,%edi |
| |
| LContinueSearch: |
| movl et_u(%ecx),%ebx |
| movl et_next(%ecx),%esi |
| cmpl %ebx,%eax |
| jle LAddedge |
| movl et_u(%esi),%ebx |
| movl et_next(%esi),%ecx |
| cmpl %ebx,%eax |
| jle LAddedge2 |
| movl et_u(%ecx),%ebx |
| movl et_next(%ecx),%esi |
| cmpl %ebx,%eax |
| jle LAddedge |
| movl et_u(%esi),%ebx |
| movl et_next(%esi),%ecx |
| cmpl %ebx,%eax |
| jg LContinueSearch |
| |
| LAddedge2: |
| movl et_next(%edx),%edx |
| movl et_prev(%esi),%ebx |
| movl %esi,et_next(%edi) |
| movl %ebx,et_prev(%edi) |
| movl %edi,et_next(%ebx) |
| movl %edi,et_prev(%esi) |
| movl %esi,%ecx |
| |
| cmpl $0,%edx |
| jnz LDoNextEdge |
| jmp LDone |
| |
| .align 4 |
| LAddedge: |
| movl et_next(%edx),%edx |
| movl et_prev(%ecx),%ebx |
| movl %ecx,et_next(%edi) |
| movl %ebx,et_prev(%edi) |
| movl %edi,et_next(%ebx) |
| movl %edi,et_prev(%ecx) |
| |
| cmpl $0,%edx |
| jnz LDoNextEdge |
| |
| LDone: |
| popl %ebx // restore register variables |
| popl %esi |
| popl %edi |
| |
| ret |
| |
| //-------------------------------------------------------------------- |
| |
| #define predge 4+4 |
| |
| .globl C(R_RemoveEdges) |
| C(R_RemoveEdges): |
| pushl %ebx |
| movl predge(%esp),%eax |
| |
| Lre_loop: |
| movl et_next(%eax),%ecx |
| movl et_nextremove(%eax),%ebx |
| movl et_prev(%eax),%edx |
| testl %ebx,%ebx |
| movl %edx,et_prev(%ecx) |
| jz Lre_done |
| movl %ecx,et_next(%edx) |
| |
| movl et_next(%ebx),%ecx |
| movl et_prev(%ebx),%edx |
| movl et_nextremove(%ebx),%eax |
| movl %edx,et_prev(%ecx) |
| testl %eax,%eax |
| movl %ecx,et_next(%edx) |
| jnz Lre_loop |
| |
| popl %ebx |
| ret |
| |
| Lre_done: |
| movl %ecx,et_next(%edx) |
| popl %ebx |
| |
| ret |
| |
| //-------------------------------------------------------------------- |
| |
| #define pedgelist 4+4 // note odd stack offset because of interleaving |
| // with pushes |
| |
| .globl C(R_StepActiveU) |
| C(R_StepActiveU): |
| pushl %edi |
| movl pedgelist(%esp),%edx |
| pushl %esi // preserve register variables |
| pushl %ebx |
| |
| movl et_prev(%edx),%esi |
| |
| LNewEdge: |
| movl et_u(%esi),%edi |
| |
| LNextEdge: |
| movl et_u(%edx),%eax |
| movl et_u_step(%edx),%ebx |
| addl %ebx,%eax |
| movl et_next(%edx),%esi |
| movl %eax,et_u(%edx) |
| cmpl %edi,%eax |
| jl LPushBack |
| |
| movl et_u(%esi),%edi |
| movl et_u_step(%esi),%ebx |
| addl %ebx,%edi |
| movl et_next(%esi),%edx |
| movl %edi,et_u(%esi) |
| cmpl %eax,%edi |
| jl LPushBack2 |
| |
| movl et_u(%edx),%eax |
| movl et_u_step(%edx),%ebx |
| addl %ebx,%eax |
| movl et_next(%edx),%esi |
| movl %eax,et_u(%edx) |
| cmpl %edi,%eax |
| jl LPushBack |
| |
| movl et_u(%esi),%edi |
| movl et_u_step(%esi),%ebx |
| addl %ebx,%edi |
| movl et_next(%esi),%edx |
| movl %edi,et_u(%esi) |
| cmpl %eax,%edi |
| jnl LNextEdge |
| |
| LPushBack2: |
| movl %edx,%ebx |
| movl %edi,%eax |
| movl %esi,%edx |
| movl %ebx,%esi |
| |
| LPushBack: |
| // push it back to keep it sorted |
| movl et_prev(%edx),%ecx |
| movl et_next(%edx),%ebx |
| |
| // done if the -1 in edge_aftertail triggered this |
| cmpl $(C(edge_aftertail)),%edx |
| jz LUDone |
| |
| // pull the edge out of the edge list |
| movl et_prev(%ecx),%edi |
| movl %ecx,et_prev(%esi) |
| movl %ebx,et_next(%ecx) |
| |
| // find out where the edge goes in the edge list |
| LPushBackLoop: |
| movl et_prev(%edi),%ecx |
| movl et_u(%edi),%ebx |
| cmpl %ebx,%eax |
| jnl LPushBackFound |
| |
| movl et_prev(%ecx),%edi |
| movl et_u(%ecx),%ebx |
| cmpl %ebx,%eax |
| jl LPushBackLoop |
| |
| movl %ecx,%edi |
| |
| // put the edge back into the edge list |
| LPushBackFound: |
| movl et_next(%edi),%ebx |
| movl %edi,et_prev(%edx) |
| movl %ebx,et_next(%edx) |
| movl %edx,et_next(%edi) |
| movl %edx,et_prev(%ebx) |
| |
| movl %esi,%edx |
| movl et_prev(%esi),%esi |
| |
| cmpl $(C(edge_tail)),%edx |
| jnz LNewEdge |
| |
| LUDone: |
| popl %ebx // restore register variables |
| popl %esi |
| popl %edi |
| |
| ret |
| |
| //-------------------------------------------------------------------- |
| |
| #define surf 4 // note this is loaded before any pushes |
| |
| .align 4 |
| TrailingEdge: |
| movl st_spanstate(%esi),%eax // check for edge inversion |
| decl %eax |
| jnz LInverted |
| |
| movl %eax,st_spanstate(%esi) |
| movl st_insubmodel(%esi),%ecx |
| movl 0x12345678,%edx // surfaces[1].st_next |
| LPatch0: |
| movl C(r_bmodelactive),%eax |
| subl %ecx,%eax |
| cmpl %esi,%edx |
| movl %eax,C(r_bmodelactive) |
| jnz LNoEmit // surface isn't on top, just remove |
| |
| // emit a span (current top going away) |
| movl et_u(%ebx),%eax |
| shrl $20,%eax // iu = integral pixel u |
| movl st_last_u(%esi),%edx |
| movl st_next(%esi),%ecx |
| cmpl %edx,%eax |
| jle LNoEmit2 // iu <= surf->last_u, so nothing to emit |
| |
| movl %eax,st_last_u(%ecx) // surf->next->last_u = iu; |
| subl %edx,%eax |
| movl %edx,espan_t_u(%ebp) // span->u = surf->last_u; |
| |
| movl %eax,espan_t_count(%ebp) // span->count = iu - span->u; |
| movl C(current_iv),%eax |
| movl %eax,espan_t_v(%ebp) // span->v = current_iv; |
| movl st_spans(%esi),%eax |
| movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans; |
| movl %ebp,st_spans(%esi) // surf->spans = span; |
| addl $(espan_t_size),%ebp |
| |
| movl st_next(%esi),%edx // remove the surface from the surface |
| movl st_prev(%esi),%esi // stack |
| |
| movl %edx,st_next(%esi) |
| movl %esi,st_prev(%edx) |
| ret |
| |
| LNoEmit2: |
| movl %eax,st_last_u(%ecx) // surf->next->last_u = iu; |
| movl st_next(%esi),%edx // remove the surface from the surface |
| movl st_prev(%esi),%esi // stack |
| |
| movl %edx,st_next(%esi) |
| movl %esi,st_prev(%edx) |
| ret |
| |
| LNoEmit: |
| movl st_next(%esi),%edx // remove the surface from the surface |
| movl st_prev(%esi),%esi // stack |
| |
| movl %edx,st_next(%esi) |
| movl %esi,st_prev(%edx) |
| ret |
| |
| LInverted: |
| movl %eax,st_spanstate(%esi) |
| ret |
| |
| //-------------------------------------------------------------------- |
| |
| // trailing edge only |
| Lgs_trailing: |
| pushl $Lgs_nextedge |
| jmp TrailingEdge |
| |
| |
| .globl C(R_GenerateSpans) |
| C(R_GenerateSpans): |
| pushl %ebp // preserve caller's stack frame |
| pushl %edi |
| pushl %esi // preserve register variables |
| pushl %ebx |
| |
| // clear active surfaces to just the background surface |
| movl C(surfaces),%eax |
| movl C(edge_head_u_shift20),%edx |
| addl $(st_size),%eax |
| // %ebp = span_p throughout |
| movl C(span_p),%ebp |
| |
| movl $0,C(r_bmodelactive) |
| |
| movl %eax,st_next(%eax) |
| movl %eax,st_prev(%eax) |
| movl %edx,st_last_u(%eax) |
| movl C(edge_head)+et_next,%ebx // edge=edge_head.next |
| |
| // generate spans |
| cmpl $(C(edge_tail)),%ebx // done if empty list |
| jz Lgs_lastspan |
| |
| Lgs_edgeloop: |
| |
| movl et_surfs(%ebx),%edi |
| movl C(surfaces),%eax |
| movl %edi,%esi |
| andl $0xFFFF0000,%edi |
| andl $0xFFFF,%esi |
| jz Lgs_leading // not a trailing edge |
| |
| // it has a left surface, so a surface is going away for this span |
| shll $(SURF_T_SHIFT),%esi |
| addl %eax,%esi |
| testl %edi,%edi |
| jz Lgs_trailing |
| |
| // both leading and trailing |
| call TrailingEdge |
| movl C(surfaces),%eax |
| |
| // --------------------------------------------------------------- |
| // handle a leading edge |
| // --------------------------------------------------------------- |
| |
| Lgs_leading: |
| shrl $16-SURF_T_SHIFT,%edi |
| movl C(surfaces),%eax |
| addl %eax,%edi |
| movl 0x12345678,%esi // surf2 = surfaces[1].next; |
| LPatch2: |
| movl st_spanstate(%edi),%edx |
| movl st_insubmodel(%edi),%eax |
| testl %eax,%eax |
| jnz Lbmodel_leading |
| |
| // handle a leading non-bmodel edge |
| |
| // don't start a span if this is an inverted span, with the end edge preceding |
| // the start edge (that is, we've already seen the end edge) |
| testl %edx,%edx |
| jnz Lxl_done |
| |
| |
| // if (surf->key < surf2->key) |
| // goto newtop; |
| incl %edx |
| movl st_key(%edi),%eax |
| movl %edx,st_spanstate(%edi) |
| movl st_key(%esi),%ecx |
| cmpl %ecx,%eax |
| jl Lnewtop |
| |
| // main sorting loop to search through surface stack until insertion point |
| // found. Always terminates because background surface is sentinel |
| // do |
| // { |
| // surf2 = surf2->next; |
| // } while (surf->key >= surf2->key); |
| Lsortloopnb: |
| movl st_next(%esi),%esi |
| movl st_key(%esi),%ecx |
| cmpl %ecx,%eax |
| jge Lsortloopnb |
| |
| jmp LInsertAndExit |
| |
| |
| // handle a leading bmodel edge |
| .align 4 |
| Lbmodel_leading: |
| |
| // don't start a span if this is an inverted span, with the end edge preceding |
| // the start edge (that is, we've already seen the end edge) |
| testl %edx,%edx |
| jnz Lxl_done |
| |
| movl C(r_bmodelactive),%ecx |
| incl %edx |
| incl %ecx |
| movl %edx,st_spanstate(%edi) |
| movl %ecx,C(r_bmodelactive) |
| |
| // if (surf->key < surf2->key) |
| // goto newtop; |
| movl st_key(%edi),%eax |
| movl st_key(%esi),%ecx |
| cmpl %ecx,%eax |
| jl Lnewtop |
| |
| // if ((surf->key == surf2->key) && surf->insubmodel) |
| // { |
| jz Lzcheck_for_newtop |
| |
| // main sorting loop to search through surface stack until insertion point |
| // found. Always terminates because background surface is sentinel |
| // do |
| // { |
| // surf2 = surf2->next; |
| // } while (surf->key > surf2->key); |
| Lsortloop: |
| movl st_next(%esi),%esi |
| movl st_key(%esi),%ecx |
| cmpl %ecx,%eax |
| jg Lsortloop |
| |
| jne LInsertAndExit |
| |
| // Do 1/z sorting to see if we've arrived in the right position |
| movl et_u(%ebx),%eax |
| subl $0xFFFFF,%eax |
| movl %eax,Ltemp |
| fildl Ltemp |
| |
| fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) * |
| // (1.0 / 0x100000); |
| |
| fld %st(0) // fu | fu |
| fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu |
| flds C(fv) // fv | fu*surf->d_zistepu | fu |
| fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu |
| fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu |
| fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| |
| flds st_d_zistepu(%esi) // surf2->d_zistepu | |
| // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| fmul %st(3),%st(0) // fu*surf2->d_zistepu | |
| // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fu*surf2->d_zistepu | |
| // fv*surf->d_zistepv | fu |
| faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu |
| |
| flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu |
| fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| fld %st(2) // newzi | fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| |
| fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv | |
| // newzibottom | newzi | fu |
| fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin | |
| // fv*surf2->d_zistepv | newzibottom | newzi | |
| // fu |
| faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu |
| fxch %st(1) // newzibottom | testzi | newzi | fu |
| |
| // if (newzibottom >= testzi) |
| // goto Lgotposition; |
| |
| fcomp %st(1) // testzi | newzi | fu |
| |
| fxch %st(1) // newzi | testzi | fu |
| fmuls float_1_point_001 // newzitop | testzi | fu |
| fxch %st(1) // testzi | newzitop | fu |
| |
| fnstsw %ax |
| testb $0x01,%ah |
| jz Lgotposition_fpop3 |
| |
| // if (newzitop >= testzi) |
| // { |
| |
| fcomp %st(1) // newzitop | fu |
| fnstsw %ax |
| testb $0x45,%ah |
| jz Lsortloop_fpop2 |
| |
| // if (surf->d_zistepu >= surf2->d_zistepu) |
| // goto newtop; |
| |
| flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop| fu |
| fcomps st_d_zistepu(%esi) // newzitop | fu |
| fnstsw %ax |
| testb $0x01,%ah |
| jz Lgotposition_fpop2 |
| |
| fstp %st(0) // clear the FPstack |
| fstp %st(0) |
| movl st_key(%edi),%eax |
| jmp Lsortloop |
| |
| |
| Lgotposition_fpop3: |
| fstp %st(0) |
| Lgotposition_fpop2: |
| fstp %st(0) |
| fstp %st(0) |
| jmp LInsertAndExit |
| |
| |
| // emit a span (obscures current top) |
| |
| Lnewtop_fpop3: |
| fstp %st(0) |
| Lnewtop_fpop2: |
| fstp %st(0) |
| fstp %st(0) |
| movl st_key(%edi),%eax // reload the sorting key |
| |
| Lnewtop: |
| movl et_u(%ebx),%eax |
| movl st_last_u(%esi),%edx |
| shrl $20,%eax // iu = integral pixel u |
| movl %eax,st_last_u(%edi) // surf->last_u = iu; |
| cmpl %edx,%eax |
| jle LInsertAndExit // iu <= surf->last_u, so nothing to emit |
| |
| subl %edx,%eax |
| movl %edx,espan_t_u(%ebp) // span->u = surf->last_u; |
| |
| movl %eax,espan_t_count(%ebp) // span->count = iu - span->u; |
| movl C(current_iv),%eax |
| movl %eax,espan_t_v(%ebp) // span->v = current_iv; |
| movl st_spans(%esi),%eax |
| movl %eax,espan_t_pnext(%ebp) // span->pnext = surf->spans; |
| movl %ebp,st_spans(%esi) // surf->spans = span; |
| addl $(espan_t_size),%ebp |
| |
| LInsertAndExit: |
| // insert before surf2 |
| movl %esi,st_next(%edi) // surf->next = surf2; |
| movl st_prev(%esi),%eax |
| movl %eax,st_prev(%edi) // surf->prev = surf2->prev; |
| movl %edi,st_prev(%esi) // surf2->prev = surf; |
| movl %edi,st_next(%eax) // surf2->prev->next = surf; |
| |
| // --------------------------------------------------------------- |
| // leading edge done |
| // --------------------------------------------------------------- |
| |
| // --------------------------------------------------------------- |
| // see if there are any more edges |
| // --------------------------------------------------------------- |
| |
| Lgs_nextedge: |
| movl et_next(%ebx),%ebx |
| cmpl $(C(edge_tail)),%ebx |
| jnz Lgs_edgeloop |
| |
| // clean up at the right edge |
| Lgs_lastspan: |
| |
| // now that we've reached the right edge of the screen, we're done with any |
| // unfinished surfaces, so emit a span for whatever's on top |
| movl 0x12345678,%esi // surfaces[1].st_next |
| LPatch3: |
| movl C(edge_tail_u_shift20),%eax |
| xorl %ecx,%ecx |
| movl st_last_u(%esi),%edx |
| subl %edx,%eax |
| jle Lgs_resetspanstate |
| |
| movl %edx,espan_t_u(%ebp) |
| movl %eax,espan_t_count(%ebp) |
| movl C(current_iv),%eax |
| movl %eax,espan_t_v(%ebp) |
| movl st_spans(%esi),%eax |
| movl %eax,espan_t_pnext(%ebp) |
| movl %ebp,st_spans(%esi) |
| addl $(espan_t_size),%ebp |
| |
| // reset spanstate for all surfaces in the surface stack |
| Lgs_resetspanstate: |
| movl %ecx,st_spanstate(%esi) |
| movl st_next(%esi),%esi |
| cmpl $0x12345678,%esi // &surfaces[1] |
| LPatch4: |
| jnz Lgs_resetspanstate |
| |
| // store the final span_p |
| movl %ebp,C(span_p) |
| |
| popl %ebx // restore register variables |
| popl %esi |
| popl %edi |
| popl %ebp // restore the caller's stack frame |
| ret |
| |
| |
| // --------------------------------------------------------------- |
| // 1/z sorting for bmodels in the same leaf |
| // --------------------------------------------------------------- |
| .align 4 |
| Lxl_done: |
| incl %edx |
| movl %edx,st_spanstate(%edi) |
| |
| jmp Lgs_nextedge |
| |
| |
| .align 4 |
| Lzcheck_for_newtop: |
| movl et_u(%ebx),%eax |
| subl $0xFFFFF,%eax |
| movl %eax,Ltemp |
| fildl Ltemp |
| |
| fmuls float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) * |
| // (1.0 / 0x100000); |
| |
| fld %st(0) // fu | fu |
| fmuls st_d_zistepu(%edi) // fu*surf->d_zistepu | fu |
| flds C(fv) // fv | fu*surf->d_zistepu | fu |
| fmuls st_d_zistepv(%edi) // fv*surf->d_zistepv | fu*surf->d_zistepu | fu |
| fxch %st(1) // fu*surf->d_zistepu | fv*surf->d_zistepv | fu |
| fadds st_d_ziorigin(%edi) // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| |
| flds st_d_zistepu(%esi) // surf2->d_zistepu | |
| // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| fmul %st(3),%st(0) // fu*surf2->d_zistepu | |
| // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fv*surf->d_zistepv | fu |
| fxch %st(1) // fu*surf->d_zistepu + surf->d_ziorigin | |
| // fu*surf2->d_zistepu | |
| // fv*surf->d_zistepv | fu |
| faddp %st(0),%st(2) // fu*surf2->d_zistepu | newzi | fu |
| |
| flds C(fv) // fv | fu*surf2->d_zistepu | newzi | fu |
| fmuls st_d_zistepv(%esi) // fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| fld %st(2) // newzi | fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| fmuls float_point_999 // newzibottom | fv*surf2->d_zistepv | |
| // fu*surf2->d_zistepu | newzi | fu |
| |
| fxch %st(2) // fu*surf2->d_zistepu | fv*surf2->d_zistepv | |
| // newzibottom | newzi | fu |
| fadds st_d_ziorigin(%esi) // fu*surf2->d_zistepu + surf2->d_ziorigin | |
| // fv*surf2->d_zistepv | newzibottom | newzi | |
| // fu |
| faddp %st(0),%st(1) // testzi | newzibottom | newzi | fu |
| fxch %st(1) // newzibottom | testzi | newzi | fu |
| |
| // if (newzibottom >= testzi) |
| // goto newtop; |
| |
| fcomp %st(1) // testzi | newzi | fu |
| |
| fxch %st(1) // newzi | testzi | fu |
| fmuls float_1_point_001 // newzitop | testzi | fu |
| fxch %st(1) // testzi | newzitop | fu |
| |
| fnstsw %ax |
| testb $0x01,%ah |
| jz Lnewtop_fpop3 |
| |
| // if (newzitop >= testzi) |
| // { |
| |
| fcomp %st(1) // newzitop | fu |
| fnstsw %ax |
| testb $0x45,%ah |
| jz Lsortloop_fpop2 |
| |
| // if (surf->d_zistepu >= surf2->d_zistepu) |
| // goto newtop; |
| |
| flds st_d_zistepu(%edi) // surf->d_zistepu | newzitop | fu |
| fcomps st_d_zistepu(%esi) // newzitop | fu |
| fnstsw %ax |
| testb $0x01,%ah |
| jz Lnewtop_fpop2 |
| |
| Lsortloop_fpop2: |
| fstp %st(0) // clear the FP stack |
| fstp %st(0) |
| movl st_key(%edi),%eax |
| jmp Lsortloop |
| |
| |
| .globl C(R_EdgeCodeEnd) |
| C(R_EdgeCodeEnd): |
| |
| |
| //---------------------------------------------------------------------- |
| // Surface array address code patching routine |
| //---------------------------------------------------------------------- |
| |
| .align 4 |
| .globl C(R_SurfacePatch) |
| C(R_SurfacePatch): |
| |
| movl C(surfaces),%eax |
| addl $(st_size),%eax |
| movl %eax,LPatch4-4 |
| |
| addl $(st_next),%eax |
| movl %eax,LPatch0-4 |
| movl %eax,LPatch2-4 |
| movl %eax,LPatch3-4 |
| |
| ret |
| |
| #endif // id386 |
| |