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
|
---|