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