| [4f508e6] | 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 | | ------------------------------------------------------------------------------
|
|---|
| [f40a309] | 19 | .text
|
|---|
| [4f508e6] | 20 |
|
|---|
| [f40a309] | 21 | .xdef _uldiv,_uldivr
|
|---|
| [4f508e6] | 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 |
|
|---|
| [f40a309] | 52 | .page
|
|---|
| [4f508e6] | 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 |
|
|---|
| [f40a309] | 91 | .bss
|
|---|
| 92 | .even
|
|---|
| [4f508e6] | 93 |
|
|---|
| [f40a309] | 94 | _uldivr: ds.l 1
|
|---|
| [4f508e6] | 95 |
|
|---|
| [f40a309] | 96 | .end
|
|---|