Un-ignored: the dev drive is the ground truth the restoration and emulator work constantly reference (DPL3/LIBDPL + VRENDER i860 renderer source, BT/RP live+dev game trees, VGL_LABS pod boot, scene/audio content). Kept in-repo for the pod-owner community. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1142 lines
28 KiB
Scheme
1142 lines
28 KiB
Scheme
//{{{ register allocation
|
|
//
|
|
// r1 return address
|
|
// r2 sp
|
|
// r3 frameP
|
|
// r4 .. r15 I should strive to conserve
|
|
// r16 .. r30 I can trash away
|
|
// r31 reserved as an addressing temporary - but available
|
|
//
|
|
// extern void scaninit ( int idr, int idg, int idb, int idz );
|
|
//
|
|
// extern void texinit ( int idu, int idv, int willy, int idz );
|
|
//
|
|
// extern void scanline ( int *fbuffer, int *zbuffer,
|
|
// int ir, int ig, int ib, int iz, int dx,
|
|
// int dr, int dg, int db, int dz );
|
|
//
|
|
// extern void ftexline ( int *fbuffer, int *zbuffer,
|
|
// int iu, int iv, int texbase, int iz, int dx,
|
|
// int idu, idv, dummy, dz );
|
|
//
|
|
// extern void scansegment ( void (*fbuffer)(),
|
|
// int fbuffer, int *zbuffer,
|
|
//
|
|
//
|
|
//
|
|
// FUNCTION PARAMETERS
|
|
//
|
|
#define param1 r16
|
|
#define param2 r17
|
|
#define param3 r18
|
|
#define param4 r19
|
|
#define param5 r20
|
|
#define param6 r21
|
|
#define param7 r22
|
|
#define param8 r23
|
|
#define param9 r24
|
|
#define param10 r25
|
|
#define param11 r26
|
|
#define param12 r27
|
|
|
|
//
|
|
// DOUBLE FLOAT LOCALS
|
|
//
|
|
// interpolant values
|
|
// we should save these first !
|
|
//
|
|
|
|
#define fminus1 f6
|
|
|
|
#define r_lo f8
|
|
#define r_hi f9
|
|
#define r r_lo
|
|
|
|
#define g_lo f10
|
|
#define g_hi f11
|
|
#define g g_lo
|
|
|
|
#define u_lo f8
|
|
#define u_hi f9
|
|
#define u u_lo
|
|
|
|
#define v_lo f10
|
|
#define v_hi f11
|
|
#define v v_lo
|
|
|
|
#define b_lo f12
|
|
#define b_hi f13
|
|
#define b b_lo
|
|
|
|
#define z_lo f14
|
|
#define z_hi f15
|
|
#define z z_lo
|
|
|
|
#define dr_lo f16
|
|
#define dr_hi f17
|
|
#define dr dr_lo
|
|
|
|
#define du_lo f16
|
|
#define du_hi f17
|
|
#define du du_lo
|
|
|
|
#define dg_lo f18
|
|
#define dg_hi f19
|
|
#define dg dg_lo
|
|
|
|
#define dv_lo f18
|
|
#define dv_hi f19
|
|
#define dv dv_lo
|
|
|
|
#define db_lo f20
|
|
#define db_hi f21
|
|
#define db db_lo
|
|
|
|
#define dz_lo f22
|
|
#define dz_hi f23
|
|
#define dz dz_lo
|
|
|
|
// double-length float temporaries
|
|
#define oldz_lo f24
|
|
#define oldz_hi f25
|
|
#define oldz oldz_lo
|
|
|
|
#define nuz f26
|
|
|
|
#define col_lo f28
|
|
#define col_hi f29
|
|
#define col col_lo
|
|
|
|
#define dbltmp f30
|
|
#define dbltmp_lo f30
|
|
#define dbltmp_hi f31
|
|
//}}}
|
|
//{{{ macros
|
|
#define push(reg,offs) st.l reg, offs(sp)
|
|
#define pop(reg,offs) ld.l offs(sp), reg
|
|
//}}}
|
|
|
|
.data
|
|
.align 8
|
|
slope_table::
|
|
.double[16] 0
|
|
|
|
.text
|
|
|
|
//{{{ scaninit ( int idr, int idg, int idb, int idz )
|
|
|
|
.globl _scaninit
|
|
.align 8
|
|
|
|
#define indr param1
|
|
#define indg param2
|
|
#define indb param3
|
|
#define indz param4
|
|
#define itemp1 param5
|
|
|
|
_scaninit::
|
|
adds -1,r0,r31
|
|
ixfr r31,fminus1
|
|
addu indr,indr,itemp1
|
|
ixfr itemp1, dr_lo
|
|
|
|
addu indg,indg,itemp1
|
|
ixfr itemp1, dg_lo
|
|
|
|
addu indb,indb,itemp1
|
|
ixfr itemp1, db_lo
|
|
|
|
addu indz,indz,itemp1
|
|
ixfr itemp1, dz_lo
|
|
|
|
fmov.ss dr_lo,dr_hi
|
|
fmov.ss dg_lo,dg_hi
|
|
fmov.ss db_lo,db_hi
|
|
bri r1
|
|
fmov.ss dz_lo,dz_hi
|
|
|
|
#undef indr
|
|
#undef indg
|
|
#undef indb
|
|
#undef indz
|
|
#undef itemp1
|
|
//}}}
|
|
//{{{ texinit ( int idu, int idv, int compat, int idz )
|
|
|
|
.globl _texinit
|
|
.align 8
|
|
|
|
#define indu param1
|
|
#define indv param2
|
|
#define tx_and_or_mask param3
|
|
#define indz param4
|
|
#define itemp1 param5
|
|
|
|
_texinit::
|
|
// build dr*2 dg*2 dz*2
|
|
adds -1,r0,r31
|
|
ixfr r31,fminus1
|
|
adds indu, indu,itemp1
|
|
and 0xffff, itemp1,itemp1
|
|
ixfr itemp1, du_lo
|
|
ixfr itemp1, du_hi
|
|
|
|
adds indv, indv,itemp1
|
|
and 0xffff, itemp1,itemp1
|
|
ixfr itemp1, dv_lo
|
|
ixfr itemp1, dv_hi
|
|
|
|
adds indz,indz,itemp1
|
|
ixfr itemp1, dz_lo // dz_lo=2*idz
|
|
ixfr itemp1, dz_hi // dz_lo=2*idz
|
|
|
|
bri r1
|
|
ixfr param3, db_lo
|
|
|
|
|
|
shr 16, tx_and_or_mask,itemp1
|
|
andh 0xffff, tx_and_or_mask, r31
|
|
or r16,r31,r31
|
|
ixfr r31, db_hi
|
|
|
|
and 0xffff, tx_and_or_mask, r31
|
|
shl 16, tx_and_or_mask,itemp1
|
|
or r16,r31,r31
|
|
ixfr r31, db_lo
|
|
|
|
bri r1
|
|
nop
|
|
|
|
#undef indu
|
|
#undef indv
|
|
#undef indz
|
|
#undef tx_and_or_mask
|
|
#undef itemp1
|
|
//}}}
|
|
|
|
//{{{ ascaninit ( int idr, int idg, int idb, int idz )
|
|
.text
|
|
|
|
.globl _ascaninit
|
|
.align 8
|
|
|
|
#define indr param8
|
|
#define indg param9
|
|
#define indb param10
|
|
#define indz param11
|
|
#define itemp1 r31
|
|
|
|
#define st_slope(reg)\
|
|
st.l reg,4(r31);\
|
|
st.l r0, 0(r31);\
|
|
subs r0,reg,r16;\
|
|
st.l r16,32(r31);\
|
|
st.l r0,36(r31)
|
|
|
|
_ascaninit::
|
|
// ixfr r16, r_lo
|
|
|
|
// mov slope_table, r31
|
|
// st_slope (indz)
|
|
// addu 8,r31,r31
|
|
// st_slope (indr)
|
|
// addu 8,r31,r31
|
|
// st_slope (indg)
|
|
// addu 8,r31,r31
|
|
// st_slope (indb)
|
|
// fxfr r_lo, r16
|
|
|
|
adds -1,r0,r31
|
|
ixfr r31,fminus1
|
|
addu indr,indr,itemp1
|
|
ixfr itemp1, dr_lo
|
|
|
|
addu indg,indg,itemp1
|
|
ixfr itemp1, dg_lo
|
|
|
|
addu indb,indb,itemp1
|
|
ixfr itemp1, db_lo
|
|
|
|
addu indz,indz,itemp1
|
|
ixfr itemp1, dz_lo
|
|
|
|
fmov.ss dr_lo,dr_hi
|
|
fmov.ss dg_lo,dg_hi
|
|
fmov.ss db_lo,db_hi
|
|
fmov.ss dz_lo,dz_hi
|
|
bri r1
|
|
nop
|
|
|
|
#undef indr
|
|
#undef indg
|
|
#undef indb
|
|
#undef indz
|
|
#undef itemp1
|
|
//}}}
|
|
//{{{ atexinit ( int idu, int idv, int compat, int idz )
|
|
|
|
.globl _atexinit
|
|
.align 8
|
|
|
|
#define indu param8
|
|
#define indv param9
|
|
#define tx_and_or_mask param10
|
|
#define indz param11
|
|
#define itemp1 r31
|
|
|
|
_atexinit::
|
|
// build dr*2 dg*2 dz*2
|
|
adds -1,r0,r31
|
|
ixfr r31,fminus1
|
|
adds indu, indu,itemp1
|
|
and 0xffff, itemp1,itemp1
|
|
ixfr itemp1, du_lo
|
|
ixfr itemp1, du_hi
|
|
|
|
adds indv, indv,itemp1
|
|
and 0xffff, itemp1,itemp1
|
|
ixfr itemp1, dv_lo
|
|
ixfr itemp1, dv_hi
|
|
|
|
adds indz,indz,itemp1
|
|
ixfr itemp1, dz_lo // dz_lo=2*idz
|
|
ixfr itemp1, dz_hi // dz_lo=2*idz
|
|
|
|
bri r1
|
|
ixfr param10, db_lo
|
|
|
|
#undef indu
|
|
#undef indv
|
|
#undef indz
|
|
#undef tx_and_or_mask
|
|
#undef itemp1
|
|
//}}}
|
|
|
|
//{{{ texinit256 ( int idu, int idv, int compat, int idz )
|
|
|
|
.globl _texinit256
|
|
.align 8
|
|
|
|
#define indu param1
|
|
#define indv param2
|
|
#define tx_and_or_mask param3
|
|
#define indz param4
|
|
#define itemp1 param5
|
|
|
|
_texinit256::
|
|
// build dr*2 dg*2 dz*2
|
|
adds indu, indu,itemp1
|
|
ixfr itemp1, du_lo
|
|
ixfr itemp1, du_hi
|
|
|
|
adds indv, indv,itemp1
|
|
ixfr itemp1, dv_lo
|
|
ixfr itemp1, dv_hi
|
|
|
|
adds indz,indz,itemp1
|
|
ixfr itemp1, dz_lo // dz_lo=2*idz
|
|
ixfr itemp1, dz_hi // dz_lo=2*idz
|
|
|
|
shr 16, tx_and_or_mask,itemp1
|
|
andh 0xffff, tx_and_or_mask, r31
|
|
or r16,r31,r31
|
|
ixfr r31, db_hi
|
|
|
|
and 0xffff, tx_and_or_mask, r31
|
|
shl 16, tx_and_or_mask,itemp1
|
|
or r16,r31,r31
|
|
ixfr r31, db_lo
|
|
|
|
bri r1
|
|
nop
|
|
|
|
#undef indu
|
|
#undef indv
|
|
#undef indz
|
|
#undef tx_and_or_mask
|
|
#undef itemp1
|
|
//}}}
|
|
|
|
//{{{ scanline ( int *fb, int *zb, int ir, int ig, int ib, int iz, int dx, int safeload )
|
|
|
|
.globl _scanline
|
|
.align 8
|
|
|
|
#define paddr param1
|
|
#define zaddr param2
|
|
#define ir param3
|
|
#define ig param4
|
|
#define ib param5
|
|
#define iz param6
|
|
#define dx param7
|
|
#define idr param8
|
|
#define idg param9
|
|
#define idb param10
|
|
#define idz param11
|
|
|
|
// WARNING - itemp1 and itemp3 overload ir and ig - be careful
|
|
|
|
#define itemp1 param3
|
|
#define itemp3 param4
|
|
#define minus1 itemp1
|
|
|
|
_scanline:
|
|
|
|
and 4,paddr,r0 // if paddr&4 == 0, cc set
|
|
bc .aligned // so we jump if paddr&4==0, i.e aligned
|
|
|
|
.unaligned: // ie first pixel NOT on a 64-bit boundary
|
|
//{{{
|
|
// ir corresponds to high word of 64-bit pair, so we down tick to
|
|
// get ir_lo etc.
|
|
//
|
|
// align to double boundary
|
|
//
|
|
|
|
|
|
addu -12, zaddr, zaddr
|
|
fld.d 8(zaddr), oldz // load zbuffer value (from &z0-4)
|
|
addu -12, paddr, paddr
|
|
|
|
ixfr ir, r_hi
|
|
ixfr ig, g_hi
|
|
ixfr ib, b_hi
|
|
ixfr iz, z_hi
|
|
|
|
// construct lo word of rgbz by subtraction
|
|
|
|
subu ir, idr, r31
|
|
ixfr r31, r_lo
|
|
subu ig, idg, r31
|
|
ixfr r31, g_lo
|
|
subu ib, idb, r31
|
|
ixfr r31, b_lo
|
|
subu iz, idz, r31
|
|
|
|
adds -1,r0,minus1
|
|
fmov.ss fminus1, z_lo // important - zlo MUST be invisible for fchkz
|
|
adds 1,dx,dx // tick count
|
|
|
|
fzchkl oldz,z,nuz // z-check with frigged z
|
|
ixfr r31, z_lo // correct z
|
|
br .aligned_path
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
//}}}
|
|
.aligned: // ie first pixel IS on a 64-bit boundary
|
|
//{{{
|
|
//
|
|
// write iz into dbl z lo, iz+dz into dbl z hi etc
|
|
//
|
|
addu -8, zaddr, zaddr
|
|
fld.d 8(zaddr), oldz // load zbuffer value HOURS to complete
|
|
addu -8, paddr, paddr
|
|
|
|
|
|
ixfr ir, r_lo
|
|
ixfr ig, g_lo
|
|
ixfr ib, b_lo
|
|
ixfr iz, z_lo
|
|
|
|
addu ib, idb, r31
|
|
ixfr r31, b_hi
|
|
addu ig, idg, r31
|
|
ixfr r31, g_hi
|
|
addu ir, idr, r31
|
|
ixfr r31, r_hi
|
|
addu iz, idz, r31
|
|
ixfr r31, z_hi
|
|
|
|
adds -1,r0,minus1
|
|
|
|
.dual
|
|
fzchkl oldz,z,nuz // z-check with unfrigged z
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
|
|
.aligned_path:
|
|
|
|
faddp b,f0,f0
|
|
or r0,dx,r31 // r31 = orig dx
|
|
faddp g,f0,f0
|
|
shr 1,dx,dx // dx now n of 2s
|
|
faddp r,f0,f0
|
|
adds -2, r31, r0 // goto last 4 if dx < 2
|
|
form f0,col
|
|
bc .last_few
|
|
fnop
|
|
adds -1,dx,dx // corrected for autoincrement, so test -3 below
|
|
fnop
|
|
bla minus1, dx, .inner_loop
|
|
//}}}
|
|
|
|
//{{{ 32-bit z, 32-bit pixel inner loop OPENED out in 2s
|
|
.inner_loop_db:
|
|
fzchks f0,f0,f0
|
|
nop
|
|
.inner_loop:
|
|
fzchkl f0,f0,f0
|
|
fst.d nuz, 8(zaddr)++
|
|
faddz z,dz,z
|
|
nop
|
|
faddp b,db,b
|
|
pst.d col, 8(paddr)++
|
|
faddp g,dg,g
|
|
nop
|
|
faddp r,dr,r
|
|
fld.d 8(zaddr), oldz
|
|
form f0,col
|
|
bla minus1,dx,.inner_loop_db
|
|
fzchkl oldz,z,nuz
|
|
or r0,itemp3,r0 // for exit condition code
|
|
form f0,f0
|
|
bc .zb_exit
|
|
//}}}
|
|
|
|
//{{{ there is just 1 pixel to go
|
|
//
|
|
// this is fortunate - if pixels left = 1, then we CANT have a -1
|
|
// mask in z_lo, since it would have bumped dx to 2
|
|
//
|
|
// we only enter here if pixels == 1 and that pixel is on screen
|
|
// so we unconditionally mask off hi word, re-execute the fzchkl
|
|
// and proceed
|
|
//
|
|
|
|
.last_few:
|
|
fmov.ss fminus1,z_hi
|
|
nop
|
|
fzchkl oldz,z,nuz
|
|
nop
|
|
fzchks f0,f0,f0 // trash 4 PM bits
|
|
fst.d nuz, 8(zaddr)++
|
|
.enddual
|
|
fzchkl f0,f0,f0 // and 2 more PM bits
|
|
bri r1
|
|
fnop
|
|
pst.d col, 8(paddr)++
|
|
|
|
.zb_exit::
|
|
fnop
|
|
bri r1
|
|
fnop
|
|
nop
|
|
//}}}
|
|
|
|
#undef paddr
|
|
#undef zaddr
|
|
#undef ir
|
|
#undef ig
|
|
#undef ib
|
|
#undef iz
|
|
#undef dx
|
|
#undef idr
|
|
#undef idg
|
|
#undef idb
|
|
#undef idz
|
|
#undef itemp1
|
|
#undef itemp2
|
|
#undef itemp3
|
|
#undef minus1
|
|
//}}}
|
|
//{{{ flatline ( int *fb, int *zb, int ir, int ig, int ib, int iz, int dx, int safeload )
|
|
|
|
.globl _flatline
|
|
.align 8
|
|
|
|
#define paddr param1
|
|
#define zaddr param2
|
|
#define ir param3
|
|
#define ig param4
|
|
#define ib param5
|
|
#define iz param6
|
|
#define dx param7
|
|
#define idr param8
|
|
#define idg param9
|
|
#define idb param10
|
|
#define idz param11
|
|
|
|
// WARNING - itemp1 and itemp3 overload ir and ig - be careful
|
|
|
|
#define itemp1 param3
|
|
#define itemp3 param4
|
|
#define minus1 itemp1
|
|
|
|
_flatline:
|
|
|
|
ixfr ir, r_hi
|
|
ixfr ig, g_hi
|
|
ixfr ib, b_hi
|
|
fmov.ss r_hi, r_lo
|
|
fmov.ss g_hi, g_lo
|
|
fmov.ss b_hi, b_lo
|
|
|
|
and 4,paddr,r0 // if paddr&4 == 0, cc set
|
|
bc .faligned // so we jump if paddr&4==0, i.e aligned
|
|
|
|
.funaligned: // ie first pixel NOT on a 64-bit boundary
|
|
//{{{
|
|
// ir corresponds to high word of 64-bit pair, so we down tick to
|
|
// get ir_lo etc.
|
|
//
|
|
// align to double boundary
|
|
//
|
|
|
|
addu -12, zaddr, zaddr
|
|
addu -12, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value (from &z0-4)
|
|
|
|
ixfr iz, z_hi
|
|
|
|
// construct lo word of rgbz by subtraction
|
|
|
|
subu iz, idz, r31
|
|
|
|
adds -1,r0,minus1
|
|
fmov.ss fminus1, z_lo // important - zlo MUST be invisible for fchkz
|
|
adds 1,dx,dx // tick count
|
|
|
|
fzchkl oldz,z,nuz // z-check with frigged z
|
|
ixfr r31, z_lo // correct z
|
|
br .faligned_path
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
//}}}
|
|
.faligned: // ie first pixel IS on a 64-bit boundary
|
|
//{{{
|
|
//
|
|
// write iz into dbl z lo, iz+dz into dbl z hi etc
|
|
//
|
|
addu -8, zaddr, zaddr
|
|
addu -8, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value HOURS to complete
|
|
|
|
ixfr iz, z_lo
|
|
|
|
addu iz, idz, r31
|
|
|
|
ixfr r31, z_hi // this needs 3 cycles to complete before fzchkl
|
|
|
|
adds -1,r0,minus1
|
|
|
|
.dual
|
|
fzchkl oldz,z,nuz // z-check with unfrigged z
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
|
|
.faligned_path:
|
|
|
|
faddp b,f0,f0
|
|
or r0,dx,r31 // r31 = orig dx
|
|
faddp g,f0,f0
|
|
shr 1,dx,dx // dx now n of 4s
|
|
faddp r,f0,f0
|
|
adds -2, r31, r0 // goto last 4 if dx < 2
|
|
form f0,col
|
|
bc .flast_few
|
|
fnop
|
|
adds -1,dx,dx // corrected for autoincrement, so test -3 below
|
|
fnop
|
|
bla minus1, dx, .finner_loop
|
|
//}}}
|
|
|
|
//{{{ 32-bit z, 32-bit flat shaded pixel inner loop OPENED out in 2s
|
|
.finner_loop_db:
|
|
fzchks f0,f0,f0
|
|
fst.d nuz, 8(zaddr)++
|
|
.finner_loop:
|
|
fzchkl f0,f0,f0
|
|
fld.d 8(zaddr), oldz
|
|
faddz z,dz,z
|
|
pst.d col, 8(paddr)++
|
|
fnop
|
|
bla minus1,dx,.finner_loop_db
|
|
fzchkl oldz,z,nuz
|
|
or r0,itemp3,r0 // for exit condition code
|
|
// weve exited the loop here
|
|
form f0,f0
|
|
bc .fzb_exit
|
|
//}}}
|
|
|
|
//{{{ there is just 1 pixel to go
|
|
//
|
|
// this is fortunate - if pixels left = 1, then we CANT have a -1
|
|
// mask in z_lo, since it would have bumped dx to 2
|
|
//
|
|
// we only enter here if pixels == 1 and that pixel is on screen
|
|
// so we unconditionally mask off hi word, re-execute the fzchkl
|
|
// and proceed
|
|
//
|
|
|
|
.flast_few:
|
|
fmov.ss fminus1, z_hi
|
|
nop
|
|
pfzchkl oldz,z,f0 // nuz
|
|
nop
|
|
pfzchks f0,f0,nuz // trash 4 PM bits
|
|
fst.d nuz, 8(zaddr)++
|
|
.enddual
|
|
pfzchkl f0,f0,f0 // and 2 more PM bits
|
|
bri r1
|
|
fnop
|
|
pst.d col, 8(paddr)++
|
|
.fzb_exit:
|
|
fnop
|
|
bri r1
|
|
fnop
|
|
nop
|
|
//}}}
|
|
|
|
#undef paddr
|
|
#undef zaddr
|
|
#undef ir
|
|
#undef ig
|
|
#undef ib
|
|
#undef iz
|
|
#undef dx
|
|
#undef idr
|
|
#undef idg
|
|
#undef idb
|
|
#undef idz
|
|
#undef itemp1
|
|
#undef itemp2
|
|
#undef itemp3
|
|
#undef minus1
|
|
//}}}
|
|
//{{{ ftexline ( *fb, *zb, u, v, *tb, z, dx, du, dv, DUMMY ,dz )
|
|
.globl _ftexline
|
|
.align 8
|
|
|
|
#define paddr param1
|
|
#define zaddr param2
|
|
#define iu param3
|
|
#define iv param4
|
|
#define texbase param5
|
|
#define iz param6
|
|
#define dx param7
|
|
#define idu param8
|
|
#define idv param9
|
|
#define itemp1 param10
|
|
#define idz param11
|
|
#define itemp3 param3
|
|
#define itemp4 param4
|
|
#define minus1 itemp1
|
|
|
|
// WARNING - itemp3 and itemp4 overload ir and ig - be careful
|
|
|
|
_ftexline::
|
|
|
|
fxfr db_lo,texbase
|
|
and 4,paddr,r0 // if paddr&7 == 0, cc set
|
|
bc .txaligned // so we jump if paddr&7==0, i.e aligned
|
|
|
|
.txunaligned: // ie first pixel NOT on a 64-bit boundary
|
|
//{{{
|
|
// align to double boundary
|
|
|
|
adds -12, zaddr, zaddr
|
|
adds -12, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value (from &z0-4)
|
|
|
|
// correct for interpolant over-tick - first u,v
|
|
|
|
subs iu, idu, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, u_lo
|
|
|
|
and 0xffff,iu,r31
|
|
ixfr r31, u_hi
|
|
|
|
subs iv, idv, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, v_lo
|
|
|
|
and 0xffff,iv,r31
|
|
ixfr r31, v_hi
|
|
|
|
ixfr iz, z_hi
|
|
|
|
adds -1,r0,minus1
|
|
fmov.ss fminus1, z_lo // important - zlo MUST be invisible for fchkz
|
|
|
|
adds 1,dx,dx // tick count
|
|
|
|
fzchkl oldz,z,nuz // z-check with frigged z
|
|
subs iz, idz, r31
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
br .txaligned_path
|
|
ixfr r31, z_lo // correct z
|
|
//}}}
|
|
.txaligned: // ie first pixel IS on a 64-bit boundary
|
|
//{{{
|
|
//
|
|
// write iz into dbl z lo, iz+dz into dbl z hi etc
|
|
//
|
|
adds -8, zaddr, zaddr
|
|
adds -8, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value HOURS to complete
|
|
|
|
ixfr iz, z_lo
|
|
adds iz, idz, r31
|
|
ixfr r31, z_hi // this needs 3 cycles to complete before fzchkl
|
|
|
|
and 0xffff,iu,r31
|
|
ixfr r31, u_lo
|
|
addu iu, idu, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, u_hi
|
|
|
|
and 0xffff,iv,r31
|
|
ixfr r31, v_lo
|
|
addu iv, idv, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, v_hi
|
|
|
|
adds -1,r0,minus1
|
|
|
|
.dual
|
|
fzchkl oldz,z,nuz // z-check with unfrigged z
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
|
|
//}}}
|
|
.txaligned_path: // above branches re-merge here
|
|
//{{{
|
|
form f0,f0 // clear merge to start up
|
|
or r0,dx,r31 // r31 = orig dx
|
|
faddp u,f0,f0
|
|
shr 1,dx,dx // dx now n of 2s
|
|
faddp v,f0,f0
|
|
adds -2, r31, r0 // goto last few if dx < 2
|
|
form f0,col
|
|
bc .txlast_few
|
|
fnop
|
|
adds -1,dx,dx // corrected for autoincrement, so test -3 below
|
|
fnop
|
|
bla minus1, dx, .txinner_loop
|
|
//}}}
|
|
|
|
//{{{ 32-bit z, texture inner loop, 2 pixels at a time
|
|
.txinner_loop_db:
|
|
fxfr col_lo,r31 // r31 = low pixel interpolated u,v
|
|
fst.d nuz, 8(zaddr) // IMPORTANT - we cannot auto-increment
|
|
.txinner_loop:
|
|
fxfr col_hi,itemp4 // in same cycle as fxfr ! ! ! ! !
|
|
fld.d 16(zaddr), oldz
|
|
faddz z,dz,z
|
|
shr 2,r31,r31 // drop 2 of 4 blue bits, i.e word address
|
|
fzchks f0,f0,f0 // drop 4 more PM bits
|
|
shr 2,itemp4,itemp4
|
|
fzchkl f0,f0,f0 // drop 2 more PM bits
|
|
fld.l texbase(r31),dbltmp_lo
|
|
faddp u,du,u
|
|
fld.l texbase(itemp4),dbltmp_hi
|
|
faddp v,dv,v
|
|
addu 8,zaddr,zaddr // see note on zaddr++ above
|
|
fnop
|
|
ld.c psr,r31 // r31 holds 16-bit pixel size
|
|
form f0,col // and merge the colour ready for next
|
|
xorh 0x00c0,r31,itemp4 // 0xc flips 32-16
|
|
fnop // itemp4 holds 32-bit pixelsize
|
|
st.c itemp4, psr // goto 32 bits
|
|
fnop
|
|
pst.d dbltmp, 8(paddr)++ // do pixel store
|
|
fnop
|
|
st.c r31, psr // and go back to 16 bits
|
|
fnop
|
|
bla minus1,dx,.txinner_loop_db
|
|
fzchkl oldz,z,nuz
|
|
nop
|
|
// weve exited the loop here
|
|
fnop
|
|
or r0,itemp3,r0
|
|
fnop
|
|
bc .tx_exit
|
|
//}}}
|
|
//{{{ there is just 1 pixel to go - we have a good z in nuz, and 2 good cols
|
|
.txlast_few: // we CANNOT ixfr and fxfr
|
|
fmov.ss fminus1, z_hi
|
|
nop
|
|
fxfr col_lo,r31 // txtemp1 = interpolated u,v
|
|
nop
|
|
fzchkl oldz,z,nuz
|
|
shr 2,r31,r31
|
|
fzchks f0,f0,f0 // trash 4 PM bits
|
|
fld.l texbase(r31), col_lo
|
|
fzchkl f0,f0,f0 // and 2 more PM bits
|
|
fst.d nuz, 8(zaddr)++
|
|
fnop
|
|
ld.c psr,r31
|
|
fnop
|
|
xorh 0x00c0,r31,itemp4
|
|
fnop
|
|
st.c itemp4, psr
|
|
fnop
|
|
pst.d col, 8(paddr)++
|
|
fnop
|
|
st.c r31,psr
|
|
.tx_exit:
|
|
.enddual
|
|
form f0,f0
|
|
bri r1
|
|
form f0,f0
|
|
nop
|
|
|
|
|
|
//}}}
|
|
|
|
#undef paddr
|
|
#undef zaddr
|
|
#undef iu
|
|
#undef iv
|
|
#undef texbase
|
|
#undef iz
|
|
#undef dx
|
|
#undef idu
|
|
#undef idv
|
|
#undef idz
|
|
#undef itemp1
|
|
#undef itemp3
|
|
#undef itemp4
|
|
#undef txtemp1
|
|
#undef minus1
|
|
//}}}
|
|
//{{{ ftexline256 ( *fb, *zb, u, v, *tb, z, dx, du, dv, DUMMY ,dz )
|
|
.globl _ftexline256
|
|
.align 8
|
|
|
|
#define paddr param1
|
|
#define zaddr param2
|
|
#define iu param3
|
|
#define iv param4
|
|
#define texbase param5
|
|
#define iz param6
|
|
#define dx param7
|
|
#define idu param8
|
|
#define idv param9
|
|
#define itemp1 param10
|
|
#define idz param11
|
|
#define itemp3 param3
|
|
#define itemp4 param4
|
|
#define minus1 itemp1
|
|
|
|
// WARNING - itemp3 and itemp4 overload ir and ig - be careful
|
|
|
|
_ftexline256::
|
|
|
|
fxfr db_lo,texbase
|
|
and 4,paddr,r0 // if paddr&7 == 0, cc set
|
|
bc .txaligned256 // so we jump if paddr&7==0, i.e aligned
|
|
|
|
.txunaligned256: // ie first pixel NOT on a 64-bit boundary
|
|
//{{{
|
|
// align to double boundary
|
|
|
|
adds -12, zaddr, zaddr
|
|
adds -12, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value (from &z0-4)
|
|
|
|
// correct for interpolant over-tick - first u,v
|
|
|
|
subs iu, idu, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, u_lo
|
|
|
|
and 0xffff,iu,r31
|
|
ixfr r31, u_hi
|
|
|
|
subs iv, idv, r31
|
|
and 0xffff,r31,r31
|
|
ixfr r31, v_lo
|
|
|
|
and 0xffff,iv,r31
|
|
ixfr r31, v_hi
|
|
|
|
ixfr iz, z_hi
|
|
|
|
adds -1,r0,minus1
|
|
fmov.ss fminus1, z_lo // important - zlo MUST be invisible for fchkz
|
|
|
|
adds 1,dx,dx // tick count
|
|
|
|
fzchkl oldz,z,nuz // z-check with frigged z
|
|
subs iz, idz, r31
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
br .txaligned_path256
|
|
ixfr r31, z_lo // correct z
|
|
//}}}
|
|
.txaligned256: // ie first pixel IS on a 64-bit boundary
|
|
//{{{
|
|
//
|
|
// write iz into dbl z lo, iz+dz into dbl z hi etc
|
|
//
|
|
adds -8, zaddr, zaddr
|
|
adds -8, paddr, paddr
|
|
|
|
fld.d 8(zaddr), oldz // load zbuffer value HOURS to complete
|
|
|
|
ixfr iz, z_lo
|
|
adds iz, idz, r31
|
|
ixfr r31, z_hi // this needs 3 cycles to complete before fzchkl
|
|
|
|
ixfr iu, u_lo
|
|
addu iu, idu, r31
|
|
ixfr r31, u_hi
|
|
|
|
ixfr iv, v_lo
|
|
addu iv, idv, r31
|
|
ixfr r31, v_hi
|
|
|
|
adds -1,r0,minus1
|
|
|
|
.dual
|
|
fzchkl oldz,z,nuz // z-check with unfrigged z
|
|
and 1,dx,itemp3 // itemp3 = extras on rhs
|
|
|
|
//}}}
|
|
.txaligned_path256: // above branches re-merge here
|
|
//{{{
|
|
form f0,f0 // clear merge to start up
|
|
or r0,dx,r31 // r31 = orig dx
|
|
faddp u,f0,f0
|
|
shr 1,dx,dx // dx now n of 2s
|
|
faddp v,f0,f0
|
|
adds -2, r31, r0 // goto last few if dx < 2
|
|
form f0,col
|
|
bc .txlast_few256
|
|
fnop
|
|
adds -1,dx,dx // corrected for autoincrement, so test -3 below
|
|
fnop
|
|
bla minus1, dx, .txinner_loop256
|
|
//}}}
|
|
|
|
//{{{ 32-bit z, texture inner loop, 2 pixels at a time
|
|
.txinner_loop_db256:
|
|
fxfr col_lo,r31 // r31 = low pixel interpolated u,v
|
|
fst.d nuz, 8(zaddr) // IMPORTANT - we cannot auto-increment
|
|
.txinner_loop256:
|
|
fxfr col_hi,itemp4 // in same cycle as fxfr ! ! ! ! !
|
|
fld.d 16(zaddr), oldz
|
|
faddz z,dz,z
|
|
shr 6,r31,r31 // drop 6 of 8 blue bits, i.e word address
|
|
fzchks f0,f0,f0 // drop 4 more PM bits
|
|
shr 6,itemp4,itemp4
|
|
fzchkl f0,f0,f0 // drop 2 more PM bits
|
|
fld.l texbase(r31),dbltmp_lo
|
|
faddp u,du,u
|
|
fld.l texbase(itemp4),dbltmp_hi
|
|
faddp v,dv,v
|
|
addu 8,zaddr,zaddr // see note on zaddr++ above
|
|
form f0,col // and merge the colour ready for next
|
|
pst.d dbltmp, 8(paddr)++ // do pixel store
|
|
fnop
|
|
bla minus1,dx,.txinner_loop_db256
|
|
fzchkl oldz,z,nuz
|
|
nop
|
|
// weve exited the loop here
|
|
fnop
|
|
or r0,itemp3,r0
|
|
fnop
|
|
bc .tx_exit256
|
|
//}}}
|
|
//{{{ there is just 1 pixel to go - we have a good z in nuz, and 2 good cols
|
|
.txlast_few256: // we CANNOT ixfr and fxfr
|
|
fmov.ss fminus1, z_hi
|
|
nop
|
|
fxfr col_lo,r31 // txtemp1 = interpolated u,v
|
|
nop
|
|
fzchkl oldz,z,nuz
|
|
shr 6,r31,r31
|
|
fzchks f0,f0,f0 // trash 4 PM bits
|
|
fld.l texbase(r31), col_lo
|
|
fzchkl f0,f0,f0 // and 2 more PM bits
|
|
fst.d nuz, 8(zaddr)++
|
|
fnop
|
|
pst.d col, 8(paddr)++
|
|
.tx_exit256:
|
|
.enddual
|
|
form f0,f0
|
|
bri r1
|
|
form f0,f0
|
|
nop
|
|
|
|
|
|
//}}}
|
|
|
|
#undef paddr
|
|
#undef zaddr
|
|
#undef iu
|
|
#undef iv
|
|
#undef texbase
|
|
#undef iz
|
|
#undef dx
|
|
#undef idu
|
|
#undef idv
|
|
#undef idz
|
|
#undef itemp1
|
|
#undef itemp3
|
|
#undef itemp4
|
|
#undef txtemp1
|
|
#undef minus1
|
|
//}}}
|
|
|
|
//{{{ 32-bit z, 32-bit pixel inner loop OPENED out in 4s
|
|
// .inner4_loop:
|
|
// pfaddz z,dz,f0
|
|
// fld.d 16(zaddr), dbltemp
|
|
// pfzchkl dbltemp,z,z
|
|
// nop
|
|
// pfaddz z,dz,dbltemp
|
|
// fst.d nuz, 8(zaddr)
|
|
// pfzchkl f0,f0,z // now 4 pixels worth of mask is ready
|
|
// nop
|
|
// faddp b,db,b
|
|
// fst.d dbltemp, 16(zaddr)++
|
|
// faddp g,dg,g
|
|
// nop
|
|
// faddp r,dr,r
|
|
// pst.d col, 8(paddr)++
|
|
// form f0,col
|
|
// nop
|
|
// faddp b,db,b
|
|
// nop // adds -4, dx, dx
|
|
// faddp g,dg,g
|
|
// pst.d col, 8(paddr)++
|
|
// faddp r,dr,r
|
|
// nop
|
|
// form f0,col
|
|
// bla minus1,dx,.inner4_loop // bnc.t .inner4_loop
|
|
// fzchkl oldz,z,nuz
|
|
// nop
|
|
// // weve exited the loop here
|
|
// fnop
|
|
// or r0,itemp3,r0 // for exit condition code
|
|
// fnop
|
|
// bc .zb_exit
|
|
//}}}
|
|
//{{{ 32-bit z, flat pixel inner loop OPENED out in 4s
|
|
// .flat4_loop:
|
|
// pfaddz z,dz,f0
|
|
// fld.d 16(zaddr), dbltemp
|
|
// pfzchkl dbltemp,z,z
|
|
// fst.d nuz, 8(zaddr)
|
|
// pfaddz z,dz,dbltemp
|
|
// nop
|
|
// pfzchkl f0,f0,z // now 4 pixels worth of mask is ready
|
|
// fst.d dbltemp, 16(zaddr)++
|
|
// fnop
|
|
// pst.d col, 8(paddr)++
|
|
// fnop
|
|
// pst.d col, 8(paddr)++
|
|
// fnop
|
|
// bla minus1,dx,.flat4_loop
|
|
// fzchkl oldz,z,nuz
|
|
// nop
|
|
// // weve exited the loop here
|
|
// fnop
|
|
// or r0,itemp3,r0 // for exit condition code
|
|
// fnop
|
|
// bc .zb_exit
|
|
//}}}
|
|
|