.insrt "reset.a68" _init: rts |J. Test 1/81 |addressed signed long division: *dividend = *dividend/divisor .globl Cp_aldiv .text addl #0,.a4 Cp_aldiv: link .a6,#0 moveml #0x3C00,.sp@- |need .d2,.d3,.d4,.d5 registers moveq #1,.d5 |sign of result movl .a6@(8),.a0 |.a0 = dividend pointer movl .a0@,.d0 |.d0 = dividend jge 1$ negl .d0 negl .d5 1$: movl .d0,.d3 |save positive dividend movl .a6@(12),.d1 |divisor jge 2$ negl .d1 negl .d5 2$: movl .d1,.d4 |save positive divisor cmpl #0x10000,.d1 |divisor < 2 ** 16? jge 3$ |no, divisor must be < 2 ** 16 clrw .d0 |yes, divide dividend swap .d0 | by 2 ** 16 divu .d1,.d0 |get the high order bits of quotient movw .d0,.d2 |save quotient high movw .d3,.d0 |dividend low + remainder*(2**16) divu .d1,.d0 |get quotient low swap .d0 |temporarily save quotient low in high movw .d2,.d0 |restore quotient high to low part of register swap .d0 |put things right jra 5$ |return 3$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? jge 3$ |no, continue shift divu .d1,.d0 |yes, divide, remainder is garbage andl #0xFFFF,.d0 |get rid of remainder movl .d0,.d2 |save quotient movl .d0,.sp@- |call ulmul with quotient movl .d4,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d3 |original dividend >= lmul result? jge 4$ |yes, quotient should be correct subql #1,.d2 |no, fix up quotient 4$: movl .d2,.d0 |move quotient to .d0 5$: tstl .d5 |sign of result jge 6$ negl .d0 6$: movl .d0,.a0@ |store result via pointer moveml .sp@+,#0x3C |restore registers unlk .a6 rts |J. Test 1/81 |addressed signed long multiply routine: *a = *a * b .globl Cp_almul .text addl #0,.a4 Cp_almul: link .a6,#0 moveml #0x3800,.sp@- |save .d2,.d3,.d4 moveq #1,.d4 |sign of result movl .a6@(8),.a0 |.a0 = pointer to a movl .a0@,.d2 |.d2 = a bge 1$ negl .d2 negl .d4 1$: movl .a6@(12),.d3 |.d3 = b bge 2$ negl .d3 negl .d4 2$: clrl .d0 movw .d2,.d0 |.d0 = alo, unsigned mulu .d3,.d0 |.d0 = blo*alo, unsigned movw .d2,.d1 |.d1 = alo swap .d2 |swap alo-ahi mulu .d3,.d2 |.d2 = blo*ahi, unsigned swap .d3 |swap blo-bhi mulu .d3,.d1 |.d1 = bhi*alo, unsigned addl .d2,.d1 |.d1 = (ahi*blo + alo*bhi) swap .d1 |.d1 = clrw .d1 | (ahi*blo + alo*bhi)*(2**16) addl .d1,.d0 |.d0 = alo*blo + (ahi*blo + alo*bhi)*(2**16) tstl .d4 |sign of result bge 3$ negl .d0 3$: movl .d0,.a0@ |store result via pointer moveml .sp@+,#0x1C |restore .d2,.d3,.d4 unlk .a6 rts |J. Test 1/81 |addressed signed long remainder: *dividend = *dividend % divisor .globl Cp_alrem .text addl #0,.a4 Cp_alrem: link .a6,#0 moveml #0x3800,.sp@- |need .d2,.d3,.d4 registers moveq #1,.d4 |sign of result movl .a6@(8),.a0 |.a0 = dividend pointer movl .a0@,.d0 |dividend bge 1$ negl .d0 negl .d4 1$: movl .d0,.d2 |save positive dividend movl .a6@(12),.d1 |divisor bge 2$ negl .d1 2$: cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 3$ |no, divisor must be < 2 ** 16 clrw .d0 |.d0 = swap .d0 | dividend high divu .d1,.d0 |yes, divide movw .d2,.d0 |.d0 = remainder high + quotient low divu .d1,.d0 |divide clrw .d0 |.d0 = swap .d0 | remainder bra 6$ |return 3$: movl .d1,.d3 |save divisor 4$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 4$ |no, continue shift divu .d1,.d0 |yes, divide andl #0xFFFF,.d0 |erase remainder movl .d0,.sp@- |call ulmul with quotient movl .d3,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d2 |original dividend >= lmul result? jge 5$ |yes, quotient should be correct subl .d3,.d0 |no, fixup 5$: subl .d2,.d0 |calculate negl .d0 | remainder 6$: tstl .d4 |sign of result bge 7$ negl .d0 7$: movl .d0,.a0@ |write result via pointer moveml .sp@+,#0x1C |restore registers unlk .a6 rts |J. Test 1/81 |addressed unsigned long division: *dividend = *dividend / divisor .globl Cp_auldiv .text addl #0,.a4 Cp_auldiv: link .a6,#0 moveml #0x3800,.sp@- |need .d2,.d3,.d4 registers movl .a6@(8),.a0 |.a0 = dividend pointer movl .a0@,.d0 |.d0 = dividend movl .d0,.d3 |save dividend movl .a6@(12),.d1 |divisor movl .d1,.d4 |save divisor cmpl #0x10000,.d1 |divisor >= 2 ** 16? jge 1$ |yes, divisor must be < 2 ** 16 clrw .d0 |divide dividend swap .d0 | by 2 ** 16 divu .d1,.d0 |get the high order bits of quotient movw .d0,.d2 |save quotient high movw .d3,.d0 |dividend low + remainder * (2**16) divu .d1,.d0 |get quotient low swap .d0 |temporarily save quotient low in high movw .d2,.d0 |restore quotient high to low part of register swap .d0 |put things right jra 3$ |return 1$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? jge 1$ |no, continue shift divu .d1,.d0 |yes, divide, remainder is garbage andl #0xFFFF,.d0 |get rid of remainder movl .d0,.d2 |save quotient movl .d0,.sp@- |call ulmul with quotient movl .d4,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d3 |original dividend >= lmul result? jge 2$ |yes, quotient should be correct subql #1,.d2 |no, fix up quotient 2$: movl .d2,.d0 |move quotient to .d0 3$: movl .d0,.a0@ |store result via pointer moveml .sp@+,#0x1C |restore registers unlk .a6 rts |J. Test 1/81 |addressed unsigned long multiply: *a = *a * b .globl Cp_aulmul .text addl #0,.a4 Cp_aulmul: link .a6,#0 moveml #0x3000,.sp@- |save .d2,.d3 movl .a6@(8),.a0 |.a0 = pointer to a movl .a0@,.d2 |.d2 = a movl .a6@(12),.d3 |.d3 = b clrl .d0 movw .d2,.d0 |.d0 = alo, unsigned mulu .d3,.d0 |.d0 = blo*alo, unsigned movw .d2,.d1 |.d1 = alo swap .d2 |swap alo-ahi mulu .d3,.d2 |.d2 = blo*ahi, unsigned swap .d3 |swap blo-bhi mulu .d3,.d1 |.d1 = bhi*alo, unsigned addl .d2,.d1 |.d1 = (ahi*blo + alo*bhi) swap .d1 |.d1 = clrw .d1 | (ahi*blo + alo*bhi)*(2**16) addl .d1,.d0 |.d0 = alo*blo + (ahi*blo + alo*bhi)*(2**16) movl .d0,.a0@ |store result via pointer 3$: moveml .sp@+,#0xC |restore .d2,.d3 unlk .a6 rts |J. Test 1/81 |addressed unsigned long remainder: *dividend = *dividend % divisor .globl Cp_aulrem .text addl #0,.a4 Cp_aulrem: link .a6,#0 moveml #0x3000,.sp@- |need .d2,.d3 registers movl .a6@(8),.a0 |.a0 = dividend pointer movl .a0@,.d0 |.d0 = dividend movl .d0,.d2 |save dividend movl .a6@(12),.d1 |divisor cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 1$ |no, divisor must be < 2 ** 16 clrw .d0 |.d0 = swap .d0 | dividend high divu .d1,.d0 |yes, divide movw .d2,.d0 |.d0 = remainder high + quotient low divu .d1,.d0 |divide clrw .d0 |.d0 = swap .d0 | remainder bra 4$ |return 1$: movl .d1,.d3 |save divisor 2$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 2$ |no, continue shift divu .d1,.d0 |yes, divide andl #0xFFFF,.d0 |erase remainder movl .d0,.sp@- |call ulmul with quotient movl .d3,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d2 |original dividend >= lmul result? jge 3$ |yes, quotient should be correct subl .d3,.d0 |no, fixup 3$: subl .d2,.d0 |calculate negl .d0 | remainder 4$: movl .d0,.a0@ |store result through pointer moveml .sp@+,#0xC |restore registers unlk .a6 rts |J. Test 3/81 |floating point routines for Nu(MC68000) |offsets in internal float structure SIGN = 0 |sign EXPT = 2 |exponent (-127/+127) MANH = 4 |high mantissa MANL = 8 |low mantissa .data afloat: |internal-a floating representation a_sign: .word 0 a_expt: .word 0 a_manh: .long 0 a_manl: .long 0 bfloat: |internal-b floating representation b_sign: .word 0 b_expt: .word 0 b_manh: .long 0 b_manl: .long 0 lsum: |storage for multiply .word 0 .long 0 |high part of accumulated sum .long 0 |low part of accumulated sum .word 0 | |convert external float to internal format |.d0,.d1 contain the external float |.a0 points to afloat or bfloat | .text etoi: clrw .a0@ |clear sign tstl .d0 |test sign of external bge 1$ |set sign 0(+), 1(-) movw #1,.a0@ 1$: movl .d1,.a0@(MANL) |save low 32 bits of mantissa movl .d0,.d1 andl #0x7FFFFF,.d1 orl #0x800000,.d1 |add hidden high order bit movl .d1,.a0@(MANH) |save high 1+23 bits of mantissa swap .d0 asrl #7,.d0 andw #0xFF,.d0 |isolate exponent bne 2$ clrl .a0@ |zero sign, exponent, clrl .a0@(MANH) | high mantissa, and clrl .a0@(MANL) | low mantissa rts 2$: subw #128,.d0 |convert from excess 0200 movw .d0,.a0@(EXPT) |store converted value rts |done | |convert internal format to external float |.a0 points to afloat or bfloat |external float returned in .d0,.d1 | .text itoe: clrl .d0 movw .a0@(EXPT),.d0 |get exponent addw #128,.d0 |convert to excess 0200 bne 1$ |if exponent is zero clrl .d1 | clear .d0,.d1 rts | and return 1$: tstw .a0@ |set sign beq 2$ |sign bit 0(+), 1(-) orw #0x100,.d0 2$: swap .d0 |align sign and exponent asll #7,.d0 | in high part of .d0 movl .a0@(MANH),.d1 |get high part of mantissa bne 3$ |check for zero mantissa clrl .d0 |if zero - clear sign and rts | exponent and return 3$: andl #0x7FFFFF,.d1 |delete high order hidden bit orl .d1,.d0 |put high 23 bits of mantissa movl .a0@(MANL),.d1 |put low 32 bits of mantissa rts |done | |normalize internal float by adjusting exponent and |shifting mantissa appropriately so 1/2 <= mnt < 1 |.a0 points to afloat or bfloat | .text normal: jsr [offset,.a4] |determine amount to shift addw .d0,.a0@(EXPT) |adjust exponent jsr [shift,.a4] |shift mantissa rts | |determine position of most significant bit of |mantissa in relation to normalized decimal point |.a0 points to afloat or bfloat |.d0 returns offset of msb from decimal point | .text offset: moveq #1,.d0 movl .a0@(MANH),.d1 |check for high order bits bne 2$ movl .a0@(MANL),.d1 |check low order bits bne 1$ clrw .d0 |zero shift count rts 1$: subw #32,.d0 |need to shift at least 23 2$: subqw #1,.d0 |find most significant bit asll #1,.d1 bcc 2$ addqw #8,.d0 |.d0 contains exponent correction rts | |shift mantissa according to offset in .d0 |.a0 points to afloat or bfloat |.d0 contains shift count, <0 -> left shift, >0 -> right shift |on return, .d1 = 0, .d2,.d3 have shifted mantissa | .text shift: clrl .d1 movl .a0@(MANH),.d2 |.d2 = high part of mantissa movl .a0@(MANL),.d3 |.d3 = low part of mantissa movw .d0,.d1 |examine exponent correction bmi 2$ |shift left bne 1$ |shift right rts |no shift - return 1$: asrl #1,.d2 |shift entire mantissa roxrl #1,.d3 | right by one bit subqw #1,.d1 |repeat until count bne 1$ | is zero andl #0xFFFFFF,.d2 |zero top byte bra shifte |return 2$: asll #1,.d3 |shift entire mantissa roxll #1,.d2 | left by one bit addqw #1,.d1 |repeat until count bne 2$ | is zero shifte: movl .d2,.a0@(MANH) |store high part of mantissa movl .d3,.a0@(MANL) |store low part of mantissa rts |done | |fetch floating arguments off stack |convert to internal format in afloat and bfloat |on return, .a0 points to afloat, .a1 points to bfloat | getargs: lea [bfloat,.a4],.a1 |.a1 points to bfloat tstw .d0 |branch to 1$ for bne 1$ | indirect argument fetch movl .a6@(16),.d0 |b-high movl .a6@(20),.d1 |b-low movl .a1,.a0 |setup .a0 for conversion jsr [etoi,.a4] |convert b-arg to internal form movl .a6@(8),.d0 |a-high movl .a6@(12),.d1 |a-low lea [afloat,.a4],.a0 |.a0 points to afloat jsr [etoi,.a4] |convert a-arg to internal form rts 1$: movl .a6@(12),.d0 |b-high movl .a6@(16),.d1 |b-low movl .a1,.a0 |setup .a0 for conversion jsr [etoi,.a4] |convert b-arg to internal form movl .a6@(8),.a0 |.a0 points to a-arg movl .a0@+,.d0 |a-high movl .a0@,.d1 |a-low lea [afloat,.a4],.a0 |.a0 points to afloat jsr [etoi,.a4] |convert a-arg to internal form rts | |free exponent returning fractional value | .globl C_frexp .text addl #0,.a4 C_frexp: link .a6,#0 lea [afloat,.a4],.a0 |.a0 points to afloat movl .a6@(8),.d0 |a-high movl .a6@(12),.d1 |a-low movl .a6@(16),.a1 |place to return exponent jsr [etoi,.a4] |convert to internal form movw .a0@(EXPT),.d0 |get unbiased exponent extl .d0 | convert to long and movl .d0,.a1@ | return value clrw .a0@(EXPT) |set exponent for fractional jsr [itoe,.a4] | value, convert for return unlk .a6 rts | |add/load exponent of float | .globl C_ldexp .text addl #0,.a4 C_ldexp: link .a6,#0 lea [afloat,.a4],.a0 |.a0 points to afloat movl .a6@(8),.d0 |a-high movl .a6@(12),.d1 |a-low jsr [etoi,.a4] |convert to internal form movl .a6@(16),.d0 |add argument addw .d0,.a0@(EXPT) | to exponent jsr [itoe,.a4] |convert and return unlk .a6 rts | |separate integer/fractional parts of float | .globl C_modf .text addl #0,.a4 C_modf: link .a6,#0 moveml #0x3800,.sp@- |save .d2,.d3,.d4 movl .a6@(8),.d0 |a-high movl .a6@(12),.d1 |a-low lea [afloat,.a4],.a0 |a0 -> afloat = fractional jsr [etoi,.a4] | part on return lea [bfloat,.a4],.a1 |a1 -> bfloat = integer part on return movw .a0@,.a1@ |copy signs movw .a0@(EXPT),.d4 |if exponent > 0 bgt 1$ | separate integer/fractional movw #-128,.a1@(EXPT) |else integer part = 0 movl .a1,.a0 | convert integer part first bra modfe | no need to separate 1$: movw .d4,.a1@(EXPT) |set integer exponent clrw .a0@(EXPT) |set fractional exponent cmpw #56,.d4 |if shift count is < 56 blt 2$ | shift mantissa movl .a0@(MANL),.a1@(MANL) |else move mantissa to integer movl .a0@(MANH),.a1@(MANH) | part and set fractional movw #-128,.a0@(EXPT) | part = 0 movl .a1,.a0 |convert decimal part first bra modfe | on exit from modf 2$: moveq #-8,.d0 |shift mantissa left jsr [shift,.a4] | by 8 for alignment clrl .d0 3$: asll #1,.d3 |rotate .d0<--.d1<--.d2<--.d3 roxll #1,.d2 | registers until shift roxll #1,.d1 | count = 0 roxll #1,.d0 subqw #1,.d4 bne 3$ movl .d3,.a0@(MANL) |save fractional components movl .d2,.a0@(MANH) | of mantissa movl .d1,.a1@(MANL) |save integer components movl .d0,.a1@(MANH) | of mantissa jsr [normal,.a4] |align fractional part subqw #8,.a0@(EXPT) | and adjust exponent movl .a1,.a0 |align integer part at jsr [offset,.a4] | decimal point without jsr [shift,.a4] | altering exponent modfe: movl .a6@(16),.a1 |get pointer argument jsr [itoe,.a4] |convert integer part movl .d0,.a1@+ | store in location movl .d1,.a1@ | given in argument lea [afloat,.a4],.a0 |convert fractional jsr [itoe,.a4] | part and return moveml .sp@+,#0x1C unlk .a6 rts | |convert floating value to fixed 32-bit integer | .globl Cp_fix .text addl #0,.a4 Cp_fix: link .a6,#0 moveml #0x3000,.sp@- |save .d2,.d3 movl .a6@(8),.d0 |.d0 = high part of float movl .a6@(12),.d1 |.d1 = low order part lea [afloat,.a4],.a0 |.a0 points to afloat jsr [etoi,.a4] |convert to internal format tstw .a0@(EXPT) |test exponent bgt 1$ |if exponent is less clrl .d0 | than or equal to zero bra fixe | return zero 1$: moveq #-8,.d0 |shift mantissa left jsr [shift,.a4] | by 8 for alignment movw .a0@(EXPT),.d1 |(note: after shift .d1 = 0) clrl .d0 |clear .d0 2$: asll #1,.d3 |rotate .d0<--.d2<--.d3 roxll #1,.d2 | registers until exponent roxll #1,.d0 | count is exhausted subqw #1,.d1 |resultant fixed 32-bit bne 2$ | value is in .d0 tstw .a0@ |check sign of float beq fixe |positive - .d0 is ok negl .d0 |negative - negate .d0 fixe: moveml .sp@+,#0xC |pop .d2,.d3 unlk .a6 rts | |convert fixed 32-bit integer to floating | .globl Cp_float .text addl #0,.a4 Cp_float: link .a6,#0 moveml #0x3000,.sp@- |save .d2,.d3 lea [afloat,.a4],.a0 |.a0 points to afloat clrl .a0@(MANH) |clear junk from mantissa clrw .a0@ |clear sign movl .a6@(8),.d0 |.d0 = 32-bit long bmi 1$ |negative bpl 2$ |positive movw #-128,.a0@(EXPT) |floating zero bra floate |return 1$: movw #1,.a0@ |negative sign negl .d0 |convert to positive 2$: movl .d0,.a0@(MANL) |move .d0 to lower mantissa jsr [offset,.a4] |determine amount to shift jsr [shift,.a4] |shift mantissa addw #56,.d0 |calculate exponent movw .d0,.a0@(EXPT) |set exponent floate: jsr [itoe,.a4] |convert to external float moveml .sp@+,#0xC |pop .d2,.d3 unlk .a6 rts | |add, subtract, compare two floating point numbers |.d0,.d1 return result of fadd,fsub operations |result of afadd,afaddf,afsub,afsubf stored |fcmp sets condition codes upon return | .globl Cp_fsub .globl Cp_fadd | .globl Cp_fcmp .globl Cp_afadd .globl Cp_afsub .globl Cp_afaddf .globl Cp_afsubf .text addl #0,.a4 Cp_fadd: link .a6,#0 clrw .d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [add,.a4] |perform addition unlk .a6 rts addl #0,.a4 Cp_fsub: link .a6,#0 clrw .d0 |flag to getargs jsr [getargs,.a4] |get arguments eorw #1,.a1@ |reverse sign of b-arg jsr [add,.a4] |perform addition unlk .a6 rts | addl #0,.a4 |Cp_fcmp: | link .a6,#0 | clrw .d0 |flag to getargs | jsr [getargs,.a4] |get arguments | eorw #1,.a1@ |reverse sign of b-arg | jsr [add,.a4] |perform compare | tstl .d0 |set condition code | unlk .a6 | rts addl #0,.a4 Cp_afadd: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [add,.a4] |perform addition movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@+ | to store result movl .d1,.a0@ | of operation unlk .a6 rts addl #0,.a4 Cp_afsub: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments eorw #1,.a1@ |reverse sign of b-arg jsr [add,.a4] |perform addition movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@+ | to store result movl .d1,.a0@ | of operation unlk .a6 rts addl #0,.a4 Cp_afaddf: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments clrl .a0@(MANL) |clear lower part of a-arg jsr [add,.a4] |perform addition movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@ | to store result unlk .a6 rts addl #0,.a4 Cp_afsubf: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments clrl .a0@(MANL) |clear lower part of a-arg eorw #1,.a1@ |reverse sign of b-arg jsr [add,.a4] |perform addition movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@ | to store result unlk .a6 rts add: moveml #0x3000,.sp@- |save .d2,.d3 movw .a0@(EXPT),.d0 |compare movw .a1@(EXPT),.d1 | exponents subw .d1,.d0 | of a and b bmi 1$ |a_expt < b_expt movl .a1,.a0 |switch .a0 to point to bfloat jsr [shift,.a4] |shift mantissa of bfloat lea [afloat,.a4],.a1 |switch .a1 to point to afloat addw .d0,.a0@(EXPT) |adjust b_expt accordingly bra 2$ 1$: negw .d0 |make the shift count positive jsr [shift,.a4] |shift mantissa of afloat addw .d0,.a0@(EXPT) |adjust a_expt accordingly 2$: tstw .a0@ beq 3$ |a-arg is negative so negl .d3 | negate mantissa negxl .d2 | for addition 3$: movl .a1@(MANH),.d0 movl .a1@(MANL),.d1 tstw .a1@ beq 4$ |b-arg is negative so negl .d1 | negate mantissa negxl .d0 | for addition 4$: addl .d1,.d3 |perform addition of addxl .d0,.d2 | mantissas tstl .d2 |check sign of result bge 5$ negl .d3 |result is negative so negxl .d2 | negate mantissa orw #1,.a0@ | and set sign bra adde 5$: andw #0,.a0@ |result positive adde: movl .d2,.a0@(MANH) |store result movl .d3,.a0@(MANL) | of computation jsr [normal,.a4] |normalize result jsr [itoe,.a4] |convert to external form moveml .sp@+,#0xC |pop .d2,.d3 rts | |negate a floating number |argument on stack |.d0,.d1 return result | .globl Cp_fneg .text addl #0,.a4 Cp_fneg: link .a6,#0 movl .a6@(12),.d1 |.d1 = low part of float movl .a6@(8),.d0 |.d0 = high part of float bmi 1$ orl #0x80000000,.d0 |turn high order bit on bra 2$ 1$: andl #0x7FFFFFFF,.d0 |turn high order bit off 2$: unlk .a6 rts | |multiply two floating numbers |.d0,.d1 return result for fmul |result for afmul,afmulf stored | .globl Cp_fmul .globl Cp_afmul .globl Cp_afmulf .text addl #0,.a4 Cp_fmul: link .a6,#0 clrw .d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [mult,.a4] |multiply arguments unlk .a6 rts addl #0,.a4 Cp_afmul: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [mult,.a4] |perform multiply movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@+ | to store result movl .d1,.a0@ | of operation unlk .a6 rts addl #0,.a4 Cp_afmulf: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [mult,.a4] |perform multiply movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@ | to store result unlk .a6 rts mult: moveml #0x3C20,.sp@- |save .d2-.d5,.a2 movw .a1@+,.d0 |.d0 = sign of b-arg eorw .d0,.a0@+ |a_sign gets resultant sign movw .a1@+,.d0 |.d0 = exponent of b-arg addw .d0,.a0@+ |a_expt gets sum of exponents clrl .d2 |clear clrl .d3 | summation registers clrl .d5 | for multiply moveq #4,.d4 |loop count addql #8,.a1 |adjust .a1 pointer lea [lsum,.a4],.a2 |adjust .a2 pointer l1$: movw .a0@+,.d0 |high to low words of afloat movw .a1@-,.d1 |low to high words of bfloat mulu .d0,.d1 |perform multiply addl .d1,.d3 addxl .d5,.d2 subqw #1,.d4 bne l1$ movl .d4,.a2@+ movl .d2,.a2@+ movl .d3,.a2@ clrl .d2 clrl .d3 moveq #3,.d4 |loop count subql #2,.a0 |adjust .a0 pointer addql #2,.a2 |adjust .a2 pointer l2$: movw .a0@-,.d0 |low to high of afloat movw .a1@+,.d1 |high to low of bfloat mulu .d0,.d1 |perform multiply addl .d1,.d3 addxl .d5,.d2 subqw #1,.d4 bne l2$ movl .a2@-,.d1 movl .a2@-,.d0 addl .d1,.d3 addxl .d0,.d2 movl .d2,.a2@+ movl .d3,.a2@ clrl .d2 clrl .d3 moveq #2,.d4 |loop count subql #2,.a1 |adjust .a1 pointer addql #2,.a2 |adjust .a2 pointer l3$: movw .a0@+,.d0 |high to low of afloat movw .a1@-,.d1 |low to high of bfloat mulu .d0,.d1 addl .d1,.d3 addxl .d5,.d2 subqw #1,.d4 bne l3$ movl .a2@-,.d1 movl .a2@-,.d0 addl .d1,.d3 addxl .d0,.d2 movl .d2,.a2@+ movl .d3,.a2@ subql #2,.a0 |adjust .a0 pointer addql #2,.a2 |adjust .a2 pointer movw .a0@-,.d0 movw .a1@+,.d1 mulu .d0,.d1 addl .d1,.a2@- multe: addql #1,.a2 |adjust .a2 pointer movb .a2@+,.a0@+ |move result movb .a2@+,.a0@+ | to afloat movb .a2@+,.a0@+ movb .a2@+,.a0@+ movb .a2@+,.a0@+ movb .a2@+,.a0@+ movb .a2@+,.a0@+ movb .a2@+,.a0@+ subql #8,.a0 |align .a0 to point subql #4,.a0 | to afloat jsr [normal,.a4] |normalize result jsr [itoe,.a4] |convert to external form moveml .sp@+,#0x43C |pop registers rts | |divide two floating numbers | .globl Cp_fdiv .globl Cp_afdiv .globl Cp_afdivf .text addl #0,.a4 Cp_fdiv: link .a6,#0 clrl .d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [div,.a4] |divide arguments unlk .a6 rts addl #0,.a4 Cp_afdiv: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [div,.a4] |divide arguments movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@+ | to store result movl .d1,.a0@ | of operation unlk .a6 rts addl #0,.a4 Cp_afdivf: link .a6,#0 moveq #1,.d0 |flag to getargs jsr [getargs,.a4] |get arguments jsr [div,.a4] |divide arguments movl .a6@(8),.a0 |.a0 points to where movl .d0,.a0@ | to store result unlk .a6 rts div: moveml #0x3E00,.sp@- |save .d2-.d6 movw .a1@+,.d0 |.d0 = sign of b-arg eorw .d0,.a0@+ |a-sign gets resultant sign movw .a1@+,.d0 |.d0 = exponent of b-arg subw .d0,.a0@+ |a-expt gets diff of exponents movl .a1@+,.d0 |.d0 = divisor high bne ok |if divisor = 0 divu .d0,.d1 | cause trap and core dump ok: movl .a1@,.d1 |.d1 = divisor low movl .a0@+,.d2 |.d2 = dividend high movl .a0@,.d3 |.d3 = dividend low clrl .d4 |clear quotient clrl .d5 | register set moveq #58,.d6 |setup shift count bra 2$ 1$: subqw #1,.d6 |exit computation when beq dive | loop count = 0 movw #0x10,.cc |set x-bit in ccr roxll #1,.d5 |shift 1 into quotient roxll #1,.d4 | accumulator registers roxll #1,.d3 |continue shift into roxll #1,.d2 | into remainder registers 2$: subl .d1,.d3 |subtract divisor from subxl .d0,.d2 | remainder bge 1$ 3$: subqw #1,.d6 |exit computation when beq dive | loop count = 0 asll #1,.d5 |shift 0 into quotient roxll #1,.d4 | accumulator registers roxll #1,.d3 |continue shift into roxll #1,.d2 | remainder registers addl .d1,.d3 |add divisor to addxl .d0,.d2 | remainder bge 1$ |positive -> shift 1 bra 3$ |negative -> shift 0 dive: subql #4,.a0 |align .a0 to mantissa movl .d4,.a0@+ |store quotient movl .d5,.a0@ | into afloat mantissa subql #8,.a0 |align .a0 to afloat jsr [normal,.a4] |normalize mantissa jsr [itoe,.a4] |convert to external float moveml .sp@+,#0x7C |pop .d2-.d6 rts |J. Test 1/81 |signed long division: quotient = dividend / divisor .globl Cp_ldiv .text addl #0,.a4 Cp_ldiv: link .a6,#0 moveml #0x3C00,.sp@- |need .d2,.d3,.d4,.d5 registers moveq #1,.d5 |sign of result movl .a6@(8),.d0 |dividend jge 1$ negl .d0 negl .d5 1$: movl .d0,.d3 |save positive dividend movl .a6@(12),.d1 |divisor jge 2$ negl .d1 negl .d5 2$: movl .d1,.d4 |save positive divisor cmpl #0x10000,.d1 |divisor >= 2 ** 16? jge 3$ |yes, divisor must be < 2 ** 16 clrw .d0 |divide dividend swap .d0 | by 2 ** 16 divu .d1,.d0 |get the high order bits of quotient movw .d0,.d2 |save quotient high movw .d3,.d0 |dividend low + remainder * (2**16) divu .d1,.d0 |get quotient low swap .d0 |temporarily save quotient low in high movw .d2,.d0 |restore quotient high to low part of register swap .d0 |put things right jra 5$ |return 3$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |insure positive andl #0x7FFFFFFF,.d0 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? jge 3$ |no, continue shift divu .d1,.d0 |yes, divide, remainder is garbage andl #0xFFFF,.d0 |get rid of remainder movl .d0,.d2 |save quotient movl .d0,.sp@- |call ulmul with quotient movl .d4,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d3 |original dividend >= lmul result? jge 4$ |yes, quotient should be correct subql #1,.d2 |no, fix up quotient 4$: movl .d2,.d0 |move quotient to .d0 5$: tstl .d5 |sign of result jge 6$ negl .d0 6$: moveml .sp@+,#0x3C |restore registers unlk .a6 rts |J. Test 1/81 |signed long multiply: c = a * b .globl Cp_lmul .text addl #0,.a4 Cp_lmul: link .a6,#0 moveml #0x3800,.sp@- |save .d2,.d3,.d4 moveq #1,.d4 |sign of result movl .a6@(8),.d2 |.d2 = a bge 1$ negl .d2 negl .d4 1$: movl .a6@(12),.d3 |.d3 = b bge 2$ negl .d3 negl .d4 2$: clrl .d0 movw .d2,.d0 |.d0 = alo, unsigned mulu .d3,.d0 |.d0 = blo*alo, unsigned movw .d2,.d1 |.d1 = alo swap .d2 |swap alo-ahi mulu .d3,.d2 |.d2 = blo*ahi, unsigned swap .d3 |swap blo-bhi mulu .d3,.d1 |.d1 = bhi*alo, unsigned addl .d2,.d1 |.d1 = (ahi*blo + alo*bhi) swap .d1 |.d1 = clrw .d1 | (ahi*blo + alo*bhi)*(2**16) addl .d1,.d0 |.d0 = alo*blo + (ahi*blo + alo*bhi)*(2**16) tstl .d4 |sign of result bge 3$ negl .d0 3$: moveml .sp@+,#0x1C |restore .d2,.d3,.d4 unlk .a6 rts |signed long remainder: a = a % b .globl Cp_lrem .text addl #0,.a4 Cp_lrem: link .a6,#0 moveml #0x3800,.sp@- |need .d2,.d3,.d4 registers moveq #1,.d4 |sign of result movl .a6@(8),.d0 |dividend bge 1$ negl .d0 negl .d4 1$: movl .d0,.d2 |save positive dividend movl .a6@(12),.d1 |divisor bge 2$ negl .d1 2$: cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 3$ |no, divisor must be < 2 ** 16 clrw .d0 |.d0 = swap .d0 | dividend high divu .d1,.d0 |yes, divide movw .d2,.d0 |.d0 = remainder high + quotient low divu .d1,.d0 |divide clrw .d0 |.d0 = swap .d0 | remainder bra 6$ |return 3$: movl .d1,.d3 |save divisor 4$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 4$ |no, continue shift divu .d1,.d0 |yes, divide andl #0xFFFF,.d0 |erase remainder movl .d0,.sp@- |call ulmul with quotient movl .d3,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d2 |original dividend >= lmul result? jge 5$ |yes, quotient should be correct subl .d3,.d0 |no, fixup 5$: subl .d2,.d0 |calculate negl .d0 | remainder 6$: tstl .d4 |sign of result bge 7$ negl .d0 7$: moveml .sp@+,#0x1C |restore registers unlk .a6 rts |J. Gula |J. Test 1/81 |unsigned long division: dividend = dividend / divisor .globl Cp_uldiv .text addl #0,.a4 Cp_uldiv: link .a6,#0 moveml #0x3800,.sp@- |need .d2,.d3,.d4 registers movl .a6@(8),.d0 |dividend movl .d0,.d3 |save dividend movl .a6@(12),.d1 |divisor movl .d1,.d4 |save divisor cmpl #0x10000,.d1 |divisor >= 2 ** 16? jge 1$ |yes, divisor must be < 2 ** 16 swap .d0 |divide dividend andl #0xFFFF,.d0 | by 2 ** 16 divu .d1,.d0 |get the high order bits of quotient movw .d0,.d2 |save quotient high movw .d3,.d0 |dividend low + remainder * (2**16) divu .d1,.d0 |get quotient low swap .d0 |temporarily save quotient low in high movw .d2,.d0 |restore quotient high to low part of register swap .d0 |put things right jra 3$ |return 1$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? jge 1$ |no, continue shift divu .d1,.d0 |yes, divide, remainder is garbage andl #0xFFFF,.d0 |get rid of remainder movl .d0,.d2 |save quotient movl .d0,.sp@- |call ulmul with quotient movl .d4,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d3 |original dividend >= lmul result? jge 2$ |yes, quotient should be correct subql #1,.d2 |no, fix up quotient 2$: movl .d2,.d0 |move quotient to .d0 3$: moveml .sp@+,#0x1C |restore registers unlk .a6 rts |J. Test 1/81 |unsigned long multiply: c = a * b .globl Cp_ulmul .text addl #0,.a4 Cp_ulmul: link .a6,#0 moveml #0x3000,.sp@- |save .d2,.d3 movl .a6@(8),.d2 |.d2 = a movl .a6@(12),.d3 |.d3 = b clrl .d0 movw .d2,.d0 |.d0 = alo, unsigned mulu .d3,.d0 |.d0 = blo*alo, unsigned movw .d2,.d1 |.d1 = alo swap .d2 |swap alo-ahi mulu .d3,.d2 |.d2 = blo*ahi, unsigned swap .d3 |swap blo-bhi mulu .d3,.d1 |.d1 = bhi*alo, unsigned addl .d2,.d1 |.d1 = (ahi*blo + alo*bhi) swap .d1 |.d1 = clrw .d1 | (ahi*blo + alo*bhi)*(2**16) addl .d1,.d0 |.d0 = alo*blo + (ahi*blo + alo*bhi)*(2**16) 3$: moveml .sp@+,#0xC |restore .d2,.d3 unlk .a6 rts |J. Test 1/81 |unsigned long remainder: a = a % b .globl Cp_ulrem .text addl #0,.a4 Cp_ulrem: link .a6,#0 moveml #0x3000,.sp@- |need .d2,.d3 registers movl .a6@(8),.d0 |dividend movl .d0,.d2 |save dividend movl .a6@(12),.d1 |divisor cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 1$ |no, divisor must be < 2 ** 16 clrw .d0 |.d0 = swap .d0 | dividend high divu .d1,.d0 |yes, divide movw .d2,.d0 |.d0 = remainder high + quotient low divu .d1,.d0 |divide clrw .d0 |.d0 = swap .d0 | remainder bra 4$ |return 1$: movl .d1,.d3 |save divisor 2$: asrl #0x1,.d0 |shift dividend asrl #0x1,.d1 |shift divisor andl #0x7FFFFFFF,.d0 |assure positive andl #0x7FFFFFFF,.d1 | sign bit cmpl #0x10000,.d1 |divisor < 2 ** 16? bge 2$ |no, continue shift divu .d1,.d0 |yes, divide andl #0xFFFF,.d0 |erase remainder movl .d0,.sp@- |call ulmul with quotient movl .d3,.sp@- | and saved divisor on stack jsr [Cp_ulmul,.a4] | as arguments addql #0x8,.sp |restore .sp cmpl .d0,.d2 |original dividend >= lmul result? jge 3$ |yes, quotient should be correct subl .d3,.d0 |no, fixup 3$: subl .d2,.d0 |calculate negl .d0 | remainder 4$: moveml .sp@+,#0xC |restore registers unlk .a6 rts