home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / lattice / _divmods.s next >
Text File  |  1992-06-15  |  3KB  |  84 lines

  1. ; long division and modulus routines
  2. ;
  3. ; written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  4. ;
  5. ;
  6. ; Revision 1.1, kub 03-90
  7. ; first version, replaces the appropriate routine from fixnum.s.
  8. ; Should be faster in more common cases. Division is done by 68000 divu
  9. ; operations if divisor is only 16 bits wide. Otherwise the normal division
  10. ; algorithm as described in various papers takes place. The division routine
  11. ; delivers the quotient in d0 and the remainder in d1, thus the implementation
  12. ; of the modulo operation is trivial. We gain some extra speed by inlining
  13. ; the division code here instead of calling __udivsi3.
  14.  
  15.     text
  16.     even
  17.     xdef    __CXD22
  18.  
  19. __CXD22:
  20.     movem.l    d0-d3,-(sp)
  21.     subq.w    #4,sp
  22.     clr.w    -(sp)        ; sign flag
  23.     clr.l    d0        ; prepare result
  24.     move.l    10(sp),d2    ; get divisor
  25.     beq.s    10$        ; divisor = 0 causes a division trap
  26.     bpl.s    1$        ; divisor < 0 ?
  27.     neg.l    d2        ; negate it
  28.     not.w    (sp)        ; remember sign
  29. 1$:    move.l    6(sp),d1    ; get dividend
  30.     bpl.s    2$        ; dividend < 0 ?
  31.     neg.l    d1        ; negate it
  32.     not.w    (sp)        ; remember sign
  33. 2$:
  34. ;== case 1) divident < divisor
  35.     cmp.l    d2,d1        ; is divident smaller then divisor ?
  36.     bcs.s    7$        ; yes, return immediately
  37. ;== case 2) divisor has <= 16 significant bits
  38.     tst.w    10(sp)
  39.     bne.s    4$        ; divisor has only 16 bits
  40.     move.w    d1,d3        ; save dividend
  41.     clr.w    d1        ; divide dvd.h by dvs
  42.     swap    d1
  43.     beq.s    3$        ; (no division necessary if dividend zero)
  44.     divu.w    d2,d1
  45. 3$:    move.w    d1,d0        ; save quotient.h
  46.  
  47.     swap    d0
  48.     move.w    d3,d1        ; (d0.h = remainder of prev divu)
  49.     divu.w    d2,d1        ; divide dvd.l by dvs
  50.     move.w    d1,d0        ; save quotient.l
  51.     clr.w    d1        ; get remainder
  52.     swap    d1
  53.     bra.s    7$        ; and return
  54. ;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
  55. 4$:
  56.     moveq.l    #31,d3        ; loop count
  57. 5$:
  58.     add.l    d1,d1        ; shift divident ...
  59.     addx.l    d0,d0        ;  ... into d0
  60.     cmp.l    d2,d0        ; compare with divisor
  61.     bcs.s    6$
  62.     sub.l    d2,d0        ; big enough, subtract
  63.     add.w    #1,d1        ; and note bit into result
  64. 6$:
  65.     dbra    d3,5$
  66.     exg    d0,d1        ; put quotient and remainder in their registers
  67. 7$:
  68.     tst.w    6(sp)        ; must the remainder be corrected ?
  69.     bpl.s    8$
  70.     neg.l    d1        ; yes, apply sign
  71. ; the following line would be correct if modulus is defined as in algebra
  72. ;    add.l    6(sp),d1    ; algebraic correction: modulus can only be >= 0
  73. 8$:    tst.w    (sp)+        ; result should be negative ?
  74.     bpl.s    9$
  75.     neg.l    d0        ; yes, negate it
  76. 9$:
  77.     lea    12(sp),sp
  78.     movem.l    (sp)+,d2-d3
  79.     rts
  80. 10$:
  81.     divu    d2,d1        ; cause division trap
  82.     bra    7$        ; back to user
  83.     end
  84.