home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / lib / mntc6846.zoo / patch / sfdiv.s < prev    next >
Encoding:
Text File  |  1994-11-26  |  4.9 KB  |  154 lines

  1.  ! C68 4 byte floating point divide routine
  2.  !-----------------------------------------------------------------------------
  3.  ! ported to 68000 by Kai-Uwe Bloem, 12/89
  4.  !  #1    original author: Peter S. Housel 4/8/89,6/2/89,6/13/89
  5.  !  #2    added support for denormalized numbers            -kub-, 01/90
  6.  !  #3    change loop criterion for division loop to have a 1 behind the implied
  7.  !    1 position of result. This gives greater accuracy, especially when
  8.  !    dealing with denormalized numbers (although there are now eventually
  9.  !    8 bits which are no longer calculated - .norm8 uses 4 of them for
  10.  !    rounding)                        -kub-, 01/90
  11.  !  bugs:
  12.  !    Division has only 4 rounding bits. There is no "sticky bit" information.
  13.  !    Due to speed improvements the code is rather cryptic.
  14.  !  #4  Redid register usage, and then added wrapper routine
  15.  !    to provide C68 IEEE compatibility    Dave & Keith Walker    02/92
  16.  !  #5  Changed exit code to put pointer to result in D0   Dave Walker  12/92
  17.  !  #6  Changed entry/exit code for C68 v4.3 compatibility
  18.  !    Removed ACK entry points.                    09/93
  19.  !-----------------------------------------------------------------------------
  20.  
  21. SAVEREG    =    3*4        ! offset of multiplicand
  22. BIAS4    =    0x7F - 1
  23.  
  24.     .sect .text
  25.  
  26.     .define .Xsfdiv
  27.     .define .Xassfdiv
  28.  
  29. !----------------------------------------
  30. !    sp    Return address
  31. !    sp+4    address of result
  32. !    sp+8    address of second operand
  33. !    sp+12    address of first operand
  34. !----------------------------------------
  35.  
  36. .Xsfdiv:
  37.     movem.l    d3/d4/d6,-(sp)        ! save registers
  38.     move.l    SAVEREG+12(sp),a1    ! address of v
  39.     move.l    (a1),d4            ! load v
  40.     move.l    SAVEREG+8(sp),a1    ! address of u
  41.     move.l    (a1),d6            ! load u
  42.     move.l    SAVEREG+4(sp),a1    ! result address
  43.     bsr    sfdivide
  44.     movem.l    (sp)+,d3/d4/d6        ! restore saved registers
  45.  
  46.     move.l    (sp)+,a1        ! get return address
  47.     lea    12(sp),sp        ! remove 3 parameters from stack
  48.     jmp    (a1)            ! ... and return
  49.  
  50. !----------------------------------------
  51. !    sp    Return address
  52. !    sp+4    address of result/first operand
  53. !    sp+8    address of second operand
  54. !----------------------------------------
  55.  
  56. .Xassfdiv:
  57.     movem.l    d3/d4/d6,-(sp)        ! save registers
  58.     move.l    SAVEREG+8(sp),a1    ! address of v
  59.     move.l    (a1),d4            ! load v
  60.     move.l    SAVEREG+4(sp),a1    ! address of u / result address
  61.     move.l    (a1),d6            ! load u
  62.     bsr    sfdivide        ! do operation
  63.     movem.l    (sp)+,d3/d4/d6        ! restore saved registers
  64.  
  65.     move.l    (sp)+,a1        ! get return address
  66.     move.l    (sp),d0            ! address of v returned as result
  67.     addq.l    #8,sp            ! remove 2 parameters from stack
  68.     jmp    (a1)            ! ... and return
  69.  
  70.  !-------------------------------------------------------------------------
  71.  ! This is the routine that actually carries out the operation.
  72.  !
  73.  ! Register usage:
  74.  !
  75.  !        Entry                Exit
  76.  !
  77.  !    d0    ?                undefined
  78.  !    d1    ?                undefined
  79.  !    d2    ?                undefined
  80.  !    d3    ?                undefined
  81.  !    d4    v                undefined
  82.  !    d6    u                undefined
  83.  !
  84.  !    A1    Address for result        preserved
  85.  !
  86.  !-----------------------------------------------------------------------------
  87.  
  88. sfdivide:
  89.     move.l    d6,d0        ! d0 = u.exp
  90.     swap    d0
  91.     move.w    d0,d2        ! d2 = u.sign
  92.  
  93.     move.l    d4,d1        ! d1 = v.exp
  94.     swap    d1
  95.     eor.w    d1,d2        ! d2 = u.sign ^ v.sign (in bit 31)
  96.  
  97.     and.l    #0x07fffff,d6    ! remove exponent from u.mantissa
  98.     lsr.w    #7,d0        ! right justify exponent in word
  99.     and.w    #0x0ff,d0    ! kill sign bit
  100.     beq    0f        ! check for zero exponent - no leading "1"
  101.     or.l    #0x800000,d6    ! restore implied leading "1"
  102.     bra    1f
  103. 0:    add.w    #1,d0        ! "normalize" exponent
  104. 1:    tst.l    d6        ! zero ?
  105.     beq    retz        ! dividing zero
  106.  
  107.     and.l    #0x07fffff,d4    ! remove exponent from v.mantissa
  108.     lsr.w    #7,d1        ! right justify exponent in word
  109.     and.w    #0x0ff,d1    ! kill sign bit
  110.     beq    0f        ! check for zero exponent - no leading "1"
  111.     or.l    #0x800000,d4    ! restore implied leading "1"
  112.     bra    1f
  113. 0:    add.w    #1,d1        ! "normalize" exponent
  114. 1:    tst.l    d4
  115.     beq    divz        ! divide by zero
  116.  
  117.     sub.w    d1,d0        ! subtract exponents,
  118.     add.w    #BIAS4-8+1,d0    !  add bias back in, account for shift
  119.     add.w    #32+2,d0    !  add loop offset, +2 for extra rounding bits
  120.                 !   for denormalized numbers (2 implied by dbra)
  121.     move    #27,d1        ! bit number for "implied" pos (+4 for rounding)
  122.     move.l    #-1,d3        ! zero the quotient 
  123.                 ! (for speed it is a one s complement)
  124.     sub.l    d4,d6        ! initial subtraction, u = u - v
  125. 2:
  126.     btst    d1,d3        ! divide until 1 in implied position
  127.     beq    5f
  128.  
  129.     add.l    d6,d6
  130.     bcs    4f        ! if carry is set, add, else subtract
  131.  
  132.     addx.l    d3,d3        ! shift quotient and set bit zero
  133.     sub.l    d4,d6        ! subtract u = u - v
  134.     dbra    d0,2b        ! give up if result is denormalized
  135.     bra    5f
  136. 4:
  137.     addx.l    d3,d3        ! shift quotient and clear bit zero
  138.     add.l    d4,d6        ! add (restore) u = u + v
  139.     dbra    d0,2b        ! give up if result is denormalized
  140. 5:    sub.w    #2,d0        ! remove rounding offset for denormalized nums
  141.     not.l    d3        ! invert quotient to get it right
  142.  
  143.     move.l    d3,(a1)        ! save quotient mantissa
  144.     clr.w    d1        ! zero rounding bits
  145.     jmp    .Xnorm4        ! exit via normalise (a1 still points to result)
  146.  
  147. retz:    clr.l    (a1)        ! zero destination
  148.     rts             ! no normalization needed
  149.  
  150. divz:
  151.     jsr    .divzero    ! call xception routine
  152.     move.l    d0,(a1)        ! store result if control returned
  153.     rts            ! exit - no normalisation needed
  154.