// // // this is the fully working tristrip.ss from before // trapezoom // // Phil 14 April 1992 // // // // // // void tristrip ( void (*init)(int,int,int,int), // void (*scan)(int*,int*,int,int,int,int,int,int,int,int,int), // int *framebuffer, // int *zbuffer, // triangle *head, // int n_tris, // int processor_shift, // int processor_id, // int stride, // int pxlsize ) //{{{ register allocation // overload the processor id register with the r4 hop value //}}} //{{{ structure offsets //{{{ vertex offsets // typedef struct s_vert { // struct s_vert *next; // POINT position; // POINT planeEqn; // float snorm [3]; // float gnorm [3]; // float colour [3]; // float texcoords [2]; // } VERTEX; // from start of structure //}}} //{{{ triangle offsets (plane equation etc.) // typedef struct s_triangle { // struct s_triangle *next; // edge *edgy; // edge *ziggy; // int dr_by_dx; // int dg_by_dx; // int db_by_dx; // int dz_by_dx; // } triangle; //}}} //{{{ edge offsets // typedef struct struct_edge { // VERTEX *v0, *v1, *vmin, *vmax; // int dx_by_dy; // int dr_by_dy; // int dg_by_dy; // int db_by_dy; // int dz_by_dy; // } edge; //}}} //}}} //{{{ stack frame layout //}}} //{{{ temporary registers // head aliases r20 // n aliases r21 // e_ab aliases r22 // e_bc aliases r23 // e_ac aliases r24 // va aliases r25 // vb aliases r26 // vc safe // ledge aliases r9 // redge aliases r10 // aedge aliases r11 //}}} //{{{ bacon,lettuce,tomato //}}} .align 8 .text //{{{ _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 st.l r1,4(sp) st.l fp,8(sp) //}}} //{{{ save r4..r31 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) //}}} call _trace_regs mov sp, r16 //{{{ save r4..r31 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 //}}} //{{{ proc exit ld.l 0(sp),r1 ld.l 8(sp),fp bri r1 addu 256, sp, sp //}}} //}}} //{{{ call _reg_dump nop //}}} //{{{ _trapezoid that works ish // this coding vaguely works ... // .align 8 // // WORST CASE 28 ticks per line, NO MEMORY HITS! // // subs r4 , r3 ,r0 <-- now folded into main body code // _trapezoid:: // bnc .do_not_collect_200_pounds // ixfr r1,f4 // NOTE f2..f7 unused in inner loops r3 present ! // and r4 , r15 ,r31 // xor r31, r28 ,r0 // r31 == r4 & r15 - if r4 & r15 != r28 , DONT call // shra 16, r8 , r22 // .trap_loop: // bnc .skip_call // normally we DO skip the call // // shra 16, r7 ,r31 // r31 = xl // subs r22 ,r31, r22 // r22 = r8 - xl // subs 0,r31,r0 // carry clear if r22 >0 // shl 2,r31,r31 // doesnt affect carry, avoids freeze condition // bnc .skip_call // // prepare to call fn // adds r5 ,r31, r16 // adds r6 ,r31, r17 // // save volatile registers // ixfr r18 ,f2 // calli r29 // GO MAN GO // ixfr r19 ,f3 // // fxfr f3, r19 // fxfr f2, r18 // // .skip_call: // adds 1, r4 , r4 // adds r7 , r9 , r7 // adds r8 , r10 , r8 // adds r19 , r12 , r19 // adds r18 , r11 , r18 // adds r20 , r13 , r20 // adds r21 , r14 , r21 // and r4 , r15 , r31 // bnc .skip_bmp // skip the bump if r4 & r15 !=0 // // bump r5 , r6 // adds r5 , r30 , r5 // adds r6 , r30 , r6 // // .skip_bmp: // subs r4 , r3 ,r0 // now folded into main body code // shra 16, r8 , r22 // doenst affect carry flag, avoid bc.t freeze // bc.t .trap_loop // this exits on r4 > r3 // xor r31, r28 ,r0 // r31 == r4 & r15 - if r4 & r15 != r28 , DONT call // fxfr f4,r1 // .do_not_collect_200_pounds: // bri r1 // nop //}}} //{{{ _trapezoid //{{{ C coding of trapezoid (from tristrip.c) // // while ( r4 < r3 ) { // if (( r4 & r15 ) == r28 ) { // r31= r7 >>16; // r22 =( r8 >>16)-r31; // // if ( r22 > 0) { // /* save rgbz */ // (* r29 )( r5 +r31, r6 +r31, r18 , r19 , r20 , r21 , r22 , r23 , r24 , r25 , r26 ); // /* restore rgbz */ // } // } // // r7 += r9 ; r8 += r10 ; r18 += r11 ; r19 += r12 ; r20 += r13 ; r21 += r14 ; // // r4 ++; // // if (( r4 & r15 ) == 0) { // r5 += r30 ; // r6 += r30 ; // } // } //}}} .align 8 // WORST CASE 28 ticks per line, NO MEMORY HITS! // subs r4 , r3 ,r0 <-- now folded into main body code _trapezoid:: bnc .do_not_collect_200_pounds // // OK - we have some crapoid code here - all the processors walk up // all the scanlines, and check to see if this is their scanline // // so we need to modify this to - firstly get the real rgbzx by // walking up until ( r4 & r15 )== r28 // now we shift all the slopes up by pshift. // now we walk up r21 scanlines r3 a time, doing each line UNTIL ( r4 >= r3 ) // now we shift all the slopes back down, and carry on adding until // r4 == r3 . Then we exit. Slopes are as they were before the shift, we // are on the same scanline we would have been on. All should be well. // // ixfr r1,f4 // NOTE f2..f7 unused in inner loops r3 present ! // // while (( r4 & r15 ) != r28 ) { // r4 ++; // r7 += r22 ; // r8 += r23 ; // r18 +=dr; // r19 +=dg; // r20 +=db; // r21 +=dz; // if (( r4 & r15 )==0) { // r6 += r30 ; // r5 += r30 ; // } // } // r22 <<=2; // r23 <<=2; // dr<<=2; // dg<<=2; // db<<=2; // dz<<=2; // // while ( r4 < r3 ) { // scanline(); // r7 += r22 ; // r8 += r23 ; // r18 +=dr; // r19 +=dg; // r20 +=db; // r21 +=dz; // r6 += r30 ; // r5 += r30 ; // r4 +=hop; // } // // r22 >>=2; // r23 >>=2; // dr>>=2; // dg>>=2; // db>>=2; // dz>>=2; // // while ( r4 > r3 ) { // r7 -= r22 ; // r8 -= r23 ; // r18 -=dr; // r19 -=dg; // r20 -=db; // r21 -=dz; // } // // and r4 , r15 ,r31 xor r31, r28 ,r0 // r31 == r4 & r15 - if r4 & r15 != r28 , DONT call shra 16, r8 , r22 .trap_loop: bnc.t .skip_call1 // normally we DO skip the call adds 1, r4 , r4 shra 16, r7 ,r31 // r31 = xl subs r22 ,r31, r22 // r22 = r8 - xl subs 0, r22 ,r0 // carry clear if r22 >0 shl 2,r31,r31 // doesnt affect carry, avoids freeze condition bnc.t .skip_call1 adds 1, r4 , r4 // prepare to call fn adds r5 ,r31, r16 adds r6 ,r31, r17 // save volatile registers ixfr r18 ,f2 calli r29 // GO MAN GO ixfr r19 ,f3 fxfr f3, r19 fxfr f2, r18 .skip_call0: adds 1, r4 , r4 .skip_call1: adds r8 , r10 , r8 adds r19 , r12 , r19 adds r18 , r11 , r18 adds r20 , r13 , r20 adds r21 , r14 , r21 adds r7 , r9 , r7 and r4 , r15 , r31 bnc.t .skip_bmp1 // skip the bump if r4 & r15 !=0 subs r4 , r3 ,r0 // now folded into main body code // bump r5 , r6 adds r5 , r30 , r5 adds r6 , r30 , r6 .skip_bmp: subs r4 , r3 ,r0 // now folded into main body code .skip_bmp1: shra 16, r8 , r22 // doenst affect carry flag, avoid bc.t freeze bc.t .trap_loop // this exits on r4 > r3 xor r31, r28 ,r0 // r31 == r4 & r15 - if r4 & r15 != r28 , DONT call fxfr f4,r1 .do_not_collect_200_pounds: bri r1 nop //}}} //{{{ _trapezoom .align 8 // seems to be 24 ticks per line, no memory hits // subs r4 , r3 ,r0 <-- now folded into main body code // // // this is the zippywippy trapezoid which understands that it // has been given slopes shifted up by processor_shift // its only difference in behaviour is to add 'hop' to r4 rather // than 1. When r4 > r3 we exit, DOING NOTHING - the calling // code can then do smart things dependent on l/ r18 ness of the // replace edge etc. // // so our trapezoom algorithm is simply // // while ( r4 < r3 ) { // scanline(); // r7 += r22 ; // r8 += r23 ; // r18 +=dr; // r19 +=dg; // r20 +=db; // r21 +=dz; // r6 += r30 ; // r5 += r30 ; // r4 +=hop; // } // return ( r4 - r3 ); // _trapezoom:: bnc .exit_zoom // ixfr r1,f4 // NOTE f2..f7 unused in inner loops r3 present ! // shra 16, r8 , r22 .trapzoom_loop: shra 16, r7 ,r31 // r31 = xl subs r22 ,r31, r22 // r22 = r8 - xl subs 0, r22 ,r0 // carry clear if r22 >0 shl 2,r31,r31 // doesnt affect carry, avoids freeze condition bnc.t .skip_zoomcall adds r28 , r4 , r4 // prepare to call fn adds r5 ,r31, r16 adds r6 ,r31, r17 // save volatile registers ixfr r18 ,f2 calli r29 // GO MAN GO ixfr r19 ,f3 fxfr f3, r19 fxfr f2, r18 .skip_zoomcall: adds r8 , r10 , r8 adds r19 , r12 , r19 adds r18 , r11 , r18 adds r20 , r13 , r20 adds r21 , r14 , r21 adds r7 , r9 , r7 adds r5 , r30 , r5 adds r6 , r30 , r6 subs r4 , r3 ,r31 // now folded into main body code bc.t .trapzoom_loop // this exits on r4 > r3 shra 16, r8 , r22 // doesnt affect carry flag, avoid bc.t freeze // 24 ticks per scanline rendered.. fxfr f4,r1 // exit with r31 == r4 - r3 .exit_zoom: bri r1 nop //}}} //{{{ _setv // #define setv(yptr, atptr, l, r18 ,act) // r4 =yptr[Y]; // r9 =l; r10 = r18 ; activate_edge=act; // r3 =atptr[Y] // below are ordered to try and minimize freezes //}}} //{{{ _swap(p1,p2) // xor r9 , r10 , r9 ; // xor r9 , r10 , r10 ; // xor r9 , r10 , r9 //}}} //{{{ _astristrip .globl _astristrip .align 8 _astristrip:: //{{{ check for r21 > 0 subs r0, r21 , r0 bc .procentry bri r1 nop //}}} //{{{ proc entry .procentry: addu -160 , sp, sp st.l fp, 156 (sp) st.l r1, 152 (sp) //}}} //{{{ save r4..r15 st.l r4, 92 (sp) st.l r5, 88 (sp) st.l r6, 84 (sp) st.l r7, 80 (sp) st.l r8, 76 (sp) st.l r9, 72 (sp) st.l r10, 68 (sp) st.l r11, 64 (sp) st.l r12, 60 (sp) st.l r13, 56 (sp) st.l r14, 52 (sp) st.l r15, 48 (sp) //}}} //{{{ save f2..f7 fst.d f2, 40 (sp) fst.d f4, 32 (sp) fst.d f6, 24 (sp) //}}} //{{{ save and reorder params st.l r16 , 96 (sp) mov r17 , r29 st.l r18 , 44 (sp) st.l r19 , 16 (sp) st.l r20 , 108 (sp) st.l r21 , 104 (sp) st.l r22 , 100 (sp) mov r23 , r28 shl 2, r24 , r30 // fix stride for byte addressing or 1,r0,r31 shl r22 ,r31, r15 // 1 << r22 adds -1, r15 , r15 // r15 = (1<next; // edge *ab,*bc,*ac; // // ab= r20 ->ziggy; ac= r20 ->edgy; // bc= r21 ->ziggy; ld.l 108 (sp), r20 ld.l 0 ( r20 ), r21 st.l r21 , 108 (sp) // pre-walk triangle pointer ld.l 8 ( r20 ), r22 ld.l 4 ( r20 ), r24 ld.l 8 ( r21 ), r23 // /* there are only 3 cases - a lowest, b lowest, c lowest */ // { // int *a, * r20 , *c, *atp; // // // a=(int *) (&ab->v0->position); // r20 =(int *) (&ab->v1->position); // c=(int *) (&ac->v1->position); // ld.l 0 ( r22 ), r25 ld.l 4 ( r22 ), r26 ld.l 4 ( r24 ), r27 // if (a[Y] < r20 [Y]) { ld.l 8 ( r25 ), r16 ld.l 8 ( r26 ), r17 subs r0, r17 ,r31;adds r31, r16 ,r0;bnc .check_bc // if (c[Y] < a[Y]) { ld.l 8 ( r27 ), r17 subs r0, r16 ,r31;adds r31, r17 ,r0;bnc .a_lowest // atp=(int *) (&ab->vmin->position); // setv(c,atp,ac,bc,ab); // } .c_lowest: ld.l 8 ( r22 ), r31;mov r24 , r9 ;ld.l 8 ( r27 ), r4 ;mov r23 , r10 ;ld.l 8 (r31), r3 ;br .l_and_r_decision;mov r22 , r11 .a_lowest: // else { // atp=(int *) (&bc->vmin->position); // setv(a,atp,ac,ab,bc); // } // } ld.l 8 ( r23 ), r31;mov r24 , r9 ;ld.l 8 ( r25 ), r4 ;mov r22 , r10 ;ld.l 8 (r31), r3 ;br .l_and_r_decision;mov r23 , r11 .check_bc: // else { // if ( r20 [Y] < c[Y]) { ld.l 8 ( r27 ), r16 // since r20 still in r17 subs r0, r16 ,r31;adds r31, r17 ,r0;bnc .c_lowest // atp=(int *) (&ac->vmin->position); // setv( r20 ,atp,bc,ab,ac); // } ld.l 8 ( r24 ), r31;mov r23 , r9 ;ld.l 8 ( r26 ), r4 ;mov r22 , r10 ;ld.l 8 (r31), r3 ;br .l_and_r_decision;mov r24 , r11 // else { // atp=(int *) (&ab->vmin->position); // setv(c,atp,ac,bc,ab); // } // } // } // ld.l 8 ( r22 ), r31;mov r24 , r9 ;ld.l 8 ( r27 ), r4 ;mov r23 , r10 ;ld.l 8 (r31), r3 ;br .l_and_r_decision;mov r22 , r11 //}}} .l_and_r_decision: //{{{ now determine ABSOLUTELY SECURELY which edge is l and which is r18 // remember, we have not yet stored r9 / r10 / r11 into memory // if ( r9 ->dx_by_dy == MINT) { ld.l 16 ( r9 ), r16 // r16 = r9 ->dx_by_dy ld.l 16 ( r10 ), r17 // r17 = r10 ->dx_by_dy xorh 0x8000, r16 ,r0 bnc.t .check_r_horiz xorh 0x8000, r17 ,r0 // most edges are NOT horizontal, so we TAKE this // if ( r9 ->vmin == r10 ->vmin) { ld.l 8 ( r9 ), r16 ld.l 8 ( r10 ), r17 xor r16 , r17 ,r0 bnc .lmin_not_rmin // branch taken if not the same // swap ( r9 , r10 , edge* ); mov r9 ,r31;mov r10 , r9 ;mov r31, r10 // activate_edge = (edge *) (1|(int) activate_edge); or 1, r11 , r11 // r7 = ((int *)( r9 ->vmin->position))[X]; // } ld.l 8 ( r9 ), r31 br .extract_plane_eqn ld.l 4 (r31), r7 .lmin_not_rmin: // else { // r7 = ((int *)( r10 ->vmin->position))[X]; // } // } ld.l 8 ( r10 ), r31 br .extract_plane_eqn ld.l 4 (r31), r7 .check_r_horiz: // else if ( r10 ->dx_by_dy == MINT) { // xorh 0x8000, r17 ,r0 <--- this is now executed above in a delayed branch bnc.t .none_horiz subs r0, r16 ,r31 // again, this is most frequent case // first instruction of .none_horiz // if ( r10 ->vmax == r9 ->vmin) { ld.l 12 ( r10 ), r16 ld.l 8 ( r9 ), r17 xor r16 , r17 ,r0 bnc .rmax_not_lmin // swap ( r9 , r10 , edge* ); mov r9 ,r31;mov r10 , r9 ;mov r31, r10 // r7 = ((int *)( r10 ->vmin->position))[X]; // } ld.l 8 ( r10 ), r31 br .extract_plane_eqn ld.l 4 (r31), r7 .rmax_not_lmin: // else { // activate_edge = (edge *) (1|(int) activate_edge); or 1, r11 , r11 // r7 = ((int *)( r9 ->vmin->position))[X]; // } // } // ld.l 8 ( r9 ), r31 br .extract_plane_eqn ld.l 4 (r31), r7 .none_horiz: // else { // if ( r10 ->dx_by_dy < r9 ->dx_by_dy) { // this was adds r31, r17 ,r0 // r31 holds - r9 ->dx_by_dy bnc .dont_swap // swap( r9 , r10 , edge* ); mov r9 ,r31;mov r10 , r9 ;mov r31, r10 // } // .dont_swap: // r7 = ((int *)( r9 ->vmin->position))[X]; ld.l 8 ( r9 ), r31 ld.l 4 (r31), r7 // // if (((int *)( r9 ->vmax->position))[Y] > // ((int *)( r10 ->vmax->position))[Y]) // { // activate_edge = (edge *) (1|(int) activate_edge); ld.l 12 ( r9 ), r16 ld.l 12 ( r10 ), r17 ld.l 8 ( r16 ), r16 ld.l 8 ( r17 ), r17 subs r17 , r16 ,r0 bc.t .extract_plane_eqn or 1, r11 , r11 //}}} .extract_plane_eqn: // tidy up after previous stuff // st.l r9 , 120 (sp) // st.l r10 , 116 (sp) st.l r11 , 112 (sp) mov r7 , r8 // since r8 == r7 r3 start of triangle //{{{ extract plane eqn DONE // remember, r20 is still in r20 mov r20 ,r31 ld.l 12 (r31), r23 ld.l 16 (r31), r24 ld.l 20 (r31), r25 ld.l 24 (r31), r26 //}}} //{{{ set up initial values for {xyzrgb} DONE // mov r9 ,r31 ld.l 16 ( r10 ), r10 ld.l 8 (r31), r16 // r16 = r9 ->vmin ld.l 4 ( r16 ), r7 ld.l 8 ( r16 ), r4 ld.l 12 ( r16 ), r21 ld.l 60 ( r16 ), r18 ld.l 64 ( r16 ), r19 ld.l 68 ( r16 ), r20 ld.l 16 (r31), r9 ld.l 20 (r31), r11 ld.l 24 (r31), r12 ld.l 28 (r31), r13 ld.l 32 (r31), r14 //}}} // /* GO ! */ //{{{ compute start values of r5 , r6 DONE ld.l 100 (sp), r31 shr r31, r4 , r31 ixfr r31, f2 ixfr r30 , f4 fmlow.dd f2,f4,f2 ld.l 44 (sp), r5 ld.l 16 (sp), r6 fxfr f2,r31 adds r5 ,r31, r5 adds r6 ,r31, r6 //}}} //{{{ set up slopes for subsequent scans DONE // (*init)( r23 , r24 , r25 , r26 ); // this can be optimised by passing hods-o-bogus parameters to init ld.l 96 (sp), r31 calli r31 nop //}}} // ideally we call trapezoom here, passing it // 4x slopes .. we need to do the trap stuff, skipping, // until we are aligned with this processor. then we do the // trapzoom, hopping 2 (4,8) lines r3 a time. trapzoom exits // with r4 - r3 in r31, so IF ITS A LEFT HAND EDGE, de-click all // incrementers until aligned - this costs way less on a right // edge. Now extract stuff out of the new edge, walking up // until r3 (from the new edge) == r4 (from the exit of last trap) // then call trapzoom again // //{{{ trapezoid DONE call _trapezoid subs r4 , r3 ,r0 //}}} //{{{ replace worn-out edge DONE ld.l 112 (sp), r31 and 1,r31,r0 bnc .activate_right // now activate left edge //{{{ activate left edge - happens every other triangle // r9 =activate_edge; ld.l 8 (r31), r16 // r16 = r11 ->vmin ld.l 16 (r31), r9 ld.l 20 (r31), r11 ld.l 24 (r31), r12 ld.l 28 (r31), r13 ld.l 32 (r31), r14 ld.l 4 ( r16 ), r7 ld.l 12 ( r16 ), r21 ld.l 60 ( r16 ), r18 ld.l 64 ( r16 ), r19 br .set_at ld.l 68 ( r16 ), r20 //}}} .activate_right: // here activate right edge //{{{ easy case, right edge // r10 = (edge *) (1 ^ (int) activate_edge); // r8 =((int *)(& r10 ->vmin->position))[X]; // r10 = r10 ->dx_by_dy; xor 1,r31,r31 ld.l 8 (r31), r16 // r16 = r10 ->vmin ld.l 16 (r31), r10 ld.l 4 ( r16 ), r8 //}}} // r3 =((int *) (& r10 ->vmax->position))[Y]; .set_at: // ld.l 116 (sp), r31 ld.l 12 (r31), r31 // since r31 holds r11 ! ld.l 8 (r31), r3 //}}} //{{{ trapezoid DONE call _trapezoid subs r4 , r3 ,r0 //}}} //{{{ r20 = r21 ; ntris--; } DONE /* i.e end loop */ ld.l 104 (sp), r16 adds -1, r16 , r16 or r0, r16 ,r0 bnc.t .for_i_ntris st.l r16 , 104 (sp) //}}} .restore: //{{{ restore f2..f7 fld.d 40 (sp), f2 fld.d 32 (sp), f4 fld.d 24 (sp), f6 //}}} //{{{ restore r4..r15 ld.l 92 (sp), r4 ld.l 88 (sp), r5 ld.l 84 (sp), r6 ld.l 80 (sp), r7 ld.l 76 (sp), r8 ld.l 72 (sp), r9 ld.l 68 (sp), r10 ld.l 64 (sp), r11 ld.l 60 (sp), r12 ld.l 56 (sp), r13 ld.l 52 (sp), r14 ld.l 48 (sp), r15 //}}} //{{{ proc exit ld.l 156 (sp),fp ld.l 152 (sp),r1 bri r1 addu 160 , sp, sp //}}} //{{{ E S C A P E ! ! ! ! ! br .restore nop //}}} //}}}