home *** CD-ROM | disk | FTP | other *** search
- ; long division and modulus routines
- ;
- ; written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
- ;
- ;
- ; Revision 1.1, kub 03-90
- ; first version, replaces the appropriate routine from fixnum.s.
- ; Should be faster in more common cases. Division is done by 68000 divu
- ; operations if divisor is only 16 bits wide. Otherwise the normal division
- ; algorithm as described in various papers takes place. The division routine
- ; delivers the quotient in d0 and the remainder in d1, thus the implementation
- ; of the modulo operation is trivial. We gain some extra speed by inlining
- ; the division code here instead of calling __udivsi3.
-
- text
- even
- xdef __CXD22
-
- __CXD22:
- movem.l d0-d3,-(sp)
- subq.w #4,sp
- clr.w -(sp) ; sign flag
- clr.l d0 ; prepare result
- move.l 10(sp),d2 ; get divisor
- beq.s 10$ ; divisor = 0 causes a division trap
- bpl.s 1$ ; divisor < 0 ?
- neg.l d2 ; negate it
- not.w (sp) ; remember sign
- 1$: move.l 6(sp),d1 ; get dividend
- bpl.s 2$ ; dividend < 0 ?
- neg.l d1 ; negate it
- not.w (sp) ; remember sign
- 2$:
- ;== case 1) divident < divisor
- cmp.l d2,d1 ; is divident smaller then divisor ?
- bcs.s 7$ ; yes, return immediately
- ;== case 2) divisor has <= 16 significant bits
- tst.w 10(sp)
- bne.s 4$ ; divisor has only 16 bits
- move.w d1,d3 ; save dividend
- clr.w d1 ; divide dvd.h by dvs
- swap d1
- beq.s 3$ ; (no division necessary if dividend zero)
- divu.w d2,d1
- 3$: move.w d1,d0 ; save quotient.h
-
- swap d0
- move.w d3,d1 ; (d0.h = remainder of prev divu)
- divu.w d2,d1 ; divide dvd.l by dvs
- move.w d1,d0 ; save quotient.l
- clr.w d1 ; get remainder
- swap d1
- bra.s 7$ ; and return
- ;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
- 4$:
- moveq.l #31,d3 ; loop count
- 5$:
- add.l d1,d1 ; shift divident ...
- addx.l d0,d0 ; ... into d0
- cmp.l d2,d0 ; compare with divisor
- bcs.s 6$
- sub.l d2,d0 ; big enough, subtract
- add.w #1,d1 ; and note bit into result
- 6$:
- dbra d3,5$
- exg d0,d1 ; put quotient and remainder in their registers
- 7$:
- tst.w 6(sp) ; must the remainder be corrected ?
- bpl.s 8$
- neg.l d1 ; yes, apply sign
- ; the following line would be correct if modulus is defined as in algebra
- ; add.l 6(sp),d1 ; algebraic correction: modulus can only be >= 0
- 8$: tst.w (sp)+ ; result should be negative ?
- bpl.s 9$
- neg.l d0 ; yes, negate it
- 9$:
- lea 12(sp),sp
- movem.l (sp)+,d2-d3
- rts
- 10$:
- divu d2,d1 ; cause division trap
- bra 7$ ; back to user
- end
-