[3ae31e9] | 1 | * ------------------------------------------------------------------------------
|
---|
| 2 | * uldiv.s -- unsigned long division, with remainder
|
---|
| 3 | * Version 2 -- 1987-06-08 -- D.N. Lynx Crowe
|
---|
| 4 | * Lifted from the Alcyon C library by disassembly so I could fix a bug -
|
---|
| 5 | * _uldivr must be in the bss segment so the code will work in PROM.
|
---|
| 6 | *
|
---|
| 7 | * long
|
---|
| 8 | * uldiv(dividnd, divisor)
|
---|
| 9 | * long dividnd, divisor;
|
---|
| 10 | *
|
---|
| 11 | * extern long uldivr;
|
---|
| 12 | *
|
---|
| 13 | * Divides 'dividnd' by 'divisor', treating both as unsigned
|
---|
| 14 | * long integers. Returns the quotient and leaves the
|
---|
| 15 | * remainder in 'uldivr'. Produces a divide check on division
|
---|
| 16 | * by zero, with $80000000 returned for both quotient and
|
---|
| 17 | * remainder.
|
---|
| 18 | * ------------------------------------------------------------------------------
|
---|
| 19 | .text
|
---|
| 20 | *
|
---|
| 21 | .xdef _uldiv,_uldivr
|
---|
| 22 | *
|
---|
| 23 | DIVIDEND .equ 8
|
---|
| 24 | DIVISOR .equ 12
|
---|
| 25 | *
|
---|
| 26 | _uldiv: link a6,#0 * Link stack frames
|
---|
| 27 | movem.l d3-d7,-(a7) * Save registers
|
---|
| 28 | move.l DIVIDEND(a6),d7 * d7 = DIVIDEND
|
---|
| 29 | move.l DIVISOR(a6),d6 * d6 = DIVISOR
|
---|
| 30 | tst.l d6 * Divide by zero ?
|
---|
| 31 | bne notdzero * Jump if not
|
---|
| 32 | *
|
---|
| 33 | move.l #$80000000,_uldivr * Force error result
|
---|
| 34 | move.l #$80000000,d0 * ... by dividing
|
---|
| 35 | divu #0,d0 * ... by zero
|
---|
| 36 | bra ulexit * ... then exit
|
---|
| 37 | *
|
---|
| 38 | notdzero: cmp.l d7,d6 * Divide underflow ?
|
---|
| 39 | bls notunflo * Jump if not
|
---|
| 40 | *
|
---|
| 41 | move.l d7,_uldivr * Remainder = dividend
|
---|
| 42 | clr.l d0 * Quotient = 0
|
---|
| 43 | bra ulexit * Exit
|
---|
| 44 | *
|
---|
| 45 | notunflo: cmp.l d6,d7 * Is dividend = divisor ?
|
---|
| 46 | bne startdiv * Go start dividing if not
|
---|
| 47 | *
|
---|
| 48 | moveq.l #1,d5 * Quotient = 1
|
---|
| 49 | clr.l d7 * Remainder = 0
|
---|
| 50 | bra setreslt * Go set result
|
---|
| 51 | *
|
---|
| 52 | .page
|
---|
| 53 | *
|
---|
| 54 | startdiv: moveq.l #1,d4 * Set result bit in d4
|
---|
| 55 | *
|
---|
| 56 | divloop1: cmp.l d6,d7 * Divisor aligned OK ?
|
---|
| 57 | bcs divloop2 * Jump if so
|
---|
| 58 | *
|
---|
| 59 | move.l d6,d0 * Can we align things better ?
|
---|
| 60 | asl.l #1,d0 * ...
|
---|
| 61 | cmp.l d0,d6 * ...
|
---|
| 62 | bhi divloop2 * Jump if not
|
---|
| 63 | *
|
---|
| 64 | asl.l #1,d6 * Shift the divisor
|
---|
| 65 | asl.l #1,d4 * Shift the result bit
|
---|
| 66 | bra divloop1 * Loop for next bit
|
---|
| 67 | *
|
---|
| 68 | divloop2: clr.l d5 * Clear quotient
|
---|
| 69 | *
|
---|
| 70 | divloop3: tst.l d4 * More bits to do ?
|
---|
| 71 | beq setreslt * Go set result if not
|
---|
| 72 | *
|
---|
| 73 | cmp.l d6,d7 * Can we subtract ?
|
---|
| 74 | bcs divloop4 * Jump if not
|
---|
| 75 | *
|
---|
| 76 | or.l d4,d5 * Set a bit in the quotient
|
---|
| 77 | sub.l d6,d7 * Subtract divisor from dividend
|
---|
| 78 | *
|
---|
| 79 | divloop4: lsr.l #1,d4 * Shift the result bit
|
---|
| 80 | lsr.l #1,d6 * Shift the divisor
|
---|
| 81 | bra divloop3 * Loop for next bit
|
---|
| 82 | *
|
---|
| 83 | setreslt: move.l d7,_uldivr * Store remainder
|
---|
| 84 | move.l d5,d0 * Put quotient in d0
|
---|
| 85 | *
|
---|
| 86 | ulexit: tst.l (a7)+ * Discard top of stack
|
---|
| 87 | movem.l (a7)+,d4-d7 * Restore registers
|
---|
| 88 | unlk a6 * Unlink stack frames
|
---|
| 89 | rts * Return to caller
|
---|
| 90 | *
|
---|
| 91 | .bss
|
---|
| 92 | .even
|
---|
| 93 | *
|
---|
| 94 | _uldivr: ds.l 1
|
---|
| 95 | *
|
---|
| 96 | .end
|
---|