^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) | round.sa 3.4 7/29/91
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) | handle rounding and normalization tasks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) | Copyright (C) Motorola, Inc. 1990
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) | All Rights Reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) | For details on the license for this file, please see the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) | file, README, in this same directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) |ROUND idnt 2,1 | Motorola 040 Floating Point Software Package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) |section 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "fpsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) | round --- round result according to precision/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) | a0 points to the input operand in the internal extended format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) | d1(high word) contains rounding precision:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) | ext = $0000xxxx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) | sgl = $0001xxxx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) | dbl = $0002xxxx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) | d1(low word) contains rounding mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) | RN = $xxxx0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) | RZ = $xxxx0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) | RM = $xxxx0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) | RP = $xxxx0011
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) | d0{31:29} contains the g,r,s bits (extended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) | On return the value pointed to by a0 is correctly rounded,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) | a0 is preserved and the g-r-s bits in d0 are cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) | The result is not typed - the tag field is invalid. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) | result is still in the internal extended format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) | The INEX bit of USER_FPSR will be set if the rounded result was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) | inexact (i.e. if any of the g-r-s bits were set).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .global round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) round:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) | If g=r=s=0 then result is exact and round is done, else set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) | the inex flag in status reg and continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) bsrs ext_grs |this subroutine looks at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) | :rounding precision and sets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) | ;the appropriate g-r-s bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) tstl %d0 |if grs are zero, go force
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) bne rnd_cont |lower bits to zero for size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) swap %d1 |set up d1.w for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bra truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rnd_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) | Use rounding mode as an index into a jump table for these modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) lea mode_tab,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) movel (%a1,%d1.w*4),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) jmp (%a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) | Jump table indexed by rounding mode in d1.w. All following assumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) | grs != 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) mode_tab:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .long rnd_near
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .long rnd_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .long rnd_mnus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) .long rnd_plus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) | ROUND PLUS INFINITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) | If sign of fp number = 0 (positive), then add 1 to l.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) rnd_plus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) swap %d1 |set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) tstb LOCAL_SGN(%a0) |check for sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bmi truncate |if positive then truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) movel #0xffffffff,%d0 |force g,r,s to be all f's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) lea add_to_l,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) movel (%a1,%d1.w*4),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) jmp (%a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) | ROUND MINUS INFINITY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) | If sign of fp number = 1 (negative), then add 1 to l.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) rnd_mnus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) swap %d1 |set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) tstb LOCAL_SGN(%a0) |check for sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) bpl truncate |if negative then truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) movel #0xffffffff,%d0 |force g,r,s to be all f's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) lea add_to_l,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) movel (%a1,%d1.w*4),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) jmp (%a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) | ROUND ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) | Always truncate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) rnd_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) swap %d1 |set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) bra truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) | ROUND NEAREST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) | If (g=1), then add 1 to l and if (r=s=0), then clear l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) | Note that this will round to even in case of a tie.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) rnd_near:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) swap %d1 |set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) asll #1,%d0 |shift g-bit to c-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) bcc truncate |if (g=1) then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) lea add_to_l,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) movel (%a1,%d1.w*4),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) jmp (%a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) | ext_grs --- extract guard, round and sticky bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) | Input: d1 = PREC:ROUND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) | Output: d0{31:29}= guard, round, sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) | The ext_grs extract the guard/round/sticky bits according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) | selected rounding precision. It is called by the round subroutine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) | only. All registers except d0 are kept intact. d0 becomes an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) | updated guard,round,sticky in d0{31:29}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) | Notes: the ext_grs uses the round PREC, and therefore has to swap d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) | prior to usage, and needs to restore d1 to original.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ext_grs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) swap %d1 |have d1.w point to round precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) cmpiw #0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) bnes sgl_or_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) bras end_ext_grs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) sgl_or_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) moveml %d2/%d3,-(%a7) |make some temp registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) cmpiw #1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) bnes grs_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) grs_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) bfextu LOCAL_HI(%a0){#24:#2},%d3 |sgl prec. g-r are 2 bits right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) movel #30,%d2 |of the sgl prec. limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) lsll %d2,%d3 |shift g-r bits to MSB of d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) movel LOCAL_HI(%a0),%d2 |get word 2 for s-bit test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) andil #0x0000003f,%d2 |s bit is the or of all other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) bnes st_stky |bits to the right of g-r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) tstl LOCAL_LO(%a0) |test lower mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) bnes st_stky |if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) tstl %d0 |test original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) bnes st_stky |if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bras end_sd |if words 3 and 4 are clr, exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) grs_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bfextu LOCAL_LO(%a0){#21:#2},%d3 |dbl-prec. g-r are 2 bits right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) movel #30,%d2 |of the dbl prec. limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) lsll %d2,%d3 |shift g-r bits to the MSB of d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) movel LOCAL_LO(%a0),%d2 |get lower mantissa for s-bit test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) andil #0x000001ff,%d2 |s bit is the or-ing of all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) bnes st_stky |other bits to the right of g-r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) tstl %d0 |test word original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bnes st_stky |if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bras end_sd |if clear, exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) st_stky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) bset #rnd_stky_bit,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) end_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) movel %d3,%d0 |return grs to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) moveml (%a7)+,%d2/%d3 |restore scratch registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) end_ext_grs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) swap %d1 |restore d1 to original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) |******************* Local Equates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .set ad_1_sgl,0x00000100 | constant to add 1 to l-bit in sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .set ad_1_dbl,0x00000800 | constant to add 1 to l-bit in dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) |Jump table for adding 1 to the l-bit indexed by rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) add_to_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) .long add_ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) .long add_sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .long add_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .long add_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) | ADD SINGLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) add_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) addl #ad_1_sgl,LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) bccs scc_clr |no mantissa overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) roxrw LOCAL_HI(%a0) |shift v-bit back in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) roxrw LOCAL_HI+2(%a0) |shift v-bit back in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) addw #0x1,LOCAL_EX(%a0) |and incr exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) scc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) tstl %d0 |test for rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) bnes sgl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) andiw #0xfe00,LOCAL_HI+2(%a0) |clear the l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) sgl_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) andil #0xffffff00,LOCAL_HI(%a0) |truncate bits beyond sgl limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) clrl LOCAL_LO(%a0) |clear d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) | ADD EXTENDED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) add_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) addql #1,LOCAL_LO(%a0) |add 1 to l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) bccs xcc_clr |test for carry out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) addql #1,LOCAL_HI(%a0) |propagate carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) bccs xcc_clr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) roxrw LOCAL_HI(%a0) |mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) roxrw LOCAL_HI+2(%a0) |mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) roxrw LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) roxrw LOCAL_LO+2(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) addw #0x1,LOCAL_EX(%a0) |and inc exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) xcc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) tstl %d0 |test rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) bnes add_ext_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) andib #0xfe,LOCAL_LO+3(%a0) |clear the l bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) add_ext_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) | ADD DOUBLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) add_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) addl #ad_1_dbl,LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) bccs dcc_clr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) addql #1,LOCAL_HI(%a0) |propagate carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) bccs dcc_clr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) roxrw LOCAL_HI(%a0) |mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) roxrw LOCAL_HI+2(%a0) |mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) roxrw LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) roxrw LOCAL_LO+2(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) addw #0x1,LOCAL_EX(%a0) |incr exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) dcc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) tstl %d0 |test for rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) bnes dbl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) andiw #0xf000,LOCAL_LO+2(%a0) |clear the l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) dbl_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) andil #0xfffff800,LOCAL_LO(%a0) |truncate bits beyond dbl limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) | Truncate all other bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) trunct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .long end_rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .long sgl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .long dbl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .long dbl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) truncate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) lea trunct,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) movel (%a1,%d1.w*4),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) jmp (%a1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) end_rnd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) | NORMALIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) | These routines (nrm_zero & nrm_set) normalize the unnorm. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) | is done by shifting the mantissa left while decrementing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) | exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) | NRM_SET shifts and decrements until there is a 1 set in the integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) | bit of the mantissa (msb in d1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) | NRM_ZERO shifts and decrements until there is a 1 set in the integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) | bit of the mantissa (msb in d1) unless this would mean the exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) | would go less than 0. In that case the number becomes a denorm - the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) | exponent (d0) is set to 0 and the mantissa (d1 & d2) is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) | normalized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) | Note that both routines have been optimized (for the worst case) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) | therefore do not have the easy to follow decrement/shift loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) | NRM_ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) | Distance to first 1 bit in mantissa = X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) | Distance to 0 from exponent = Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) | If X < Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) | Then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) | nrm_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) | Else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) | shift mantissa by Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) | set exponent = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) |input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) | FP_SCR1 = exponent, ms mantissa part, ls mantissa part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) |output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) | L_SCR1{4} = fpte15 or ete15 bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .global nrm_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) nrm_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) movew LOCAL_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) cmpw #64,%d0 |see if exp > 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) bmis d0_less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) bsr nrm_set |exp > 64 so exp won't exceed 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) d0_less:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) moveml %d2/%d3/%d5/%d6,-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) movel LOCAL_HI(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) movel LOCAL_LO(%a0),%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) bfffo %d1{#0:#32},%d3 |get the distance to the first 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) | ;in ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) beqs ms_clr |branch if no bits were set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) cmpw %d3,%d0 |of X>Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) bmis greater |then exp will go past 0 (neg) if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) | ;it is just shifted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) bsr nrm_set |else exp won't go past 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) moveml (%a7)+,%d2/%d3/%d5/%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) greater:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) movel %d2,%d6 |save ls mant in d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) lsll %d0,%d2 |shift ls mant by count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) lsll %d0,%d1 |shift ms mant by count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) movel #32,%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) subl %d0,%d5 |make op a denorm by shifting bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) lsrl %d5,%d6 |by the number in the exp, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) | ;set exp = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) orl %d6,%d1 |shift the ls mant bits into the ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) movel #0,%d0 |same as if decremented exp to 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) | ;while shifting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) movew %d0,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) movel %d1,LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) movel %d2,LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) moveml (%a7)+,%d2/%d3/%d5/%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ms_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) bfffo %d2{#0:#32},%d3 |check if any bits set in ls mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) beqs all_clr |branch if none set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) addw #32,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) cmpw %d3,%d0 |if X>Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bmis greater |then branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) bsr nrm_set |else exp won't go past 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) moveml (%a7)+,%d2/%d3/%d5/%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) all_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) movew #0,LOCAL_EX(%a0) |no mantissa bits set. Set exp = 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) moveml (%a7)+,%d2/%d3/%d5/%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) | NRM_SET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .global nrm_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) nrm_set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) movel %d7,-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) bfffo LOCAL_HI(%a0){#0:#32},%d7 |find first 1 in ms mant to d7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) beqs lower |branch if ms mant is all 0's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) movel %d6,-(%a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) subw %d7,LOCAL_EX(%a0) |sub exponent by count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) movel LOCAL_HI(%a0),%d0 |d0 has ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) movel LOCAL_LO(%a0),%d1 |d1 has ls mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) lsll %d7,%d0 |shift first 1 to j bit position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) movel %d1,%d6 |copy ls mant into d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) lsll %d7,%d6 |shift ls mant by count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) movel %d6,LOCAL_LO(%a0) |store ls mant into memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) moveql #32,%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) subl %d7,%d6 |continue shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) lsrl %d6,%d1 |shift off all bits but those that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) | ;be shifted into ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) orl %d1,%d0 |shift the ls mant bits into the ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) movel %d0,LOCAL_HI(%a0) |store ms mant into memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) moveml (%a7)+,%d7/%d6 |restore registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) | We get here if ms mant was = 0, and we assume ls mant has bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) | set (otherwise this would have been tagged a zero not a denorm).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) lower:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) movew LOCAL_EX(%a0),%d0 |d0 has exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) movel LOCAL_LO(%a0),%d1 |d1 has ls mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) subw #32,%d0 |account for ms mant being all zeros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) bfffo %d1{#0:#32},%d7 |find first 1 in ls mant to d7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) subw %d7,%d0 |subtract shift count from exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) lsll %d7,%d1 |shift first 1 to integer bit in ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) movew %d0,LOCAL_EX(%a0) |store ms mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) movel %d1,LOCAL_HI(%a0) |store exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) clrl LOCAL_LO(%a0) |clear ls mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) movel (%a7)+,%d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) | denorm --- denormalize an intermediate result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) | Used by underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) | Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) | a0 points to the operand to be denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) | (in the internal extended format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) | d0: rounding precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) | Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) | a0 points to the denormalized result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) | (in the internal extended format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) | d0 is guard,round,sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) | d0 comes into this routine with the rounding precision. It
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) | is then loaded with the denormalized exponent threshold for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) | rounding precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .global denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) btstb #6,LOCAL_EX(%a0) |check for exponents between $7fff-$4000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) beqs no_sgn_ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) bsetb #7,LOCAL_EX(%a0) |sign extend if it is so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) no_sgn_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cmpib #0,%d0 |if 0 then extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) bnes not_ext |else branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) clrl %d1 |load d1 with ext threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) clrl %d0 |clear the sticky flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) bsr dnrm_lp |denormalize the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) tstb %d1 |check for inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) beq no_inex |if clr, no inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) bras dnrm_inex |if set, set inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) cmpil #1,%d0 |if 1 then single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) beqs load_sgl |else must be 2, double prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) load_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) movew #dbl_thresh,%d1 |put copy of threshold in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) movel %d1,%d0 |copy d1 into d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) subw LOCAL_EX(%a0),%d0 |diff = threshold - exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) cmpw #67,%d0 |if diff > 67 (mant + grs bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) bpls chk_stky |then branch (all bits would be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) | ; shifted off in denorm routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) clrl %d0 |else clear the sticky flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) bsr dnrm_lp |denormalize the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) tstb %d1 |check flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) beqs no_inex |if clr, no inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) bras dnrm_inex |if set, set inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) load_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) movew #sgl_thresh,%d1 |put copy of threshold in d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) movel %d1,%d0 |copy d1 into d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) subw LOCAL_EX(%a0),%d0 |diff = threshold - exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) cmpw #67,%d0 |if diff > 67 (mant + grs bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) bpls chk_stky |then branch (all bits would be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) | ; shifted off in denorm routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) clrl %d0 |else clear the sticky flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) bsr dnrm_lp |denormalize the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) tstb %d1 |check flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) beqs no_inex |if clr, no inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) bras dnrm_inex |if set, set inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) chk_stky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) tstl LOCAL_HI(%a0) |check for any bits set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) bnes set_stky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) tstl LOCAL_LO(%a0) |check for any bits set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) bnes set_stky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) bras clr_mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) set_stky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) movel #0x20000000,%d0 |set sticky bit in return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) clr_mant:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) movew %d1,LOCAL_EX(%a0) |load exp with threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) movel #0,LOCAL_HI(%a0) |set d1 = 0 (ms mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) movel #0,LOCAL_LO(%a0) |set d2 = 0 (ms mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dnrm_inex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) orl #inx2a_mask,USER_FPSR(%a6) |set inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) no_inex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) | dnrm_lp --- normalize exponent/mantissa to specified threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) | Input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) | a0 points to the operand to be denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) | d0{31:29} initial guard,round,sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) | d1{15:0} denormalization threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) | Output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) | a0 points to the denormalized operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) | d0{31:29} final guard,round,sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) | d1.b inexact flag: all ones means inexact result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) | The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) | so that bfext can be used to extract the new low part of the mantissa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) | Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) | is no LOCAL_GRS scratch word following it on the fsave frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) .global dnrm_lp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dnrm_lp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) movel %d2,-(%sp) |save d2 for temp use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) btstb #E3,E_BYTE(%a6) |test for type E3 exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) beqs not_E3 |not type E3 exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) bfextu WBTEMP_GRS(%a6){#6:#3},%d2 |extract guard,round, sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) movel #29,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) lsll %d0,%d2 |shift g,r,s to their positions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) movel %d2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) not_E3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) movel (%sp)+,%d2 |restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) movel LOCAL_LO(%a0),FP_SCR2+LOCAL_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) movel %d0,FP_SCR2+LOCAL_GRS(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) movel %d1,%d0 |copy the denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) subw LOCAL_EX(%a0),%d1 |d1 = threshold - uns exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) bles no_lp |d1 <= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) cmpw #32,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) blts case_1 |0 = d1 < 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cmpw #64,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) blts case_2 |32 <= d1 < 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) bra case_3 |d1 >= 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) | No normalization necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) no_lp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) clrb %d1 |set no inex2 reported
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) movel FP_SCR2+LOCAL_GRS(%a6),%d0 |restore original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) | case (0<d1<32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) movel %d2,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) movew %d0,LOCAL_EX(%a0) |exponent = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) movel #32,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) subw %d1,%d0 |d0 = 32 - d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) bfextu LOCAL_EX(%a0){%d0:#32},%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) bfextu %d2{%d1:%d0},%d2 |d2 = new LOCAL_HI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) bfextu LOCAL_HI(%a0){%d0:#32},%d1 |d1 = new LOCAL_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) bfextu FP_SCR2+LOCAL_LO(%a6){%d0:#32},%d0 |d0 = new G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) movel %d2,LOCAL_HI(%a0) |store new LOCAL_HI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) movel %d1,LOCAL_LO(%a0) |store new LOCAL_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) clrb %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) bftst %d0{#2:#30}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) beqs c1nstky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) bsetl #rnd_stky_bit,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) st %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) c1nstky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) movel FP_SCR2+LOCAL_GRS(%a6),%d2 |restore original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) andil #0xe0000000,%d2 |clear all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) tstl %d2 |test if original G,R,S are clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) beqs grs_clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) orl #0x20000000,%d0 |set sticky bit in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) grs_clear:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) andil #0xe0000000,%d0 |clear all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) movel (%sp)+,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) | case (32<=d1<64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) movel %d2,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) movew %d0,LOCAL_EX(%a0) |unsigned exponent = threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) subw #32,%d1 |d1 now between 0 and 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) movel #32,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) subw %d1,%d0 |d0 = 32 - d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) bfextu LOCAL_EX(%a0){%d0:#32},%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) bfextu %d2{%d1:%d0},%d2 |d2 = new LOCAL_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) bfextu LOCAL_HI(%a0){%d0:#32},%d1 |d1 = new G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) bftst %d1{#2:#30}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) bnes c2_sstky |bra if sticky bit to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) bftst FP_SCR2+LOCAL_LO(%a6){%d0:#32}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) bnes c2_sstky |bra if sticky bit to be set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) movel %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) clrb %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) bras end_c2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) c2_sstky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) movel %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) bsetl #rnd_stky_bit,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) st %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) end_c2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) clrl LOCAL_HI(%a0) |store LOCAL_HI = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) movel %d2,LOCAL_LO(%a0) |store LOCAL_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) movel FP_SCR2+LOCAL_GRS(%a6),%d2 |restore original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) andil #0xe0000000,%d2 |clear all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) tstl %d2 |test if original G,R,S are clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) beqs clear_grs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) orl #0x20000000,%d0 |set sticky bit in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) clear_grs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) andil #0xe0000000,%d0 |get rid of all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) movel (%sp)+,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) | d1 >= 64 Force the exponent to be the denorm threshold with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) | correct sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) case_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) movew %d0,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) tstw LOCAL_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) bges c3con
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) c3neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) orl #0x80000000,LOCAL_EX(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) c3con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) cmpw #64,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) beqs sixty_four
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) cmpw #65,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) beqs sixty_five
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) | Shift value is out of range. Set d1 for inex2 flag and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) | return a zero with the given threshold.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) movel #0x20000000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) st %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) sixty_four:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) movel LOCAL_HI(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) bfextu %d0{#2:#30},%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) andil #0xc0000000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) bras c3com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) sixty_five:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) movel LOCAL_HI(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) bfextu %d0{#1:#31},%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) andil #0x80000000,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) lsrl #1,%d0 |shift high bit into R bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) c3com:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tstl %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) bnes c3ssticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) tstl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) bnes c3ssticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) tstb FP_SCR2+LOCAL_GRS(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) bnes c3ssticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) clrb %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) bras c3end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) c3ssticky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) bsetl #rnd_stky_bit,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) st %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) c3end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) clrl LOCAL_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) clrl LOCAL_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) |end