;--- HOW TO DO ARITHMETIC IN IKONAS MICROCODE, AND OTHER TRICKS ---; ; ; Paul Heckbert, NYIT ; CONSTANTS pr rlimm 0 b1 bd ; r1 = 0 ; or aluz b1 bd ; r1 = 0 ldudr 0xffff pr rimm 0xffff b1 bd ; r1 = -1 ; or mr car0 rlimm 0 b1 bd ; r1 = -1 ; or aluones b1 bd ; r1 = -1 (look Ma, no data field!) aluones b1 llfbd ; r1 = -2 aluones b1 rlfbd ; r1 = 2147483647 (you get the idea) ; NEGATE mr car1 ra1 b2 bd ; r2 = -r1 ; COMPLEMENT mr car0 ra1 b2 bd ; r2 = ~r1 = -r1-1 ; EXTRACT LOW HALFWORD ras rlimm 0xffff b1 bd ; r1 &= 0x0000ffff pr rlmdr b1 bd ; r1 = LOW MDR = MDR&0x0000ffff ; EXTRACT HIGH HALFWORD nras rlimm 0xffff b1 bd ; r1 &= 0xffff0000 ; ADD rps ra1 b2 alumdr ; mdr = r1+r2 ; ADD TWO 16-BIT NUMBERS IN PARALLEL rps carh0 ra1 b2 qd ; Q = (hi(r1)+hi(r2):lo(r1)+lo(r2)) ; SUBTRACT rms car1 ra1 b2 alumdr ; mdr = r1-r2 ; DECREMENT (note: there's no way to decrement without using ; the data field or a second register) smr car1 rlimm 1 b2 bd ; r1 = r1-1 ; or smr car0 rlimm 0 b2 bd ; r1 = r1-1 ; INCREMENT incrs b2 ; r2++ ; or ps car1 b2 bd ; r2++ ; or rps rlimm 1 b2 bd ; r2++ ; STEP RIGHT ONE LORES PIXEL (assuming you've got address in a register) incrs car1 b2 alumar ; MAR=r2+=2 (no wasted data field!) ; IF (R1<=R2) R1++ rms car1 ra2 b1 ; r2-r1 ps car31 b1 bd ; r1 = r1+car31 = r1+(r2>=r1) ; IF (R1>R2) R1++ rms car1 ra2 b1 ; r2-r1 ps carn31 b1 bd ; r1 = r1+carn31 = r1+(r2>1 rors rimm 0 b1 bd skip: ; or smtc carz b1 ; convert to sign/magnitude ps b1 rafbd ; shift right 1 arithmetic smtc carz b1 ; convert back ; or ps b1 rlflqbd ls0 ; logical shift (r1,Q) right 1 bit ; ; note on neg. numbers: ; on the vax: -1>>1 = -1, -2>>1 = -1, -3>>1 = -2 ; with rafbd: -1>>1 = 0, -2>>1 = -1, -3>>1 = -1 ; 16-BIT MULTIPLY USING MULTIPLIER CHIP pr ra1 alumpx pr ra2 alumpy nanop ; necessary! b2 bd mpzbr ; r2 = r1*r2+32768 smr car1 rlimm 32768 b2 bd ; subtract 32768 ; CONVERT FROM SIGNED TO TWO'S COMPLEMENT OR VICE-VERSA smtc carz b2 ; 32-BIT NORMALIZE pr ra1 qd ; load Q with # to be normalized aluz b2 bd ; initialize shift counter to 0 slnml car1 b2 nccovr jmpdf . ; shift Q left, r2++ till normalized ; when done, r2 contains # of shifts ; works for numbers < 2^30 ; 64-BIT NORMALIZE pr ra1 qd ; Q is low 32 bits, r2 high 32 dlnml ls0 b2 nccovr jmpdf . ; shift r2,Q left till normalized ; works for numbers < 2^62 ; UNSIGNED 32-BIT MULTIPLY aluz b3 bd ; R3,Q = r1*r2 pr ra1 qd ldcnt -31 ; Q = r1; set counter umpy ra2 b3 ls0 ncccntz jmpcnt .; 32 bit operands, 64 bit result ; TWO'S COMPLEMENT 32-BIT MULTIPLY aluz b3 bd ; R3,Q = r1*r2 pr ra1 qd ldcnt -30 ; Q = r1; set counter tcmpy ra2 b3 ls0 ncccntz jmpcnt .; 32 bit operands, 64 bit result tcmpl ra2 b3 carz ls0 ; TWO'S COMPLEMENT DIVISION, method 1 (positive operands only) dlnml ra2 b1 lr ldcnt -30 ; Q = r1,Q / r2; r1 = r1,Q % r2 tcdiv ra2 b1 lr carz ncccntz jmpcnt . ; shift and subtract in loop tcdivc ra2 b1 ss0 carz ; divide correction rps ra2 b1 bd ; fix remainder ; note: low bit of quotient is always 0, so it should not be trusted ; TWO'S COMPLEMENT DIVISION, method 2 (positive operands only) dlnml ra2 b1 lr ldcnt -31 ; Q = r1,Q / r2; r1 = r1,Q % r2 tcdiv ra2 b1 lr carz ncccntz jmpcnt . ; shift and subtract in loop tcdivc ra2 b1 ss1 carz ; divide correction rps ra2 b1 rlflqbd ; fix quotient and remainder ; TRICKS: ikmdr pr rbhs b1 qd ; MDR = BUS; Q = r1>>16 rps ra1 b2 bdqd alumar ; MAR = Q = r2 += r1 rps car1 rbhs b1 sq llfbd ; r1 = ((r1>>16)+Q+1)<<1 ikrd b1 ikbr rps ra2 bdqd ; read; r1 = BUS; Q = r1+r2 ldudr 0xf ; clears hires image pr rimm 0xffff qd alumar napush ; nalup doesn't use data field hreswr smr rlimm car0 0 sq qd alumar ccgtz nalup dfikd ; note: rlimm implies dfikd ras rlimm 255 b1 bd ; copy low byte of r1 into all 4 bytes rors rbbr b1 bd rors rbhr b1 bd