// nicked from output of PGC Rel 1.4 -opt 2 .text .align 8 .text //{{{ Heavy description // // DIVISION pxpl5 support code // // over and above the normal transform / light / clip, pxpl5 // requires triangles to be prepared for display by converting them // into screen-space linear expressions. Both scan-conversion and shading // information need to be so converted // // constructing linear expressions for scan-conversion is EDGIZing // constructing linear expressions for shading is PLANARIZing // putting triangles into 64x128 pixel bins is BINITIZing // // these are some optimized routines for edgizing, planarizing and // binitizing // // it is clear that this software is just not fast enough when coded in C for // 2 reasons - inefficient register usage (crap compiler) and excessive memory // hits. Memory hits occur at function calls, where stack frames are moved // and registers saved away to adhere to C calling conventions - lets trash // the calling conventions (and make this undebuggable!) // // The functions below are very optimized to NEVER hit memory. The price // we pay is that they are not directly callable in C - the C-callable // code is in pxpl5tri.ss, and is a bunch of triangle functions, which // save away volatile registers, chain together calls to these functions, // then restore registers and return // // HOWEVER - note safe_binitize_fn, which every 256 triangles or so is forced // to call some C, and which may under worst-case circumstances call malloc. // dont be scared, it works // // depressing timings - the gayboy coding of planarize executes in 116 ticks, // the steroid-laden version 73 ticks - this is for 32 fpu ops. So, I // shall make this even worse, by introducing a zbuf_plus2_fn, which // both z-buffers, AND planarizes 2 other functions at the same time. This // can take advantage of the 3-ness of the i860 pipe by unrolling 3 // planarizations at once. It is also optimized for the PAZ primitive of // z-buffer, luminance, specularity - using z-buffer, planar, planar I get // 97k triangles/sec .. lets try to get 130k from zbuf_plus2_fn // // oh rats - the VERTEX and NORM_COL are now separated in memory - I need to // pass in offset from Z, otherOffset from Z into z_buf_plus2 // // define some useful registers, which are // pointers to 4 vertices rv1 .. rv4 // 4 x coordinates fx1 .. fx4 // 4 y coordinates fy1 .. fy4 // 3 value coordinates fv1 .. fv3 // minimaxes fminx, fminy, fmaxx, fmaxy // repeated expressions fx23, fx31, fx12, fC //}}} // // // integer registers first // // // // // // fp registers // // // screen-space minimax for binitizing // PASS NO FLOAT PARAMETERS IN HERE OR YOU ARE S T U F F E D // // x, y coords for tris/quads // repeated expressions fx32, fx13, fx21, fC // screen-space function values for planarizing //{{{ some housekeeping code //{{{ tex_scalefac .globl _tex_scalefac .align 8 _tex_scalefac:: // // f8 , 2, 3 hold 3 z values - find which is biggest, scale // it up to have no leading zeros, return scale factor (1.0, 2.0 etc) // sign bit guaranteed not set // z not yet munged by scale bits, so z in range 0.0 .. 1.0 // biggest test is easy - fxfr to integer registers, // do integer compare to determine biggest // extract exponent from biggest, all 3 zs // // use r31 to hold max, use int parameter registers as temporaries // // this would appear to take 16ish ticks // fxfr f8 , r16 fxfr f9 , r17 fxfr f10 , r18 subs r16 , r17 , r0 bc i2_gt_i1 subs r16 , r18 , r0 bnc.t igotmax mov r16 , r31 br igotmax mov r18 , r31 i2_gt_i1:: subs r17 , r18 , r0 bnc.t igotmax mov r17 , r31 br igotmax mov r18 , r31 igotmax:: // // compute exponent difference between 0.999 and max // // dont worry, its just IEEE-754 - read the i860 databook // // warning - it may fall down in a heap if we ever give it // a denormal, so just set the far clipping plane somewhere // sensible - i will work out where // andh 0x7f80, r31, r31 // extract exponent of max orh 0x7e80, r0, r16 subu r16 , r31, r31 // and we have magic bri r1 ixfr r31, f8 //}}} //{{{ _trunc_test ( int *truncy, float a, float b, float c ) .globl _trunc_test .align 8 _trunc_test:: adds -64, sp, sp fst.d f2, 0(sp) fst.d f4, 8(sp) fst.d f6, 16(sp) fst.d f8, 24(sp) st.l r4, 28(sp) st.l r5, 32(sp) st.l r6, 36(sp) pftrunc.sd f8, f0 pftrunc.sd f9, f0 pftrunc.sd f10, f0 pfadd.sd f0, f0, f2 pfadd.sd f0, f0, f4 pfadd.sd f0, f0, f6 fxfr f2, r4 fxfr f4, r5 fxfr f6, r6 st.l r4, 0(r16) st.l r5, 4(r16) st.l r6, 8(r16) fld.d 0(sp), f2 fld.d 8(sp), f4 fld.d 16(sp), f6 fld.d 24(sp), f8 ld.l 28(sp), r4 ld.l 32(sp), r5 ld.l 36(sp), r6 bri r1 adds 64, sp, sp //}}} //{{{ give_fp returns value of frame pointer .globl _give_fp .align 8 // binitize a primitive _give_fp:: bri r1 addu r0, r3, r16 //}}} //{{{ give_stepping .globl _give_stepping .align 8 _give_stepping:: ld.c epsr, r16 shr 8, r16, r16 bri r1 and 0x1f, r16, r16 //}}} //{{{ give_860type .globl _give_860type .align 8 _give_860type:: ld.c epsr, r16 bri r1 and 0xff, r16, r16 //}}} //}}} // // these are the function prototypes // // extern void preplanarize_fn ( float *coeffs, VERTEX *v1, VERTEX *v2, VERTEX *v3, VERTEX *v4 ); // extern void edgize_tri_fn ( void ); // extern void edgize_quad_fn ( void ); // extern void zbuffer_fn ( void ); // extern void zb_plus2_fn ( void ); // extern void planarize_fn ( int pp5_opcode, int index ); // extern void binitize_fn ( int macro_lo, int macro_hi, // int scrmaxx, int scrmaxy, int scrbinsx ) // extern void safe_binitize_fn ( int macro_lo, int macro_hi, int scrbinsx ) // //{{{ fsr access // .globl _getFsr // .align 8 //_getFsr:: // bri r1 // ld.c fsr, r16 // // // .globl _setFsr // .align 8 //_setFsr:: // bri r1 // st.c r16, fsr //}}} //{{{ _reg_dump .globl _reg_dump .align 8 _reg_dump:: //{{{ proc entry - save r1 r2 r3 addu -256, sp, sp st.l r1,0(sp) adds 256,sp,r1 // save r2 **before** call into stack frame st.l r1,4(sp) st.l fp,8(sp) //}}} //{{{ save r4..r31, f2..f31 st.l r4, 12(sp) st.l r5, 16(sp) st.l r6, 20(sp) st.l r7, 24(sp) st.l r8, 28(sp) st.l r9, 32(sp) st.l r10, 36(sp) st.l r11, 40(sp) st.l r12, 44(sp) st.l r13, 48(sp) st.l r14, 52(sp) st.l r15, 56(sp) st.l r16, 60(sp) //st.l r17, 64(sp) st.l r18, 68(sp) st.l r19, 72(sp) st.l r20, 76(sp) st.l r21, 80(sp) st.l r22, 84(sp) st.l r23, 88(sp) st.l r24, 92(sp) st.l r25, 96(sp) st.l r26, 100(sp) st.l r27, 104(sp) st.l r28, 108(sp) st.l r29, 112(sp) st.l r30, 116(sp) st.l r31, 120(sp) adds 120, sp, sp fst.l f2, 4(sp)++ fst.l f3, 4(sp)++ fst.l f4, 4(sp)++ fst.l f5, 4(sp)++ fst.l f6, 4(sp)++ fst.l f7, 4(sp)++ fst.l f8, 4(sp)++ fst.l f9, 4(sp)++ fst.l f10, 4(sp)++ fst.l f11, 4(sp)++ fst.l f12, 4(sp)++ fst.l f13, 4(sp)++ fst.l f14, 4(sp)++ fst.l f15, 4(sp)++ fst.l f16, 4(sp)++ fst.l f17, 4(sp)++ fst.l f18, 4(sp)++ fst.l f19, 4(sp)++ fst.l f20, 4(sp)++ fst.l f21, 4(sp)++ fst.l f22, 4(sp)++ fst.l f23, 4(sp)++ fst.l f24, 4(sp)++ fst.l f25, 4(sp)++ fst.l f26, 4(sp)++ fst.l f27, 4(sp)++ fst.l f28, 4(sp)++ fst.l f29, 4(sp)++ fst.l f30, 4(sp)++ fst.l f31, 4(sp)++ adds -240, sp, sp //}}} call _trace_regs mov sp, r16 //{{{ restore all ld.l 12(sp) , r4 ld.l 16(sp) , r5 ld.l 20(sp) , r6 ld.l 24(sp) , r7 ld.l 28(sp) , r8 ld.l 32(sp) , r9 ld.l 36(sp) , r10 ld.l 40(sp) , r11 ld.l 44(sp) , r12 ld.l 48(sp) , r13 ld.l 52(sp) , r14 ld.l 56(sp) , r15 ld.l 60(sp) , r16 ld.l 64(sp) , r17 ld.l 68(sp) , r18 ld.l 72(sp) , r19 ld.l 76(sp) , r20 ld.l 80(sp) , r21 ld.l 84(sp) , r22 ld.l 88(sp) , r23 ld.l 92(sp) , r24 ld.l 96(sp) , r25 ld.l 100(sp) , r26 ld.l 104(sp) , r27 ld.l 108(sp) , r28 ld.l 112(sp) , r29 ld.l 116(sp) , r30 ld.l 120(sp) , r31 adds 120, sp, sp fld.l 4(sp)++, f2 fld.l 4(sp)++, f3 fld.l 4(sp)++, f4 fld.l 4(sp)++, f5 fld.l 4(sp)++, f6 fld.l 4(sp)++, f7 fld.l 4(sp)++, f8 fld.l 4(sp)++, f9 fld.l 4(sp)++, f10 fld.l 4(sp)++, f11 fld.l 4(sp)++, f12 fld.l 4(sp)++, f13 fld.l 4(sp)++, f14 fld.l 4(sp)++, f15 fld.l 4(sp)++, f16 fld.l 4(sp)++, f17 fld.l 4(sp)++, f18 fld.l 4(sp)++, f19 fld.l 4(sp)++, f20 fld.l 4(sp)++, f21 fld.l 4(sp)++, f22 fld.l 4(sp)++, f23 fld.l 4(sp)++, f24 fld.l 4(sp)++, f25 fld.l 4(sp)++, f26 fld.l 4(sp)++, f27 fld.l 4(sp)++, f28 fld.l 4(sp)++, f29 fld.l 4(sp)++, f30 fld.l 4(sp)++, f31 adds -240, sp, sp //}}} //{{{ proc exit ld.l 0(sp),r1 ld.l 8(sp),fp bri r1 addu 256, sp, sp //}}} //}}} // constant for 1/x code .data .align 8 .Cmax_x: // (0) .C640: .long 0x442fbf5c // 7.02989990E+02 .Cmax_y: // (0) .C480: .long 0x43ff7eb8 // 5.10989990E+02 .C00037: // (0) .long 0x40000000 // 2.00000000E+00 .C362436: // (0) .long 0x3ecccccd // 4.00000006E-01 .Czscale1024: // (0) .long 0x49800000 // 1.04857600E+06 .Czscale: // (0) .long 0x497fffff // 1.04857588E+06 .Ctexscale: // (0) .long 0x477fffff // 6.55359883E+04 .tri_entry: .string "triangle entry" .byte 0x0 .tri_preplanarize: .string "preplanarize" .byte 0x0 .tri_edgeized: .string "edgized triangle" .byte 0x0 .tri_zbufized: .string "zbuffered triangle" .byte 0x0 .tri_planarized: .string "planarized something" .byte 0x0 .preplane_gotc: .string "halfway thru preplane" .byte 0x0 .plane_loadedvs: .string "planarize - have loaded fv1 etc." .byte 0x0 .bini_full: .string "bin full" .byte 0x0 .bini_doneminimax: .string "binitize, done minimax" .byte 0x0 .bini_notfull: .string "bin not full" .byte 0x0 .bini_start: .string "bin start binitize" .byte 0x0 .bini_minimax: .string "bin got minimaxes" .byte 0x0 .bini_endfull: .string "end of bin full" .byte 0x0 .bini_more_x: .string "more than 1 x-bin" .byte 0x0 .bini_more_y: .string "more than 1 y-bin" .byte 0x0 .bini_x_loop: .string "x-loop in binitize" .byte 0x0 .bini_check_usage: .string "check usage count" .byte 0x0 .r5r6r7opcodes: .string "r5 r6 r7 have opcodes?" .byte 0x0 .bini_pipe_minimax: .string "computed minimax piped" .byte 0x0