home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mntlib18 / sozolong.s < prev    next >
Encoding:
Text File  |  1993-08-03  |  4.5 KB  |  190 lines

  1. ; long arithmetic routines
  2. ;
  3. ; written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  4. ;
  5. ; Names changed and converted from MIT to Motorola syntax by Dave Gymer for SC
  6.  
  7.     .text
  8.     .even
  9.     .globl    lmul,lmulu
  10.     .globl    ldiv,ldivu
  11.     .globl    lrem,lremu
  12.  
  13. ldiv:
  14.     move.l    d2,a0        ; save registers
  15.     move.l    d3,a1
  16.     clr.w    -(sp)        ; sign flag
  17.     clr.l    d0        ; prepare result
  18.     move.l    10(sp),d2    ; get divisor
  19.     beq    L9        ; divisor = 0 causes a division trap
  20.     bpl    J0        ; divisor < 0 ?
  21.     neg.l    d2        ; negate it
  22.     not.w    (sp)        ; remember sign
  23. J0:    move.l    6(sp),d1    ; get dividend
  24.     bpl    J1        ; dividend < 0 ?
  25.     neg.l    d1        ; negate it
  26.     not.w    (sp)        ; remember sign
  27. J1:
  28. ;== case 1) divident < divisor
  29.     cmp.l    d2,d1        ; is divident smaller then divisor ?
  30.     bcs    L8        ; yes, return immediately
  31. ;== case 2) divisor has <= 16 significant bits
  32.     tst.w    10(sp)
  33.     bne    L2        ; divisor has only 16 bits
  34.     move.w    d1,d3        ; save dividend
  35.     clr.w    d1        ; divide dvd.h by dvs
  36.     swap    d1
  37.     beq    J2        ; (no division necessary if dividend zero)
  38.     divu    d2,d1
  39. J2:    move.w    d1,d0        ; save quotient.h
  40.     swap    d0
  41.     move.w    d3,d1        ; (d0.h = remainder of prev divu)
  42.     divu    d2,d1        ; divide dvd.l by dvs
  43.     move.w    d1,d0        ; save quotient.l
  44.     clr.w    d1        ; get remainder
  45.     swap    d1
  46.     bra    L8        ; and return
  47. ;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
  48. L2:
  49.     moveq    #31,d3        ; loop count
  50. L3:
  51.     add.l    d1,d1        ; shift divident ...
  52.     addx.l    d0,d0        ;  ... into d0
  53.     cmp.l    d2,d0        ; compare with divisor
  54.     bcs    J3
  55.     sub.l    d2,d0        ; big enough, subtract
  56.     add.w    #1,d1        ; and note bit into result
  57. J3:
  58.     dbra    d3,L3
  59.     exg    d0,d1        ; put quotient and remainder in their registers
  60. L8:
  61.     tst.w    6(sp)        ; must the remainder be corrected ?
  62.     bpl    J4
  63.     neg.l    d1        ; yes, apply sign
  64. ; the following line would be correct if modulus is defined as in algebra
  65. ;    add.l    6(sp),d1    ; algebraic correction: modulus can only be >= 0
  66. J4:    tst.w    (sp)+        ; result should be negative ?
  67.     bpl    J5
  68.     neg.l    d0        ; yes, negate it
  69. J5:
  70.     move.l    a1,d3
  71.     move.l    a0,d2
  72.     rts
  73. L9:
  74.     divu    d2,d1        ; cause division trap
  75.     bra    L8        ; back to user
  76.  
  77. lrem:
  78.     move.l    8(sp),-(sp)    ; push divisor
  79.     move.l    8(sp),-(sp)    ; push dividend
  80.     bsr    ldiv
  81.     lea    8(sp),sp
  82.     move.l    d1,d0        ; return the remainder in d0
  83.     rts
  84.  
  85. ldivu:
  86.     move.l    d2,a0        ; save registers
  87.     move.l    d3,a1
  88.     clr.l    d0        ; prepare result
  89.     move.l    8(sp),d2    ; get divisor
  90.     beq    N9        ; divisor = 0 causes a division trap
  91.     move.l    4(sp),d1    ; get dividend
  92. ;== case 1) divident < divisor
  93.     cmp.l    d2,d1        ; is divident smaller then divisor ?
  94.     bcs    N8        ; yes, return immediately
  95. ;== case 2) divisor has <= 16 significant bits
  96.     tst.w    8(sp)
  97.     bne    N2        ; divisor has only 16 bits
  98.     move.w    d1,d3        ; save dividend
  99.     clr.w    d1        ; divide dvd.h by dvs
  100.     swap    d1
  101.     beq    K0        ; (no division necessary if dividend zero)
  102.     divu    d2,d1
  103. K0:    move.w    d1,d0        ; save quotient.h
  104.     swap    d0
  105.     move.w    d3,d1        ; (d1.h = remainder of prev divu)
  106.     divu    d2,d1        ; divide dvd.l by dvs
  107.     move.w    d1,d0        ; save quotient.l
  108.     clr.w    d1        ; get remainder
  109.     swap    d1
  110.     bra    N8        ; and return
  111. ;== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
  112. N2:
  113.     moveq    #31,d3        ; loop count
  114. N3:
  115.     add.l    d1,d1        ; shift divident ...
  116.     addx.l    d0,d0        ;  ... into d0
  117.     cmp.l    d2,d0        ; compare with divisor
  118.     bcs    K1
  119.     sub.l    d2,d0        ; big enough, subtract
  120.     add.w    #1,d1        ; and note bit in result
  121. K1:
  122.     dbra    d3,N3
  123.     exg    d0,d1        ; put quotient and remainder in their registers
  124. N8:
  125.     move.l    a1,d3
  126.     move.l    a0,d2
  127.     rts
  128. N9:
  129.     divu    d2,d1        ; cause division trap
  130.     bra    N8        ; back to user
  131.  
  132. lremu:
  133.     move.l    8(sp),-(sp)    ; push divisor
  134.     move.l    8(sp),-(sp)    ; push dividend
  135.     bsr    ldivu
  136.     lea    8(sp),sp
  137.     move.l    d1,d0        ; return the remainder in d0
  138.     rts
  139.  
  140. lmul:
  141.     move.l    d2,a0        ; save registers
  142.     move.l    d3,a1
  143.     movem.w    4(sp),d0-d3    ; get the two longs. u = d0-d1, v = d2-d3
  144.     move.w    d0,-(sp)        ; sign flag
  145.     bpl    J6        ; is u negative ?
  146.     neg.w    d1        ; yes, force it positive
  147.     negx.w    d0
  148. J6:    tst.w    d2        ; is v negative ?
  149.     bpl    J7
  150.     neg.w    d3        ; yes, force it positive ...
  151.     negx.w    d2
  152.     not.w    (sp)        ;  ... and modify flag word
  153. J7:
  154.     ext.l    d0        ; u.h <> 0 ?
  155.     beq    M1
  156.     mulu    d3,d0        ; r  = v.l * u.h
  157. M1:    tst.w    d2        ; v.h <> 0 ?
  158.     beq    M2
  159.     mulu    d1,d2        ; r += v.h * u.l
  160.     add.w    d2,d0
  161. M2:    swap    d0
  162.     clr.w    d0
  163.     mulu    d3,d1        ; r += v.l * u.l
  164.     add.l    d1,d0
  165.     move.l    a1,d3
  166.     move.l    a0,d2
  167.     tst.w    (sp)+        ; should the result be negated ?
  168.     bpl    M3        ; no, just return
  169.     neg.l    d0        ; else r = -r
  170. M3:    rts
  171.  
  172. lmulu:
  173.     move.l    d2,a0        ; save registers
  174.     move.l    d3,a1
  175.     movem.w    4(sp),d0-d3    ; get the two longs. u = d0-d1, v = d2-d3
  176.     ext.l    d0        ; u.h <> 0 ?
  177.     beq    O1
  178.     mulu    d3,d0        ; r  = v.l * u.h
  179. O1:    tst.w    d2        ; v.h <> 0 ?
  180.     beq    O2
  181.     mulu    d1,d2        ; r += v.h * u.l
  182.     add.w    d2,d0
  183. O2:    swap    d0
  184.     clr.w    d0
  185.     mulu    d3,d1        ; r += v.l * u.l
  186.     add.l    d1,d0
  187.     move.l    a1,d3
  188.     move.l    a0,d2
  189.     rts
  190.