aboutsummaryrefslogtreecommitdiffstats
path: root/QW/client/r_edgea.s
diff options
context:
space:
mode:
Diffstat (limited to 'QW/client/r_edgea.s')
-rw-r--r--QW/client/r_edgea.s750
1 files changed, 750 insertions, 0 deletions
diff --git a/QW/client/r_edgea.s b/QW/client/r_edgea.s
new file mode 100644
index 0000000..f67130f
--- /dev/null
+++ b/QW/client/r_edgea.s
@@ -0,0 +1,750 @@
+/*
+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
+