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 0x80000000 returned for both quotient and
|
---|
17 | | remainder.
|
---|
18 | | ------------------------------------------------------------------------------
|
---|
19 | .text
|
---|
20 |
|
---|
21 | .xdef uldiv,uldivr
|
---|
22 |
|
---|
23 | DIVIDEND = 8
|
---|
24 | DIVISOR = 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 #0x80000000,uldivr | Force error result
|
---|
34 | move.l #0x80000000,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
|
---|