//{{{ 16 bit zbuffer, 8 bit pixels //{{{ about zbuffer.ss // // zbuffer.s // // 16 bit Z buffer routine. // // This routine takes a scan line segment and performs // a standard z check across the segment, whilst interpolating z // // The routine assumes a pixel size of 8 bits. // All scan segments are flat shaded. // Assume following inputs // // int length; ; no. of pixels in segment // fpoint zstart; ; z start value // fpoint deltaz; ; delta z with x // pixel cstart; ; initial colour // pixel deltac; ; delta colour with x // // // r1 return address // r2 stack pointer // r3 frame pointer // r4..r15 local variables left unchanged by subroutine // r16..r27 parameters and temporaries, not preserved by subroutines // r28..r30 temporaries, not preserved by subroutine // r31 addressing temporary // // f0/f1 zero // f2..f7 local values, preserved by subroutine // f8..f15 parameters and temporaries, not preserved by subroutine // f16..f31 temporary // //}}} // ROUTINE PARAMETRS define(sp, r2) //stack pointer define(Zaddr, r16) // zixel address define(Paddr, r17) // pixel address define(Zstart, r18) // start z value define(dZ, r19) // delta z for each pixel define(Xstart, r20) // start x value define(length, r21) // total no. of pixels in segment define(Col, r22) // start colour // // GLOBAL DATA // // // LOCALS define(i, r28) define(lc, r29) define(itemp1, r29) define(itemp2, r30) define(itemp3, r31) define(oldZval, f8) //current z buffer value define(newZval, f10) // new z value define(lZmaskl, f12) // mask for left end of scan segment define(lZmaskl1, f12) define(lZmaskl2, f13) define(lZmaskh, f14) define(lZmaskh1, f14) define(lZmaskh2, f15) define(rZmaskl, f16) // mask for right end of scan segment define(rZmaskl1, f16) define(rZmaskl2, f17) define(rZmaskh, f18) define(rZmaskh1, f18) define(rZmaskh2, f19) define(iZval, f20) // interpolated z value define(colour, f22) // 8 pixels of constant colour define(colourl, f22) define(colourh, f23) define(ftemp1, f24) // temporary val define(ftemp2, f26) define(iZ, f26) // z interpolator define(iZl, f26) define(iZh, f27) define(aZl, f28) // z accumulator define(aZh, f29) define(aZ, f28) define(aZ1, f28) define(aZ2, f30) // // Table of Z masks for un-aligned accesses // .data; .align .double lZmask_table:: .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 .long 0x0000FFFF, 0x00000000, 0x00000000, 0x00000000 .long 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000 .long 0xFFFFFFFF, 0x0000FFFF, 0x00000000, 0x00000000 .long 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000 .long 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF, 0x00000000 .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000FFFF rZmask_table:: .long 0x00000000, 0x00000000, 0x00000000, 0x00000000 .long 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF .long 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF .long 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFFFFFFFF .long 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF .long 0x00000000, 0x00000000, 0xFFFF0000, 0xFFFFFFFF .long 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF .long 0x00000000, 0x00000000, 0x00000000, 0xFFFF0000 // // .globl _zbufferSegment .text _zbufferSegment:: // generate colour ixfr Col,colourl fmov.ss colourl,colourh // generate left and right masks and 7,Xstart,itemp1 // determine alignment of start pixel subs 8,itemp1,itemp2 // 4 - align subs length,itemp2,length // adjust length and 7,length,itemp3 // determine alignment mov lZmask_table,itemp2 shl 4,itemp1,i adds itemp2,i,itemp2 fld.q 0(itemp2),lZmaskl mov rZmask_table,itemp2 shl 4,itemp3,i adds itemp2,i,itemp2 fld.q 0(itemp2),rZmaskl subs 0,length,r0 bc over64bits // check for only 64 bit segment fxfr lZmaskl1,i fxfr rZmaskl1,itemp2 or i,itemp2,itemp2 ixfr itemp2,lZmaskl1 fxfr lZmaskl2,i fxfr rZmaskl2,itemp2 or i,itemp2,itemp2 ixfr itemp2,lZmaskl2 fxfr lZmaskh1,i fxfr rZmaskh1,itemp2 or i,itemp2,itemp2 ixfr itemp2,lZmaskh1 fxfr lZmaskh2,i fxfr rZmaskh2,itemp2 or i,itemp2,itemp2 ixfr itemp2,lZmaskh2 over64bits: // initialise accumulator to Zstart - ndZ ixfr itemp1,ftemp1 ixfr dZ,ftemp2 // 2 free cycles here fmlow.dd ftemp1,ftemp2,ftemp1 // n * dZ // 4 free cycles here so adds -8,Zaddr,Zaddr // anticipate autoincrement adds -8,Paddr,Paddr // anticipate autoincrement fxfr ftemp1,itemp1 subs Zstart,itemp1,itemp2 ixfr itemp2,aZl fmov.ss aZl, aZh //accumulator = Zstart-ndZ | Zstart-ndZ .dual // Process first 1 -> 8 pixels // interpolate z over first pixels fmov.ss f0,iZl // iZl = 0 shl 1,dZ,itemp1 fnop ixfr itemp1,iZh // iZh = 2dZ faddz aZ1,iZ,aZ1 // first result shl 1,itemp1,itemp1 // 4dZ fnop ixfr dZ,iZl // iZl = dZ fnop ixfr dZ,iZh // iZh = dZ faddz aZ1,iZ,aZ2 // second result fld.d 8(Zaddr)++,oldZval // get first 4 zbuffer values form lZmaskl,iZval // merge -> zval ixfr itemp1,iZl // iZl = 4dZ fzchks oldZval,iZval,newZval // check z over current pixels ixfr itemp1,iZh // iZh = 4dZ // interpolate z over next 4 pixels faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixel faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixel form lZmaskh,iZval nop // if length > 8 then traverse rest of segment fzchks oldZval,iZval,newZval // check z for next 4 Pixels subs 8,length,r0 fnop bnc last_8_pixels fnop adds -8,r0,i // loop increment fnop adds -8,length,lc // ensure loop for length only fnop bla i,lc,loop1 fnop nop loop1: // interpolate z over next 4 pixels faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixel faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixel form f0,iZval pst.d colour,8(Paddr)++ // store new Pixel fzchks oldZval,iZval,newZval // check z for next 4 Pixels nop // interpolate z over next 4 pixels faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixel faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixel form f0,iZval bla i,lc,loop1 fzchks oldZval,iZval,newZval // check z for next 4 pixels adds -8,length,length endloop1: // less than 8 pixels left at this stage last_8_pixels: fnop subs 4,length,r0 fnop bnc last_pixels // > 4 pixels left // interpolate z over last 5->7 pixels faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixels faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixels form rZmaskl,iZval pst.d colour,8(Paddr)++ // store new Pixel fzchks oldZval,iZval,newZval // check z for next 4 pixels adds -4,length,length // 1 -> 4 pixels left // interpolate z over last n pixels (1 - 4 pixels remain) faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixels faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixels form rZmaskh,iZval nop .enddual fzchks oldZval,iZval,newZval adds -4,length,length fnop fst.d newZval,0(Zaddr) // store final Zixels bri r1 pst.d colour,8(Paddr)++ // store final Pixels // last 0 -> 4 pixels last_pixels: fnop subs 0,length,r0 fnop bnc exit // 1 -> 4 pixels left // interpolate z over last n pixels (1 - 4 pixels remain) faddz aZ1,iZ,aZ1 fld.d 8(Zaddr)++,oldZval // load old Zixels faddz aZ2,iZ,aZ2 fst.d newZval,-8(Zaddr) // store new Zixels form rZmaskl,iZval pst.d colour,8(Paddr)++ // store new Pixels .enddual fzchks oldZval,iZval,newZval adds -4,length,length fzchks f0,oldZval,f0 // shift PM right 4 fst.d newZval,0(Zaddr) // store final Zixels // NOTE: to shift PM and leave top // 4 bits clear src2 < src1 bri r1 pst.d colour,8(Paddr)++ // store final Pixels // O.K complete now exit: .enddual fnop fst.d newZval,0(Zaddr) // store final Zixels bri r1 pst.d colour,8(Paddr)++ // store final Pixels // THE END //}}}