home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD1.img / d1xx / d169 / src / dres / notinlib / muldiv.asm < prev   
Assembly Source File  |  1988-11-22  |  5KB  |  211 lines

  1.  
  2. ;FUNC=    MulDiv        D0/D1/D2
  3. ;FUNC=    UMulDiv     D0/D1/D2
  4. ;FUNC=    MulShift    D0/D1/D2
  5. ;FUNC=    UMulShift   D0/D1/D2
  6.  
  7.         ;    MulDiv    (a ,b ,c)   32x32->64 64/32->32     (signed)
  8.         ;    MulShift(a ,b ,n)   32x32->64 64>>n->32     (signed)
  9.         ;         D0,D1,D2
  10.         ;
  11.         ;    32x32->64 64/32->32
  12.         ;    32x32->64 64>>n->32
  13.         ;
  14.         ;    note:    n is a word
  15.  
  16.         public  _MulDiv
  17.         public  _UMulDiv
  18.         public  _MulShift
  19.         public  _UMulShift
  20.  
  21.         ;    Various connotations specifying which arguments are
  22.         ;    unsigned (you gain a bit when using unsigned arguments)
  23.  
  24. REGS        eqr     D2-D7
  25.  
  26. _UMulDiv    movem.l REGS,-(sp)
  27.         clr.w   D7
  28.         bra     .md10
  29. _MulDiv     movem.l REGS,-(sp)
  30.         clr.w   D7
  31.         tst.l   D0
  32.         bpl     .md2
  33.         neg.l   D0
  34.         tst.l   D1        ; neg
  35.         bpl     .md1    ; neg
  36.         neg.l   D1
  37.         tst.l   D2        ; neg neg
  38.         bpl     .md10   ; neg neg
  39.         neg.l   D2
  40.         bra     .md9    ; neg neg neg
  41. .md1        tst.l   D2        ; neg
  42.         bpl     .md9    ; neg
  43.         neg.l   D2
  44.         bra     .md10   ; neg neg
  45. .md2        tst.l   D1
  46.         bpl     .md3
  47.         neg.l   D1
  48.         tst.l   D2        ; neg
  49.         bpl     .md9    ; neg
  50.         neg.l   D2
  51.         bra     .md10   ; neg neg
  52. .md3        tst.l   D2
  53.         bpl     .md10
  54.         neg.l   D2
  55.         bra     .md9
  56.  
  57. _UMulShift  movem.l REGS,-(sp)
  58.         clr.w   D7
  59.         bra     .md6
  60. _MulShift   movem.l REGS,-(sp)
  61.         clr.w   D7
  62.         tst.l   D0
  63.         bpl     .md4
  64.         neg.l   D0
  65.         tst.l   D1
  66.         bpl     .md5
  67.         neg.l   D0
  68.         bra     .md6
  69. .md4        tst.l   D1
  70.         bpl     .md6
  71.         neg.l   D1
  72. .md5        addq.w  #1,D7
  73.  
  74. .md6        swap    D0
  75.         swap    D1
  76.         tst.w   D0
  77.         beq     .md601
  78.         bsr     .md0huge
  79.         beq     .md602a
  80.         bra     .md603
  81. .md601        tst.w   D1
  82.         beq     .md602
  83.         bsr     .md1huge
  84.         beq     .md602a
  85.         bra     .md603
  86. .md602        swap    D0
  87.         swap    D1
  88.         mulu    D1,D0
  89. .md602a     lsr.l   D2,D0
  90.         bra     .mddone
  91. .md603        subq.w  #1,D2
  92.         bmi     .mddone
  93. .md604        lsr.l   #1,D3
  94.         roxr.l  #1,D0
  95.         dbf     D2,.md604
  96.         bra     .mddone
  97.  
  98.  
  99. .md10        swap    D0
  100.         swap    D1
  101.         tst.w   D0
  102.         beq     .md101
  103.         bsr     .md0huge
  104.         beq     .mdsdiv
  105.         bsr     div64
  106.         bra     .mddone
  107. .md101        tst.w   D1
  108.         beq     .md105
  109.         bsr     .md1huge
  110.         beq     .mdsdiv
  111.         bsr     div64
  112.         bra     .mddone
  113. .md105        swap    D0        ; both word sized
  114.         swap    D1
  115.         mulu    D1,D0    ; D1.WxD0.W -> D0.L
  116. .mdsdiv     move.l  D2,D1
  117.         jsr     .divu#
  118.  
  119.         ;
  120.         ;
  121.  
  122. .md9        addq.w  #1,D7
  123.  
  124.         ;    All elements now unsigned, D7.W determines whether to
  125.         ;    negate at end.
  126.  
  127. .mddone     btst.l  #0,D7
  128.         beq     .mddone2
  129.         neg.l   D0
  130. .mddone2    movem.l (sp)+,REGS
  131.         rts
  132.  
  133.  
  134.         ;    NOTE:    entered with register halves reversed
  135.         ;
  136.         ;    D2 not effected
  137.         ;    Test D3 on return
  138.  
  139. .md0huge    tst.w   D1
  140.         beq     .md1hugex    ; D0.L, D1.W
  141.                 ; D0.L, D1.L    (long x long)
  142.         move.w  D0,D4    ; save ah
  143.         move.w  D0,D3    ; ah bh
  144.         mulu.w  D1,D3
  145.         swap    D0        ; al bh
  146.         move.w  D0,D5
  147.         mulu.w  D1,D5
  148.         swap    D1
  149.         mulu.w  D1,D0    ; al bl
  150.         mulu.w  D4,D1    ; ah bl
  151.         add.l   D1,D5    ; combine blah and bhal
  152.         bcc     .mud1
  153.         add.l   #$10000,D3
  154. .mud1        swap    D0        ; LSB MSB
  155.         add.w   D5,D0
  156.         swap    D0
  157.         clr.w   D5
  158.         swap    D5
  159.         addx.l  D5,D3    ;64 bit mul result: D3|D0
  160.         rts         ;Test D3
  161.  
  162.         ; D2 not effected
  163.  
  164. .md1huge    exg     D0,D1
  165. .md1hugex
  166.         ; D0.L, D1.W    al ah
  167.         ;               bl
  168.  
  169.         move.w  D0,D3
  170.         mulu.w  D1,D3    ; D3 = bl x ah
  171.         swap    D0
  172.         mulu.w  D1,D0    ; D0 = bl x al
  173.         swap    D0        ; add lsb byte of D3 to msb byte of D0
  174.         add.w   D3,D0
  175.         swap    D0
  176.         clr.w   D3        ; doesn't effect X
  177.         swap    D3        ; msb of D3 actually lsb of second longword
  178.         moveq.l #0,D1
  179.         addx    D1,D3    ; possible x(carry) from previous addition
  180.                 ; 64 bit mul result: D3|D0
  181.                 ; Test D3
  182.         rts
  183.  
  184.         ;    DIV64
  185.         ;
  186.         ;    64/32->32   D3|D0 / D2 -> D0
  187.  
  188. div64:
  189.         move.l  #0,A0    ;Divide!    D1 into D3|D0, D2 = cntr, A0 = rslt
  190.         move.w  #31,D2    ;(no initial compare).  31 + 1 iterations
  191. .mud10        adda.l  A0,A0    ;shift result left
  192.         asl.l   #1,D0    ;Shift left
  193.         roxl.l  #1,D3
  194.         cmp.l   D1,D3
  195.         blo     .mud11    ;if D3    < D1, skip
  196.         sub.l   D1,D3    ;   D3 >= D1
  197.         addq.l  #1,A0    ;result = result | 1
  198. .mud11        dbf     D2,.mud10
  199.  
  200.         ;    If remainder (D3) larger than 1/2 C (D1 >> 1), then
  201.         ;    round up result.
  202.  
  203.         lsr.l   #1,D1
  204.         cmp.l   D1,D3
  205.         blo     .mud12    ; skip if remainder < 1/2C
  206.         addq.l  #1,A0
  207. .mud12
  208.         move.l  A0,D0    ;return result
  209.         rts
  210.  
  211.