^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) M68000 Hi-Performance Microprocessor Division
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) M68060 Software Package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) Production Release P1.00 -- October 10, 1994
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) THE SOFTWARE is provided on an "AS IS" basis and without warranty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) To the maximum extent permitted by applicable law,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) and any warranty against infringement with regard to the SOFTWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) (INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) To the maximum extent permitted by applicable law,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) so long as this entire notice is retained without alteration in any modified and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) redistributed versions, and that such modified versions are clearly identified as such.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) No licenses are granted by implication, estoppel or otherwise under any patents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) or trademarks of Motorola, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) # freal.s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) # This file is appended to the top of the 060FPSP package
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) # and contains the entry points into the package. The user, in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) # effect, branches to one of the branch table entries located
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) # after _060FPSP_TABLE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) # Also, subroutine stubs exist in this file (_fpsp_done for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) # example) that are referenced by the FPSP package itself in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) # to call a given routine. The stub routine actually performs the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) # callout. The FPSP code does a "bsr" to the stub routine. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) # extra layer of hierarchy adds a slight performance penalty but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) # it makes the FPSP code easier to read and more mainatinable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) set _off_bsun, 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) set _off_snan, 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) set _off_operr, 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) set _off_ovfl, 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) set _off_unfl, 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) set _off_dz, 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) set _off_inex, 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) set _off_fline, 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) set _off_fpu_dis, 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) set _off_trap, 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) set _off_trace, 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) set _off_access, 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) set _off_done, 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) set _off_imr, 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) set _off_dmr, 0x44
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) set _off_dmw, 0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) set _off_irw, 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) set _off_irl, 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) set _off_drb, 0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) set _off_drw, 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) set _off_drl, 0x5c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) set _off_dwb, 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) set _off_dww, 0x64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) set _off_dwl, 0x68
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) _060FPSP_TABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ###############################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) # Here's the table of ENTRY POINTS for those linking the package.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) bra.l _fpsp_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bra.l _fpsp_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bra.l _fpsp_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bra.l _fpsp_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bra.l _fpsp_dz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) bra.l _fpsp_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) bra.l _fpsp_fline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) bra.l _fpsp_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) bra.l _fpsp_effadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) short 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) space 56
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) ###############################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) global _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) _fpsp_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) global _real_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) _real_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) global _real_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) _real_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) global _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) _real_inex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) global _real_bsun
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) _real_bsun:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) global _real_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) _real_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) global _real_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) _real_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) global _real_dz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) _real_dz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) global _real_fline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) _real_fline:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) global _real_fpu_disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) _real_fpu_disabled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) global _real_trap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) _real_trap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) global _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) _real_trace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) global _real_access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) _real_access:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #######################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) global _imem_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) _imem_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) global _dmem_read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) _dmem_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) global _dmem_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) _dmem_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) global _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) _imem_read_word:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) global _imem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) _imem_read_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) global _dmem_read_byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) _dmem_read_byte:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) global _dmem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) _dmem_read_word:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) global _dmem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) _dmem_read_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) global _dmem_write_byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) _dmem_write_byte:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) global _dmem_write_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) _dmem_write_word:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) global _dmem_write_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) _dmem_write_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) mov.l 0x4(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) rtd &0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) # This file contains a set of define statements for constants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) # in order to promote readability within the corecode itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) set LOCAL_SIZE, 192 # stack frame size(bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) set LV, -LOCAL_SIZE # stack offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) set EXC_SR, 0x4 # stack status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) set EXC_PC, 0x6 # stack pc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) set EXC_VOFF, 0xa # stacked vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) set EXC_EA, 0xc # stacked <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) set EXC_FP, 0x0 # frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) set EXC_AREGS, -68 # offset of all address regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) set EXC_DREGS, -100 # offset of all data regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) set EXC_FPREGS, -36 # offset of all fp regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) set EXC_A5, EXC_AREGS+(5*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) set EXC_A4, EXC_AREGS+(4*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) set EXC_A3, EXC_AREGS+(3*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) set EXC_A2, EXC_AREGS+(2*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) set EXC_A1, EXC_AREGS+(1*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) set EXC_A0, EXC_AREGS+(0*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) set EXC_D7, EXC_DREGS+(7*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) set EXC_D6, EXC_DREGS+(6*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) set EXC_D5, EXC_DREGS+(5*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) set EXC_D4, EXC_DREGS+(4*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) set EXC_D3, EXC_DREGS+(3*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) set EXC_D2, EXC_DREGS+(2*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) set EXC_D1, EXC_DREGS+(1*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) set EXC_D0, EXC_DREGS+(0*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) set FP_SCR1, LV+80 # fp scratch 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) set FP_SCR1_EX, FP_SCR1+0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) set FP_SCR1_SGN, FP_SCR1+2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) set FP_SCR1_HI, FP_SCR1+4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) set FP_SCR1_LO, FP_SCR1+8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) set FP_SCR0, LV+68 # fp scratch 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) set FP_SCR0_EX, FP_SCR0+0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) set FP_SCR0_SGN, FP_SCR0+2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) set FP_SCR0_HI, FP_SCR0+4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) set FP_SCR0_LO, FP_SCR0+8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) set FP_DST, LV+56 # fp destination operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) set FP_DST_EX, FP_DST+0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) set FP_DST_SGN, FP_DST+2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) set FP_DST_HI, FP_DST+4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) set FP_DST_LO, FP_DST+8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) set FP_SRC, LV+44 # fp source operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) set FP_SRC_EX, FP_SRC+0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) set FP_SRC_SGN, FP_SRC+2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) set FP_SRC_HI, FP_SRC+4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) set FP_SRC_LO, FP_SRC+8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) set USER_FPIAR, LV+40 # FP instr address register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) set USER_FPSR, LV+36 # FP status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) set FPSR_CC, USER_FPSR+0 # FPSR condition codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) set USER_FPCR, LV+32 # FP control register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) set L_SCR3, LV+28 # integer scratch 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) set L_SCR2, LV+24 # integer scratch 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) set L_SCR1, LV+20 # integer scratch 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) set EXC_TEMP2, LV+24 # temporary space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) set EXC_TEMP, LV+16 # temporary space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) set DTAG, LV+15 # destination operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) set STAG, LV+14 # source operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) set SPCOND_FLG, LV+10 # flag: special case (see below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) set EXC_CC, LV+8 # saved condition codes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) set EXC_EXTWPTR, LV+4 # saved current PC (active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) set EXC_EXTWORD, LV+2 # saved extension word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) set EXC_CMDREG, LV+2 # saved extension word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) set EXC_OPWORD, LV+0 # saved operation word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) ################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) # Helpful macros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) set FTEMP, 0 # offsets within an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) set FTEMP_EX, 0 # extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) set FTEMP_SGN, 2 # value saved in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) set FTEMP_HI, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) set FTEMP_LO, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) set FTEMP_GRS, 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) set LOCAL, 0 # offsets within an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) set LOCAL_EX, 0 # extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) set LOCAL_SGN, 2 # value saved in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) set LOCAL_HI, 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) set LOCAL_LO, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) set LOCAL_GRS, 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) set DST, 0 # offsets within an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) set DST_EX, 0 # extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) set DST_HI, 4 # value saved in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) set DST_LO, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) set SRC, 0 # offsets within an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) set SRC_EX, 0 # extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) set SRC_HI, 4 # value saved in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) set SRC_LO, 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) set SGL_LO, 0x3f81 # min sgl prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) set SGL_HI, 0x407e # max sgl prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) set DBL_LO, 0x3c01 # min dbl prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) set DBL_HI, 0x43fe # max dbl prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) set EXT_LO, 0x0 # min ext prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) set EXT_HI, 0x7ffe # max ext prec exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) set EXT_BIAS, 0x3fff # extended precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) set SGL_BIAS, 0x007f # single precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) set DBL_BIAS, 0x03ff # double precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) set NORM, 0x00 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) set ZERO, 0x01 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) set INF, 0x02 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) set QNAN, 0x03 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) set DENORM, 0x04 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) set SNAN, 0x05 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) set UNNORM, 0x06 # operand type for STAG/DTAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ##################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) # FPSR/FPCR bits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) ##################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) set neg_bit, 0x3 # negative result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) set z_bit, 0x2 # zero result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) set inf_bit, 0x1 # infinite result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) set nan_bit, 0x0 # NAN result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) set q_sn_bit, 0x7 # sign bit of quotient byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) set bsun_bit, 7 # branch on unordered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) set snan_bit, 6 # signalling NAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) set operr_bit, 5 # operand error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) set ovfl_bit, 4 # overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) set unfl_bit, 3 # underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) set dz_bit, 2 # divide by zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) set inex2_bit, 1 # inexact result 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) set inex1_bit, 0 # inexact result 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) set aiop_bit, 7 # accrued inexact operation bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) set aovfl_bit, 6 # accrued overflow bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) set aunfl_bit, 5 # accrued underflow bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) set adz_bit, 4 # accrued dz bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) set ainex_bit, 3 # accrued inexact bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) #############################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) # FPSR individual bit masks #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) #############################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) set neg_mask, 0x08000000 # negative bit mask (lw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) set inf_mask, 0x02000000 # infinity bit mask (lw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) set z_mask, 0x04000000 # zero bit mask (lw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) set nan_mask, 0x01000000 # nan bit mask (lw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) set neg_bmask, 0x08 # negative bit mask (byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) set inf_bmask, 0x02 # infinity bit mask (byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) set z_bmask, 0x04 # zero bit mask (byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) set nan_bmask, 0x01 # nan bit mask (byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) set bsun_mask, 0x00008000 # bsun exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) set snan_mask, 0x00004000 # snan exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) set operr_mask, 0x00002000 # operr exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) set ovfl_mask, 0x00001000 # overflow exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) set unfl_mask, 0x00000800 # underflow exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) set dz_mask, 0x00000400 # dz exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) set inex2_mask, 0x00000200 # inex2 exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) set inex1_mask, 0x00000100 # inex1 exception mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) set aiop_mask, 0x00000080 # accrued illegal operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) set aovfl_mask, 0x00000040 # accrued overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) set aunfl_mask, 0x00000020 # accrued underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) set adz_mask, 0x00000010 # accrued divide by zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) set ainex_mask, 0x00000008 # accrued inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ######################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) # FPSR combinations used in the FPSP #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ######################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) set dzinf_mask, inf_mask+dz_mask+adz_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) set opnan_mask, nan_mask+operr_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) set nzi_mask, 0x01ffffff #clears N, Z, and I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) set inx1a_mask, inex1_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) set inx2a_mask, inex2_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) set snaniop_mask, nan_mask+snan_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) set snaniop2_mask, snan_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) set naniop_mask, nan_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) set neginf_mask, neg_mask+inf_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) set infaiop_mask, inf_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) set negz_mask, neg_mask+z_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) set opaop_mask, operr_mask+aiop_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) #########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) # misc. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) set rnd_stky_bit, 29 # stky bit pos in longword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) set sign_bit, 0x7 # sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) set signan_bit, 0x6 # signalling nan bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) set sgl_thresh, 0x3f81 # minimum sgl exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) set dbl_thresh, 0x3c01 # minimum dbl exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) set x_mode, 0x0 # extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) set s_mode, 0x4 # single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) set d_mode, 0x8 # double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) set rn_mode, 0x0 # round-to-nearest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) set rz_mode, 0x1 # round-to-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) set rm_mode, 0x2 # round-tp-minus-infinity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) set rp_mode, 0x3 # round-to-plus-infinity
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) set mantissalen, 64 # length of mantissa in bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) set BYTE, 1 # len(byte) == 1 byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) set WORD, 2 # len(word) == 2 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) set LONG, 4 # len(longword) == 2 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) set BSUN_VEC, 0xc0 # bsun vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) set INEX_VEC, 0xc4 # inexact vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) set DZ_VEC, 0xc8 # dz vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) set UNFL_VEC, 0xcc # unfl vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) set OPERR_VEC, 0xd0 # operr vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) set OVFL_VEC, 0xd4 # ovfl vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) set SNAN_VEC, 0xd8 # snan vector offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) # SPecial CONDition FLaGs #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) set fbsun_flg, 0x02 # flag bit: bsun exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) set mda7_flg, 0x08 # flag bit: -(a7) <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) set fmovm_flg, 0x40 # flag bit: fmovm instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) set immed_flg, 0x80 # flag bit: &<data> <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) set ftrapcc_bit, 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) set fbsun_bit, 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) set mia7_bit, 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) set mda7_bit, 0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) set immed_bit, 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) ##################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) # TRANSCENDENTAL "LAST-OP" FLAGS #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) ##################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) set FMUL_OP, 0x0 # fmul instr performed last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) set FDIV_OP, 0x1 # fdiv performed last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) set FADD_OP, 0x2 # fadd performed last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) set FMOV_OP, 0x3 # fmov performed last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) #############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) # CONSTANTS #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) #############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) TWOBYPI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) long 0x3FE45F30,0x6DC9C883
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) # _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) # FP Overflow exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) # set_tag_x() - determine optype of src/dst operands #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) # store_fpreg() - store opclass 0 or 2 result to FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) # unnorm_fix() - change UNNORM operands to NORM or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) # load_fpn2() - load dst operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) # fout() - emulate an opclass 3 instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) # _real_ovfl() - "callout" for Overflow exception enabled code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) # _real_inex() - "callout" for Inexact exception enabled code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) # _real_trace() - "callout" for Trace exception code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) # - The system stack contains the FP Ovfl exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) # - The fsave frame contains the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) # Overflow Exception enabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) # - The fsave frame contains the adjusted src op for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) # Overflow Exception disabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) # - The "exception present" flag in the fsave frame is cleared #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) # On the 060, if an FP overflow is present as the result of any #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) # instruction, the 060 will take an overflow exception whether the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) # exception is enabled or disabled in the FPCR. For the disabled case, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) # This handler emulates the instruction to determine what the correct #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) # default result should be for the operation. This default result is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) # then stored in either the FP regfile, data regfile, or memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) # Finally, the handler exits through the "callout" _fpsp_done() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) # denoting that no exceptional conditions exist within the machine. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) # If the exception is enabled, then this handler must create the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) # exceptional operand and plave it in the fsave state frame, and store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) # the default result (only if the instruction is opclass 3). For #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) # exceptions enabled, this handler must exit through the "callout" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) # _real_ovfl() so that the operating system enabled overflow handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) # can handle this case. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) # Two other conditions exist. First, if overflow was disabled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) # but the inexact exception was enabled, this handler must exit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) # through the "callout" _real_inex() regardless of whether the result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) # was inexact. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) # Also, in the case of an opclass three instruction where #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) # overflow was disabled and the trace exception was enabled, this #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) # handler must exit through the "callout" _real_trace(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) global _fpsp_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) _fpsp_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) #$# sub.l &24,%sp # make room for src/dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) bne.w fovfl_out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) # since, I believe, only NORMs and DENORMs can come through here,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) # maybe we can avoid the subroutine call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) mov.b %d0,STAG(%a6) # maybe NORM,DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) # bit five of the fp extension word separates the monadic and dyadic operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) # that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) # will never take this exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) beq.b fovfl_extract # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) bsr.l load_fpn2 # load dst into FP_DST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) bne.b fovfl_op2_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) fovfl_op2_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) mov.b %d0,DTAG(%a6) # save dst optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) fovfl_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) mov.b 1+EXC_CMDREG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) andi.w &0x007f,%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) # maybe we can make these entry points ONLY the OVFL entry points of each routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) # the operation has been emulated. the result is in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) # the EXOP, if an exception occurred, is in fp1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) # we must save the default result regardless of whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) # traps are enabled or disabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) bfextu EXC_CMDREG(%a6){&6:&3},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) bsr.l store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) # the exceptional possibilities we have left ourselves with are ONLY overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) # and inexact. and, the inexact is such that overflow occurred and was disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) # but inexact was enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) btst &ovfl_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) bne.b fovfl_ovfl_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) btst &inex2_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) bne.b fovfl_inex_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) #$# add.l &24,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) # in fp1. now, simply jump to _real_ovfl()!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) fovfl_ovfl_on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) mov.w &0xe005,2+FP_SRC(%a6) # save exc status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) bra.l _real_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) # overflow occurred but is disabled. meanwhile, inexact is enabled. Therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) # we must jump to real_inex().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) fovfl_inex_on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) mov.w &0xe001,2+FP_SRC(%a6) # save exc status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) bra.l _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) fovfl_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) # the src operand is definitely a NORM(!), so tag it as such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) mov.b &NORM,STAG(%a6) # set src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) lea FP_SRC(%a6),%a0 # pass ptr to src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) bsr.l fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) btst &ovfl_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) bne.w fovfl_ovfl_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) btst &inex2_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) bne.w fovfl_inex_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #$# add.l &24,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) beq.l _fpsp_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) # _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) # FP Underflow exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) # set_tag_x() - determine optype of src/dst operands #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) # store_fpreg() - store opclass 0 or 2 result to FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) # unnorm_fix() - change UNNORM operands to NORM or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) # load_fpn2() - load dst operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) # fout() - emulate an opclass 3 instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) # _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) # _real_ovfl() - "callout" for Overflow exception enabled code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) # _real_inex() - "callout" for Inexact exception enabled code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) # _real_trace() - "callout" for Trace exception code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) # - The system stack contains the FP Unfl exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) # - The fsave frame contains the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) # Underflow Exception enabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) # - The fsave frame contains the adjusted src op for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) # Underflow Exception disabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) # - The "exception present" flag in the fsave frame is cleared #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) # On the 060, if an FP underflow is present as the result of any #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) # instruction, the 060 will take an underflow exception whether the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) # exception is enabled or disabled in the FPCR. For the disabled case, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) # This handler emulates the instruction to determine what the correct #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) # default result should be for the operation. This default result is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) # then stored in either the FP regfile, data regfile, or memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) # Finally, the handler exits through the "callout" _fpsp_done() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) # denoting that no exceptional conditions exist within the machine. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) # If the exception is enabled, then this handler must create the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) # exceptional operand and plave it in the fsave state frame, and store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) # the default result (only if the instruction is opclass 3). For #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) # exceptions enabled, this handler must exit through the "callout" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) # _real_unfl() so that the operating system enabled overflow handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) # can handle this case. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) # Two other conditions exist. First, if underflow was disabled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) # but the inexact exception was enabled and the result was inexact, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) # this handler must exit through the "callout" _real_inex(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) # was inexact. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) # Also, in the case of an opclass three instruction where #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) # underflow was disabled and the trace exception was enabled, this #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) # handler must exit through the "callout" _real_trace(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) global _fpsp_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) _fpsp_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) #$# sub.l &24,%sp # make room for src/dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) bne.w funfl_out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) mov.b %d0,STAG(%a6) # maybe NORM,DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) # bit five of the fp ext word separates the monadic and dyadic operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) # that can pass through fpsp_unfl(). remember that fcmp, and ftst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) # will never take this exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) beq.b funfl_extract # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) # now, what's left that's not dyadic is fsincos. we can distinguish it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) # from all dyadics by the '0110xxx pattern
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) bne.b funfl_extract # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) bsr.l load_fpn2 # load dst into FP_DST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) bne.b funfl_op2_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) funfl_op2_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mov.b %d0,DTAG(%a6) # save dst optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) funfl_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) #$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) #$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) #$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) mov.b 1+EXC_CMDREG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) andi.w &0x007f,%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) andi.l &0x00ff01ff,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) # maybe we can make these entry points ONLY the OVFL entry points of each routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) bfextu EXC_CMDREG(%a6){&6:&3},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) bsr.l store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) # The `060 FPU multiplier hardware is such that if the result of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) # multiply operation is the smallest possible normalized number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) # (0x00000000_80000000_00000000), then the machine will take an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) # underflow exception. Since this is incorrect, we need to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) # if our emulation, after re-doing the operation, decided that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) # no underflow was called for. We do these checks only in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) # funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) # special case will simply exit gracefully with the correct result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) # the exceptional possibilities we have left ourselves with are ONLY overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) # and inexact. and, the inexact is such that overflow occurred and was disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) # but inexact was enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) btst &unfl_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) bne.b funfl_unfl_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) funfl_chkinex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) btst &inex2_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) bne.b funfl_inex_on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) funfl_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) #$# add.l &24,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) # overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) # in fp1 (don't forget to save fp0). what to do now?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) # well, we simply have to get to go to _real_unfl()!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) funfl_unfl_on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) # The `060 FPU multiplier hardware is such that if the result of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) # multiply operation is the smallest possible normalized number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) # (0x00000000_80000000_00000000), then the machine will take an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) # underflow exception. Since this is incorrect, we check here to see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) # if our emulation, after re-doing the operation, decided that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) # no underflow was called for.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) btst &unfl_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) beq.w funfl_chkinex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) funfl_unfl_on2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) mov.w &0xe003,2+FP_SRC(%a6) # save exc status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) bra.l _real_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) # underflow occurred but is disabled. meanwhile, inexact is enabled. Therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) # we must jump to real_inex().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) funfl_inex_on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) # The `060 FPU multiplier hardware is such that if the result of a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) # multiply operation is the smallest possible normalized number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) # (0x00000000_80000000_00000000), then the machine will take an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) # underflow exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) # But, whether bogus or not, if inexact is enabled AND it occurred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) # then we have to branch to real_inex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) btst &inex2_bit,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) beq.w funfl_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) funfl_inex_on2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) mov.w &0xe001,2+FP_SRC(%a6) # save exc status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) bra.l _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) #######################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) funfl_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) #$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) #$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) # the src operand is definitely a NORM(!), so tag it as such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) mov.b &NORM,STAG(%a6) # set src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) lea FP_SRC(%a6),%a0 # pass ptr to src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) bsr.l fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) btst &unfl_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) bne.w funfl_unfl_on2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) btst &inex2_bit,FPCR_ENABLE(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) bne.w funfl_inex_on2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) #$# add.l &24,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) beq.l _fpsp_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) # _fpsp_unsupp(): 060FPSP entry point for FP "Unimplemented #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) # Data Type" exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) # FP Unimplemented Data Type exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) # _imem_read_{word,long}() - read instruction word/longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) # set_tag_x() - determine optype of src/dst operands #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) # store_fpreg() - store opclass 0 or 2 result to FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) # unnorm_fix() - change UNNORM operands to NORM or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) # load_fpn2() - load dst operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) # load_fpn1() - load src operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) # fout() - emulate an opclass 3 instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) # _real_inex() - "callout" to operating system inexact handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) # _fpsp_done() - "callout" for exit; work all done #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) # _real_trace() - "callout" for Trace enabled exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) # funimp_skew() - adjust fsave src ops to "incorrect" value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) # _real_snan() - "callout" for SNAN exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) # _real_operr() - "callout" for OPERR exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) # _real_ovfl() - "callout" for OVFL exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) # _real_unfl() - "callout" for UNFL exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) # get_packed() - fetch packed operand from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) # - The system stack contains the "Unimp Data Type" stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) # - The fsave frame contains the ssrc op (for UNNORM/DENORM) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) # If Inexact exception (opclass 3): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) # - The system stack is changed to an Inexact exception stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) # If SNAN exception (opclass 3): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) # - The system stack is changed to an SNAN exception stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) # If OPERR exception (opclass 3): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) # - The system stack is changed to an OPERR exception stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) # If OVFL exception (opclass 3): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) # - The system stack is changed to an OVFL exception stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) # If UNFL exception (opclass 3): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) # - The system stack is changed to an UNFL exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) # If Trace exception enabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) # - The system stack is changed to a Trace exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) # Else: (normal case) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) # - Correct result has been stored as appropriate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) # Two main instruction types can enter here: (1) DENORM or UNNORM #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) # unimplemented data types. These can be either opclass 0,2 or 3 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) # instructions, and (2) PACKED unimplemented data format instructions #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) # also of opclasses 0,2, or 3. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) # For UNNORM/DENORM opclass 0 and 2, the handler fetches the src #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) # operand from the fsave state frame and the dst operand (if dyadic) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) # from the FP register file. The instruction is then emulated by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) # choosing an emulation routine from a table of routines indexed by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) # instruction type. Once the instruction has been emulated and result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) # saved, then we check to see if any enabled exceptions resulted from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) # instruction emulation. If none, then we exit through the "callout" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) # _fpsp_done(). If there is an enabled FP exception, then we insert #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) # this exception into the FPU in the fsave state frame and then exit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) # through _fpsp_done(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) # PACKED opclass 0 and 2 is similar in how the instruction is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) # emulated and exceptions handled. The differences occur in how the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) # handler loads the packed op (by calling get_packed() routine) and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) # by the fact that a Trace exception could be pending for PACKED ops. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) # If a Trace exception is pending, then the current exception stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) # frame is changed to a Trace exception stack frame and an exit is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) # made through _real_trace(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) # For UNNORM/DENORM opclass 3, the actual move out to memory is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) # performed by calling the routine fout(). If no exception should occur #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) # as the result of emulation, then an exit either occurs through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) # _fpsp_done() or through _real_trace() if a Trace exception is pending #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) # (a Trace stack frame must be created here, too). If an FP exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) # should occur, then we must create an exception stack frame of that #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) # type and jump to either _real_snan(), _real_operr(), _real_inex(), #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) # _real_unfl(), or _real_ovfl() as appropriate. PACKED opclass 3 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) # emulation is performed in a similar manner. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) # (1) DENORM and UNNORM (unimplemented) data types:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) # post-instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) # * EA *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) # pre-instruction * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) # * 0x0 * 0x0dc * * 0x3 * 0x0dc *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) # * Next * * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) # * PC * * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) # * SR * * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) # (2) PACKED format (unsupported) opclasses two and three:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) # * EA *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) # * *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) # * 0x2 * 0x0dc *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) # * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) # * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) # * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) global _fpsp_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) _fpsp_unsupp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) fsave FP_SRC(%a6) # save fp state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) btst &0x5,EXC_SR(%a6) # user or supervisor mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) bne.b fu_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) fu_u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) mov.l %usp,%a0 # fetch user stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) mov.l %a0,EXC_A7(%a6) # save on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) bra.b fu_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) # if the exception is an opclass zero or two unimplemented data type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) # exception, then the a7' calculated here is wrong since it doesn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) # stack an ea. however, we don't need an a7' for this case anyways.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) fu_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) lea 0x4+EXC_EA(%a6),%a0 # load old a7'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) mov.l %a0,EXC_A7(%a6) # save on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) fu_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) # the FPIAR should be set correctly for ALL exceptions passing through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) # this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) ############################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) clr.b SPCOND_FLG(%a6) # clear special condition flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) # Separate opclass three (fpn-to-mem) ops since they have a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) # stack frame and protocol.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) btst &0x5,EXC_CMDREG(%a6) # is it an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) bne.w fu_out # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) # Separate packed opclass two instructions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) bfextu EXC_CMDREG(%a6){&0:&6},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) cmpi.b %d0,&0x13
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) beq.w fu_in_pack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) # I'm not sure at this point what FPSR bits are valid for this instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) # so, since the emulation routines re-create them anyways, zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) andi.l &0x00ff00ff,USER_FPSR(%a6) # zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) # Opclass two w/ memory-to-fpn operation will have an incorrect extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) # precision format if the src format was single or double and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) # source data type was an INF, NAN, DENORM, or UNNORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) lea FP_SRC(%a6),%a0 # pass ptr to input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) bsr.l fix_skewed_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) # we don't know whether the src operand or the dst operand (or both) is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) # UNNORM or DENORM. call the function that tags the operand type. if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) # input is an UNNORM, then convert it to a NORM, DENORM, or ZERO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) bne.b fu_op2 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) fu_op2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) mov.b %d0,STAG(%a6) # save src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) # bit five of the fp extension word separates the monadic and dyadic operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) # at this point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) beq.b fu_extract # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) beq.b fu_extract # yes, so it's monadic, too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) bsr.l load_fpn2 # load dst into FP_DST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) bne.b fu_op2_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) fu_op2_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) mov.b %d0,DTAG(%a6) # save dst optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) fu_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) # Exceptions in order of precedence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) # BSUN : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) # SNAN : all dyadic ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) # OPERR : fsqrt(-NORM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) # OVFL : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) # UNFL : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) # DZ : fdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) # INEX2 : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) # INEX1 : none (packed doesn't go through here)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) # we determine the highest priority exception(if any) set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) # emulation routine that has also been enabled by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) bne.b fu_in_ena # some are enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) fu_in_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) # fcmp and ftst do not store any result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) andi.b &0x38,%d0 # extract bits 3-5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) cmpi.b %d0,&0x38 # is instr fcmp or ftst?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) beq.b fu_in_exit # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) bsr.l store_fpreg # store the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) fu_in_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) fu_in_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) bfffo %d0{&24:&8},%d0 # find highest priority exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) bne.b fu_in_exc # there is at least one set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) # No exceptions occurred that were also enabled. Now:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) # if (OVFL && ovfl_disabled && inexact_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) # branch to _real_inex() (even if the result was exact!);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) # } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) # save the result in the proper fp reg (unless the op is fcmp or ftst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) # return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) # }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) beq.b fu_in_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) fu_in_ovflchk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) beq.b fu_in_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) bra.w fu_in_exc_ovfl # go insert overflow frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) # An exception occurred and that exception was enabled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) # shift enabled exception field into lo byte of d0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) # if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) # ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) # /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) # * this is the case where we must call _real_inex() now or else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) # * there will be no other way to pass it the exceptional operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) # */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) # call _real_inex();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) # } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) # restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) # }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) fu_in_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) subi.l &24,%d0 # fix offset to be 0-8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) cmpi.b %d0,&0x6 # is exception INEX? (6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) bne.b fu_in_exc_exit # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) # the enabled exception was inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) bne.w fu_in_exc_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) bne.w fu_in_exc_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) # here, we insert the correct fsave status value into the fsave frame for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) # corresponding exception. the operand in the fsave frame should be the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) # src operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) fu_in_exc_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) mov.l %d0,-(%sp) # save d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) bsr.l funimp_skew # skew sgl or dbl inputs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) mov.l (%sp)+,%d0 # restore d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) mov.w (tbl_except.b,%pc,%d0.w*2),2+FP_SRC(%a6) # create exc status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) frestore FP_SRC(%a6) # restore src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) tbl_except:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) short 0xe000,0xe006,0xe004,0xe005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) short 0xe003,0xe002,0xe001,0xe001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) fu_in_exc_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) mov.w &0x4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) bra.b fu_in_exc_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) fu_in_exc_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) mov.w &0x03,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) bra.b fu_in_exc_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) # If the input operand to this operation was opclass two and a single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) # or double precision denorm, inf, or nan, the operand needs to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) # "corrected" in order to have the proper equivalent extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) # number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) global fix_skewed_ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) fix_skewed_ops:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) bfextu EXC_CMDREG(%a6){&0:&6},%d0 # extract opclass,src fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) cmpi.b %d0,&0x11 # is class = 2 & fmt = sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) beq.b fso_sgl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) cmpi.b %d0,&0x15 # is class = 2 & fmt = dbl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) beq.b fso_dbl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) rts # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) fso_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) cmpi.w %d0,&0x3f80 # is |exp| == $3f80?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) beq.b fso_sgl_dnrm_zero # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) cmpi.w %d0,&0x407f # no; is |exp| == $407f?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) beq.b fso_infnan # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) rts # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) fso_sgl_dnrm_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) beq.b fso_zero # it's a skewed zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) fso_sgl_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) # here, we count on norm not to alter a0...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) bsr.l norm # normalize mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) neg.w %d0 # -shft amt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) addi.w &0x3f81,%d0 # adjust new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) or.w %d0,LOCAL_EX(%a0) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) fso_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) andi.w &0x8000,LOCAL_EX(%a0) # clear bogus exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) fso_infnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) andi.b &0x7f,LOCAL_HI(%a0) # clear j-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) ori.w &0x7fff,LOCAL_EX(%a0) # make exponent = $7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) fso_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) mov.w LOCAL_EX(%a0),%d0 # fetch src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) cmpi.w %d0,&0x3c00 # is |exp| == $3c00?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) beq.b fso_dbl_dnrm_zero # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) cmpi.w %d0,&0x43ff # no; is |exp| == $43ff?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) beq.b fso_infnan # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) rts # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) fso_dbl_dnrm_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) andi.l &0x7fffffff,LOCAL_HI(%a0) # clear j-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) bne.b fso_dbl_dnrm # it's a skewed denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) tst.l LOCAL_LO(%a0) # is it a zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) beq.b fso_zero # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) fso_dbl_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) # here, we count on norm not to alter a0...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) bsr.l norm # normalize mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) neg.w %d0 # -shft amt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) addi.w &0x3c01,%d0 # adjust new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) andi.w &0x8000,LOCAL_EX(%a0) # clear old exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) or.w %d0,LOCAL_EX(%a0) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) # fmove out took an unimplemented data type exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) # the src operand is in FP_SRC. Call _fout() to write out the result and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) # to determine which exceptions, if any, to take.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) fu_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) # Separate packed move outs from the UNNORM and DENORM move outs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) bfextu EXC_CMDREG(%a6){&3:&3},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) cmpi.b %d0,&0x3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) beq.w fu_out_pack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) cmpi.b %d0,&0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) beq.w fu_out_pack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) # I'm not sure at this point what FPSR bits are valid for this instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) # so, since the emulation routines re-create them anyways, zero exception field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) # fmove out doesn't affect ccodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) # the src can ONLY be a DENORM or an UNNORM! so, don't make any big subroutine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) # call here. just figure out what it is...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) mov.w FP_SRC_EX(%a6),%d0 # get exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) beq.b fu_out_denorm # it's a DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) bsr.l unnorm_fix # yes; fix it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) mov.b %d0,STAG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) bra.b fu_out_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) fu_out_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) mov.b &DENORM,STAG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) fu_out_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) lea FP_SRC(%a6),%a0 # pass ptr to src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) mov.l (%a6),EXC_A6(%a6) # in case a6 changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) bsr.l fout # call fmove out routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) # Exceptions in order of precedence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) # BSUN : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) # SNAN : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) # OPERR : fmove.{b,w,l} out of large UNNORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) # OVFL : fmove.{s,d}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) # UNFL : fmove.{s,d,x}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) # DZ : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) # INEX2 : all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) # INEX1 : none (packed doesn't travel through here)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) # determine the highest priority exception(if any) set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) # emulation routine that has also been enabled by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) bne.w fu_out_ena # some are enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) fu_out_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) mov.l EXC_A6(%a6),(%a6) # in case a6 changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) # on extended precision opclass three instructions using pre-decrement or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) # post-increment addressing mode, the address register is not updated. is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) # address register was the stack pointer used from user mode, then let's update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) # it here. if it was used from supervisor mode, then we have to handle this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) # as a special case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) bne.b fu_out_done_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) mov.l EXC_A7(%a6),%a0 # restore a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) fu_out_done_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) bne.b fu_out_trace # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) # is the ea mode pre-decrement of the stack pointer from supervisor mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) # ("fmov.x fpm,-(a7)") if so,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) fu_out_done_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) bne.b fu_out_done_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) # the extended precision result is still in fp0. but, we need to save it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) # somewhere on the stack until we can copy it to its final resting place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) # here, we're counting on the top of the stack to be the old place-holders
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) # for fp0/fp1 which have already been restored. that way, we can write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) # over those destinations with the shifted stack frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) # now, copy the result to the proper place on the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) btst &0x7,(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) bne.b fu_out_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) fu_out_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) bfffo %d0{&24:&8},%d0 # find highest priority exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) bne.b fu_out_exc # there is at least one set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) # no exceptions were set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) # if a disabled overflow occurred and inexact was enabled but the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) # was exact, then a branch to _real_inex() is made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) beq.w fu_out_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) fu_out_ovflchk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) beq.w fu_out_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) bra.w fu_inex # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) # The fp move out that took the "Unimplemented Data Type" exception was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) # being traced. Since the stack frames are similar, get the "current" PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) # from FPIAR and put it in the trace stack frame then jump to _real_trace().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) # UNSUPP FRAME TRACE FRAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) # * EA * * Current *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) # * * * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) # * 0x3 * 0x0dc * * 0x2 * 0x024 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) # * Next * * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) # * PC * * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) # * SR * * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) fu_out_trace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) mov.w &0x2024,0x6(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) fmov.l %fpiar,0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) # an exception occurred and that exception was enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) fu_out_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) subi.l &24,%d0 # fix offset to be 0-8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) # we don't mess with the existing fsave frame. just re-insert it and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) # jump to the "_real_{}()" handler...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) mov.w (tbl_fu_out.b,%pc,%d0.w*2),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) jmp (tbl_fu_out.b,%pc,%d0.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) swbeg &0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) tbl_fu_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) short tbl_fu_out - tbl_fu_out # BSUN can't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) short tbl_fu_out - tbl_fu_out # SNAN can't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) short fu_operr - tbl_fu_out # OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) short fu_ovfl - tbl_fu_out # OVFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) short fu_unfl - tbl_fu_out # UNFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) short tbl_fu_out - tbl_fu_out # DZ can't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) short fu_inex - tbl_fu_out # INEX2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) short tbl_fu_out - tbl_fu_out # INEX1 won't make it here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) # for snan,operr,ovfl,unfl, src op is still in FP_SRC so just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) # frestore it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) fu_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) mov.w &0xe006,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) bra.l _real_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) fu_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) mov.w &0xe004,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) bra.l _real_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) fu_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) mov.w &0x30d4,EXC_VOFF(%a6) # vector offset = 0xd4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) mov.w &0xe005,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) frestore FP_SRC(%a6) # restore EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) bra.l _real_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) # underflow can happen for extended precision. extended precision opclass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) # three instruction exceptions don't update the stack pointer. so, if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) # exception occurred from user mode, then simply update a7 and exit normally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) # if the exception occurred from supervisor mode, check if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) fu_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) mov.l EXC_A6(%a6),(%a6) # restore a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) bne.w fu_unfl_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) mov.l EXC_A7(%a6),%a0 # restore a7 whether we need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) mov.l %a0,%usp # to or not...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) fu_unfl_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) mov.w &0xe003,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) frestore FP_SRC(%a6) # restore EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) bra.l _real_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) fu_unfl_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) cmpi.b SPCOND_FLG(%a6),&mda7_flg # was the <ea> mode -(sp)?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) bne.b fu_unfl_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) # the extended precision result is still in fp0. but, we need to save it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) # somewhere on the stack until we can copy it to its final resting place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) # (where the exc frame is currently). make sure it's not at the top of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) # frame or it will get overwritten when the exc stack frame is shifted "down".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) fmovm.x &0x80,FP_SRC(%a6) # put answer on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) fmovm.x &0x40,FP_DST(%a6) # put EXOP on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) mov.w &0x30cc,EXC_VOFF(%a6) # vector offset = 0xcc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) mov.w &0xe003,2+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) frestore FP_DST(%a6) # restore EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) # now, copy the result to the proper place on the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) mov.l LOCAL_SIZE+FP_SRC_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) mov.l LOCAL_SIZE+FP_SRC_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) mov.l LOCAL_SIZE+FP_SRC_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) bra.l _real_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) # fmove in and out enter here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) fu_inex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) fmovm.x &0x40,FP_SRC(%a6) # save EXOP to the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) mov.w &0xe001,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) frestore FP_SRC(%a6) # restore EXOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) bra.l _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) fu_in_pack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) # I'm not sure at this point what FPSR bits are valid for this instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) # so, since the emulation routines re-create them anyways, zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) andi.l &0x0ff00ff,USER_FPSR(%a6) # zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) bsr.l get_packed # fetch packed src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) lea FP_SRC(%a6),%a0 # pass ptr to src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) bsr.l set_tag_x # set src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) mov.b %d0,STAG(%a6) # save src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) # bit five of the fp extension word separates the monadic and dyadic operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) # at this point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) beq.b fu_extract_p # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) cmpi.b 1+EXC_CMDREG(%a6),&0x3a # is operation an ftst?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) beq.b fu_extract_p # yes, so it's monadic, too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) bsr.l load_fpn2 # load dst into FP_DST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) bne.b fu_op2_done_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) fu_op2_done_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) mov.b %d0,DTAG(%a6) # save dst optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) fu_extract_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) bfextu 1+EXC_CMDREG(%a6){&1:&7},%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) mov.l (tbl_unsupp.l,%pc,%d1.l*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) # Exceptions in order of precedence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) # BSUN : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) # SNAN : all dyadic ops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) # OPERR : fsqrt(-NORM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) # OVFL : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) # UNFL : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) # DZ : fdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) # INEX2 : all except ftst,fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) # INEX1 : all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) # we determine the highest priority exception(if any) set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) # emulation routine that has also been enabled by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) bne.w fu_in_ena_p # some are enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) fu_in_cont_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) # fcmp and ftst do not store any result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) mov.b 1+EXC_CMDREG(%a6),%d0 # fetch extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) andi.b &0x38,%d0 # extract bits 3-5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) cmpi.b %d0,&0x38 # is instr fcmp or ftst?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) beq.b fu_in_exit_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) bsr.l store_fpreg # store the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) fu_in_exit_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) btst &0x5,EXC_SR(%a6) # user or supervisor?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) bne.w fu_in_exit_s_p # supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) mov.l EXC_A7(%a6),%a0 # update user a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) fu_in_exit_cont_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) unlk %a6 # unravel stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) bne.w fu_trace_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) # the exception occurred in supervisor mode. check to see if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) # addressing mode was (a7)+. if so, we'll need to shift the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) # stack frame "up".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) fu_in_exit_s_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) btst &mia7_bit,SPCOND_FLG(%a6) # was ea mode (a7)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) beq.b fu_in_exit_cont_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) unlk %a6 # unravel stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) # shift the stack frame "up". we don't really care about the <ea> field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) mov.l 0x4(%sp),0x10(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) mov.l 0x0(%sp),0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) bne.w fu_trace_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) fu_in_ena_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled & set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) bfffo %d0{&24:&8},%d0 # find highest priority exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) bne.b fu_in_exc_p # at least one was set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) # No exceptions occurred that were also enabled. Now:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) # if (OVFL && ovfl_disabled && inexact_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) # branch to _real_inex() (even if the result was exact!);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) # } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) # save the result in the proper fp reg (unless the op is fcmp or ftst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) # return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) # }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) btst &ovfl_bit,FPSR_EXCEPT(%a6) # was overflow set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) beq.w fu_in_cont_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) fu_in_ovflchk_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) btst &inex2_bit,FPCR_ENABLE(%a6) # was inexact enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) beq.w fu_in_cont_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) bra.w fu_in_exc_ovfl_p # do _real_inex() now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) # An exception occurred and that exception was enabled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) # shift enabled exception field into lo byte of d0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) # if (((INEX2 || INEX1) && inex_enabled && OVFL && ovfl_disabled) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) # ((INEX2 || INEX1) && inex_enabled && UNFL && unfl_disabled)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) # /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) # * this is the case where we must call _real_inex() now or else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) # * there will be no other way to pass it the exceptional operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) # */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) # call _real_inex();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) # } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) # restore exc state (SNAN||OPERR||OVFL||UNFL||DZ||INEX) into the FPU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) # }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) fu_in_exc_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) subi.l &24,%d0 # fix offset to be 0-8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) cmpi.b %d0,&0x6 # is exception INEX? (6 or 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) blt.b fu_in_exc_exit_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) # the enabled exception was inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) btst &unfl_bit,FPSR_EXCEPT(%a6) # did disabled underflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) bne.w fu_in_exc_unfl_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) btst &ovfl_bit,FPSR_EXCEPT(%a6) # did disabled overflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) bne.w fu_in_exc_ovfl_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) # here, we insert the correct fsave status value into the fsave frame for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) # corresponding exception. the operand in the fsave frame should be the original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) # src operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) # as a reminder for future predicted pain and agony, we are passing in fsave the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) # "non-skewed" operand for cases of sgl and dbl src INFs,NANs, and DENORMs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) # this is INCORRECT for enabled SNAN which would give to the user the skewed SNAN!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) fu_in_exc_exit_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) btst &0x5,EXC_SR(%a6) # user or supervisor?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) bne.w fu_in_exc_exit_s_p # supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) mov.l EXC_A7(%a6),%a0 # update user a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) fu_in_exc_exit_cont_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) frestore FP_SRC(%a6) # restore src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) btst &0x7,(%sp) # is trace enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) bne.w fu_trace_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) tbl_except_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) short 0xe000,0xe006,0xe004,0xe005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) short 0xe003,0xe002,0xe001,0xe001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) fu_in_exc_ovfl_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) mov.w &0x3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) bra.w fu_in_exc_exit_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) fu_in_exc_unfl_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) mov.w &0x4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) bra.w fu_in_exc_exit_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) fu_in_exc_exit_s_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) btst &mia7_bit,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) beq.b fu_in_exc_exit_cont_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) mov.w (tbl_except_p.b,%pc,%d0.w*2),2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) frestore FP_SRC(%a6) # restore src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) unlk %a6 # unravel stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) # shift stack frame "up". who cares about <ea> field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) mov.l 0x4(%sp),0x10(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) mov.l 0x0(%sp),0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) bne.b fu_trace_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) # The opclass two PACKED instruction that took an "Unimplemented Data Type"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) # exception was being traced. Make the "current" PC the FPIAR and put it in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) # trace stack frame then jump to _real_trace().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) # UNSUPP FRAME TRACE FRAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) # * EA * * Current *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) # * * * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) # * 0x2 * 0x0dc * * 0x2 * 0x024 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) # * Next * * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) # * PC * * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) # * SR * * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) fu_trace_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) mov.w &0x2024,0x6(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) fmov.l %fpiar,0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) #########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) #########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) fu_out_pack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) # I'm not sure at this point what FPSR bits are valid for this instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) # so, since the emulation routines re-create them anyways, zero exception field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) # fmove out doesn't affect ccodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) and.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) bfextu EXC_CMDREG(%a6){&6:&3},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) bsr.l load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) # unlike other opclass 3, unimplemented data type exceptions, packed must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) # able to detect all operand types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) bne.b fu_op2_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) fu_op2_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) mov.b %d0,STAG(%a6) # save src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) mov.b FPCR_MODE(%a6),%d0 # fetch rnd mode/prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) lea FP_SRC(%a6),%a0 # pass ptr to src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) mov.l (%a6),EXC_A6(%a6) # in case a6 changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) bsr.l fout # call fmove out routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) # Exceptions in order of precedence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) # BSUN : no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) # SNAN : yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) # OPERR : if ((k_factor > +17) || (dec. exp exceeds 3 digits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) # OVFL : no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) # UNFL : no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) # DZ : no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) # INEX2 : yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) # INEX1 : no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) # determine the highest priority exception(if any) set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) # emulation routine that has also been enabled by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) bne.w fu_out_ena_p # some are enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) fu_out_exit_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) mov.l EXC_A6(%a6),(%a6) # restore a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) btst &0x5,EXC_SR(%a6) # user or supervisor?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) bne.b fu_out_exit_s_p # supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) mov.l EXC_A7(%a6),%a0 # update user a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) fu_out_exit_cont_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) unlk %a6 # unravel stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) bne.w fu_trace_p # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) # the exception occurred in supervisor mode. check to see if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) # addressing mode was -(a7). if so, we'll need to shift the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) # stack frame "down".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) fu_out_exit_s_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) btst &mda7_bit,SPCOND_FLG(%a6) # was ea mode -(a7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) beq.b fu_out_exit_cont_p # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) # now, copy the result to the proper place on the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+EXC_SR+0x0(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+EXC_SR+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+EXC_SR+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) btst &0x7,(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) bne.w fu_trace_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) fu_out_ena_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) bfffo %d0{&24:&8},%d0 # find highest priority exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) beq.w fu_out_exit_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) mov.l EXC_A6(%a6),(%a6) # restore a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) # an exception occurred and that exception was enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) # the only exception possible on packed move out are INEX, OPERR, and SNAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) fu_out_exc_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) cmpi.b %d0,&0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) bgt.w fu_inex_p2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) beq.w fu_operr_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) fu_snan_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) bne.b fu_snan_s_p
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) mov.l EXC_A7(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) bra.w fu_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) fu_snan_s_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) bne.w fu_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) # the strategy is to move the exception frame "down" 12 bytes. then, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) # can store the default result where the exception frame was.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) mov.w &0x30d8,EXC_VOFF(%a6) # vector offset = 0xd0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) mov.w &0xe006,2+FP_SRC(%a6) # set fsave status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) frestore FP_SRC(%a6) # restore src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) # now, we copy the default result to its proper location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) bra.l _real_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) fu_operr_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) bne.w fu_operr_p_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) mov.l EXC_A7(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) bra.w fu_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) fu_operr_p_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) bne.w fu_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) # the strategy is to move the exception frame "down" 12 bytes. then, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) # can store the default result where the exception frame was.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) mov.w &0x30d0,EXC_VOFF(%a6) # vector offset = 0xd0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) mov.w &0xe004,2+FP_SRC(%a6) # set fsave status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) frestore FP_SRC(%a6) # restore src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) # now, we copy the default result to its proper location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) bra.l _real_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) fu_inex_p2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) bne.w fu_inex_s_p2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) mov.l EXC_A7(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) mov.l %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) bra.w fu_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) fu_inex_s_p2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) bne.w fu_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) # the instruction was "fmove.p fpn,-(a7)" from supervisor mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) # the strategy is to move the exception frame "down" 12 bytes. then, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) # can store the default result where the exception frame was.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0/fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) mov.w &0x30c4,EXC_VOFF(%a6) # vector offset = 0xc4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) mov.w &0xe001,2+FP_SRC(%a6) # set fsave status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) frestore FP_SRC(%a6) # restore src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) mov.l LOCAL_SIZE+2+EXC_PC(%sp),LOCAL_SIZE+2+EXC_PC-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) # now, we copy the default result to its proper location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) mov.l LOCAL_SIZE+FP_DST_EX(%sp),LOCAL_SIZE+0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) mov.l LOCAL_SIZE+FP_DST_HI(%sp),LOCAL_SIZE+0x8(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) mov.l LOCAL_SIZE+FP_DST_LO(%sp),LOCAL_SIZE+0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) bra.l _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) # if we're stuffing a source operand back into an fsave frame then we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) # have to make sure that for single or double source operands that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) # format stuffed is as weird as the hardware usually makes it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) global funimp_skew
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) funimp_skew:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) bfextu EXC_EXTWORD(%a6){&3:&3},%d0 # extract src specifier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) cmpi.b %d0,&0x1 # was src sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) beq.b funimp_skew_sgl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) cmpi.b %d0,&0x5 # was src dbl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) beq.b funimp_skew_dbl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) funimp_skew_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) beq.b funimp_skew_sgl_not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) cmpi.w %d0,&0x3f80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) bgt.b funimp_skew_sgl_not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) neg.w %d0 # make exponent negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) addi.w &0x3f81,%d0 # find amt to shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) mov.l FP_SRC_HI(%a6),%d1 # fetch DENORM hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) lsr.l %d0,%d1 # shift it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) bset &31,%d1 # set j-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) mov.l %d1,FP_SRC_HI(%a6) # insert new hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) andi.w &0x8000,FP_SRC_EX(%a6) # clear old exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) ori.w &0x3f80,FP_SRC_EX(%a6) # insert new "skewed" exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) funimp_skew_sgl_not:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) funimp_skew_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) mov.w FP_SRC_EX(%a6),%d0 # fetch DENORM exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) beq.b funimp_skew_dbl_not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) cmpi.w %d0,&0x3c00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) bgt.b funimp_skew_dbl_not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) tst.b FP_SRC_EX(%a6) # make "internal format"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) smi.b 0x2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) mov.w %d0,FP_SRC_EX(%a6) # insert exponent with cleared sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) clr.l %d0 # clear g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) lea FP_SRC(%a6),%a0 # pass ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) mov.w &0x3c01,%d1 # pass denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) bsr.l dnrm_lp # denorm it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) mov.w &0x3c00,%d0 # new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) tst.b 0x2+FP_SRC(%a6) # is sign set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) beq.b fss_dbl_denorm_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) bset &15,%d0 # set sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) fss_dbl_denorm_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) bset &0x7,FP_SRC_HI(%a6) # set j-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) mov.w %d0,FP_SRC_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347) funimp_skew_dbl_not:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) global _mem_write2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) _mem_write2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) btst &0x5,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) beq.l _dmem_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) mov.l 0x0(%a0),FP_DST_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) mov.l 0x4(%a0),FP_DST_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) mov.l 0x8(%a0),FP_DST_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) # _fpsp_effadd(): 060FPSP entry point for FP "Unimplemented #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) # effective address" exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) # FP Unimplemented Effective Address exception in an operating #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) # system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) # set_tag_x() - determine optype of src/dst operands #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) # store_fpreg() - store opclass 0 or 2 result to FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) # unnorm_fix() - change UNNORM operands to NORM or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376) # load_fpn2() - load dst operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) # decbin() - convert packed data to FP binary data #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) # _real_fpu_disabled() - "callout" for "FPU disabled" exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) # _real_access() - "callout" for access error exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) # _mem_read() - read extended immediate operand from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) # _fpsp_done() - "callout" for exit; work all done #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) # _real_trace() - "callout" for Trace enabled exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) # fmovm_dynamic() - emulate dynamic fmovm instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) # fmovm_ctrl() - emulate fmovm control instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) # - The system stack contains the "Unimplemented <ea>" stk frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) # If access error: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) # - The system stack is changed to an access error stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) # If FPU disabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) # - The system stack is changed to an FPU disabled stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) # If Trace exception enabled: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) # - The system stack is changed to a Trace exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) # Else: (normal case) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) # - None (correct result has been stored as appropriate) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) # This exception handles 3 types of operations: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) # (1) FP Instructions using extended precision or packed immediate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) # addressing mode. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) # (2) The "fmovm.x" instruction w/ dynamic register specification. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) # (3) The "fmovm.l" instruction w/ 2 or 3 control registers. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) # For immediate data operations, the data is read in w/ a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) # _mem_read() "callout", converted to FP binary (if packed), and used #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) # as the source operand to the instruction specified by the instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) # word. If no FP exception should be reported ads a result of the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) # emulation, then the result is stored to the destination register and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) # the handler exits through _fpsp_done(). If an enabled exc has been #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) # signalled as a result of emulation, then an fsave state frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) # corresponding to the FP exception type must be entered into the 060 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) # FPU before exiting. In either the enabled or disabled cases, we #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) # must also check if a Trace exception is pending, in which case, we #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) # must create a Trace exception stack frame from the current exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418) # stack frame. If no Trace is pending, we simply exit through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) # _fpsp_done(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) # For "fmovm.x", call the routine fmovm_dynamic() which will #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421) # decode and emulate the instruction. No FP exceptions can be pending #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) # as a result of this operation emulation. A Trace exception can be #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) # pending, though, which means the current stack frame must be changed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) # to a Trace stack frame and an exit made through _real_trace(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) # For the case of "fmovm.x Dn,-(a7)", where the offending instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426) # was executed from supervisor mode, this handler must store the FP #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) # register file values to the system stack by itself since #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) # fmovm_dynamic() can't handle this. A normal exit is made through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) # fpsp_done(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) # For "fmovm.l", fmovm_ctrl() is used to emulate the instruction. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) # Again, a Trace exception may be pending and an exit made through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) # _real_trace(). Else, a normal exit is made through _fpsp_done(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) # Before any of the above is attempted, it must be checked to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) # see if the FPU is disabled. Since the "Unimp <ea>" exception is taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) # before the "FPU disabled" exception, but the "FPU disabled" exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) # has higher priority, we check the disabled bit in the PCR. If set, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) # then we must create an 8 word "FPU disabled" exception stack frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) # from the current 4 word exception stack frame. This includes #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) # reproducing the effective address of the instruction to put on the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) # new stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) # In the process of all emulation work, if a _mem_read() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) # "callout" returns a failing result indicating an access error, then #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) # we must create an access error stack frame from the current stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) # frame. This information includes a faulting address and a fault- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) # status-longword. These are created within this handler. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) global _fpsp_effadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) _fpsp_effadd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) # This exception type takes priority over the "Line F Emulator"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) # exception. Therefore, the FPU could be disabled when entering here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) # So, we must check to see if it's disabled and handle that case separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) mov.l %d0,-(%sp) # save d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) movc %pcr,%d0 # load proc cr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) btst &0x1,%d0 # is FPU disabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) bne.w iea_disabled # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) mov.l (%sp)+,%d0 # restore d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) link %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) # PC of instruction that took the exception is the PC in the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) tst.w %d0 # is operation fmovem?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) bmi.w iea_fmovm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) # here, we will have:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) # fabs fdabs fsabs facos fmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) # fadd fdadd fsadd fasin frem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) # fcmp fatan fscale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) # fdiv fddiv fsdiv fatanh fsin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) # fint fcos fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) # fintrz fcosh fsinh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) # fmove fdmove fsmove fetox ftan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) # fmul fdmul fsmul fetoxm1 ftanh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) # fneg fdneg fsneg fgetexp ftentox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) # fsgldiv fgetman ftwotox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) # fsglmul flog10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) # fsqrt flog2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) # fsub fdsub fssub flogn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) # ftst flognp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) # which can all use f<op>.{x,p}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) # so, now it's immediate data extended precision AND PACKED FORMAT!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) iea_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) andi.l &0x00ff00ff,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) btst &0xa,%d0 # is src fmt x or p?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) bne.b iea_op_pack # packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) lea FP_SRC(%a6),%a1 # pass: ptr to super addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) mov.l &0xc,%d0 # pass: 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) bsr.l _imem_read # read extended immediate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) bne.w iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) bra.b iea_op_setsrc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) iea_op_pack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) mov.l EXC_EXTWPTR(%a6),%a0 # pass: ptr to #<data>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) lea FP_SRC(%a6),%a1 # pass: ptr to super dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) mov.l &0xc,%d0 # pass: 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) bsr.l _imem_read # read packed operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) bne.w iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) # The packed operand is an INF or a NAN if the exponent field is all ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) cmpi.w %d0,&0x7fff # INF or NAN?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531) beq.b iea_op_setsrc # operand is an INF or NAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) # The packed operand is a zero if the mantissa is all zero, else it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) # a normal packed op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) mov.b 3+FP_SRC(%a6),%d0 # get byte 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) andi.b &0x0f,%d0 # clear all but last nybble
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) bne.b iea_op_gp_not_spec # not a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) tst.l FP_SRC_HI(%a6) # is lw 2 zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) bne.b iea_op_gp_not_spec # not a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) tst.l FP_SRC_LO(%a6) # is lw 3 zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) beq.b iea_op_setsrc # operand is a ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) iea_op_gp_not_spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) lea FP_SRC(%a6),%a0 # pass: ptr to packed op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) bsr.l decbin # convert to extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) iea_op_setsrc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) addi.l &0xc,EXC_EXTWPTR(%a6) # update extension word pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) # FP_SRC now holds the src operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) mov.b %d0,STAG(%a6) # could be ANYTHING!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) bne.b iea_op_getdst # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) mov.b %d0,STAG(%a6) # set new optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) iea_op_getdst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) clr.b STORE_FLG(%a6) # clear "store result" boolean
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) beq.b iea_op_extract # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) btst &0x4,1+EXC_CMDREG(%a6) # is operation fsincos,ftst,fcmp?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) bne.b iea_op_spec # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) iea_op_loaddst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) bsr.l load_fpn2 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) mov.b %d0,DTAG(%a6) # could be ANYTHING!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) bne.b iea_op_extract # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) bsr.l unnorm_fix # yes; convert to NORM/DENORM/ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) mov.b %d0,DTAG(%a6) # set new optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577) bra.b iea_op_extract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) # the operation is fsincos, ftst, or fcmp. only fcmp is dyadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580) iea_op_spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) btst &0x3,1+EXC_CMDREG(%a6) # is operation fsincos?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) beq.b iea_op_extract # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) # now, we're left with ftst and fcmp. so, first let's tag them so that they don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) # store a result. then, only fcmp will branch back and pick up a dst operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) st STORE_FLG(%a6) # don't store a final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) btst &0x1,1+EXC_CMDREG(%a6) # is operation fcmp?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587) beq.b iea_op_loaddst # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) iea_op_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) mov.b FPCR_MODE(%a6),%d0 # pass: rnd mode,prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593) mov.b 1+EXC_CMDREG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) andi.w &0x007f,%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) # Exceptions in order of precedence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) # BSUN : none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) # SNAN : all operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) # OPERR : all reg-reg or mem-reg operations that can normally operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) # OVFL : same as OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) # UNFL : same as OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) # DZ : same as OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) # INEX2 : same as OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) # INEX1 : all packed immediate operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) # we determine the highest priority exception(if any) set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) # emulation routine that has also been enabled by the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) mov.b FPCR_ENABLE(%a6),%d0 # fetch exceptions enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) bne.b iea_op_ena # some are enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) # now, we save the result, unless, of course, the operation was ftst or fcmp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) # these don't save results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) iea_op_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) tst.b STORE_FLG(%a6) # does this op store a result?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) bne.b iea_op_exit1 # exit with no frestore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) iea_op_store:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # fetch dst regno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) bsr.l store_fpreg # store the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) iea_op_exit1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640) unlk %a6 # unravel the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643) bne.w iea_op_trace # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) iea_op_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) and.b FPSR_EXCEPT(%a6),%d0 # keep only ones enable and set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) bfffo %d0{&24:&8},%d0 # find highest priority exception
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) bne.b iea_op_exc # at least one was set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) # no exception occurred. now, did a disabled, exact overflow occur with inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) # enabled? if so, then we have to stuff an overflow frame into the FPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) beq.b iea_op_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) iea_op_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) btst &inex2_bit,FPCR_ENABLE(%a6) # is inexact enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) beq.b iea_op_store # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) bra.b iea_op_exc_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) # an enabled exception occurred. we have to insert the exception type back into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) # the machine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) iea_op_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) subi.l &24,%d0 # fix offset to be 0-8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) cmpi.b %d0,&0x6 # is exception INEX?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) bne.b iea_op_exc_force # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) # the enabled exception was inexact. so, if it occurs with an overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) # or underflow that was disabled, then we have to force an overflow or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) # underflow frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) btst &ovfl_bit,FPSR_EXCEPT(%a6) # did overflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) bne.b iea_op_exc_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) btst &unfl_bit,FPSR_EXCEPT(%a6) # did underflow occur?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) bne.b iea_op_exc_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) iea_op_exc_force:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) mov.w (tbl_iea_except.b,%pc,%d0.w*2),2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) bra.b iea_op_exit2 # exit with frestore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) tbl_iea_except:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) short 0xe002, 0xe006, 0xe004, 0xe005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) short 0xe003, 0xe002, 0xe001, 0xe001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) iea_op_exc_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) mov.w &0xe005,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687) bra.b iea_op_exit2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) iea_op_exc_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) mov.w &0xe003,2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) iea_op_exit2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) mov.l EXC_PC(%a6),USER_FPIAR(%a6) # set FPIAR to "Current PC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set "Next PC" in exc frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) frestore FP_SRC(%a6) # restore exceptional state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) unlk %a6 # unravel the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) btst &0x7,(%sp) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) bne.b iea_op_trace # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) # The opclass two instruction that took an "Unimplemented Effective Address"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) # exception was being traced. Make the "current" PC the FPIAR and put it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) # the trace stack frame then jump to _real_trace().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) # UNIMP EA FRAME TRACE FRAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) # * 0x0 * 0x0f0 * * Current *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) # ***************** * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) # * Current * *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) # * PC * * 0x2 * 0x024 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) # * SR * * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) # ***************** * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) # * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) iea_op_trace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) mov.l (%sp),-(%sp) # shift stack frame "down"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) mov.w 0x8(%sp),0x4(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) iea_fmovm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) btst &14,%d0 # ctrl or data reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) beq.w iea_fmovm_ctrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) iea_fmovm_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) btst &0x5,EXC_SR(%a6) # user or supervisor mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) bne.b iea_fmovm_data_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) iea_fmovm_data_u:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) mov.l %usp,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) mov.l %a0,EXC_A7(%a6) # store current a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) bsr.l fmovm_dynamic # do dynamic fmovm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) mov.l EXC_A7(%a6),%a0 # load possibly new a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) mov.l %a0,%usp # update usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) bra.w iea_fmovm_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) iea_fmovm_data_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) clr.b SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) lea 0x2+EXC_VOFF(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) mov.l %a0,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) bsr.l fmovm_dynamic # do dynamic fmovm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) beq.w iea_fmovm_data_predec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) cmpi.b SPCOND_FLG(%a6),&mia7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) bne.w iea_fmovm_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) # right now, d0 = the size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) # the data has been fetched from the supervisor stack, but we have not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) # incremented the stack pointer by the appropriate number of bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) # do it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) iea_fmovm_data_postinc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) btst &0x7,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) bne.b iea_fmovm_data_pi_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) mov.l EXC_EXTWPTR(%a6),(EXC_PC,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) lea (EXC_SR,%a6,%d0),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) mov.l %a0,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) mov.l (%sp)+,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) bra.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) iea_fmovm_data_pi_trace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) mov.l EXC_EXTWPTR(%a6),(EXC_PC-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) mov.l EXC_PC(%a6),(EXC_VOFF+0x2-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) lea (EXC_SR-0x4,%a6,%d0),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) mov.l %a0,EXC_SR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) mov.l (%sp)+,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) # right now, d1 = size and d0 = the strg.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) iea_fmovm_data_predec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) mov.b %d1,EXC_VOFF(%a6) # store strg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) mov.b %d0,0x1+EXC_VOFF(%a6) # store size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) fmovm.x EXC_FP0(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) mov.l (%a6),-(%sp) # make a copy of a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) mov.l %d0,-(%sp) # save d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) mov.l %d1,-(%sp) # save d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) mov.l EXC_EXTWPTR(%a6),-(%sp) # make a copy of Next PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) mov.b 0x1+EXC_VOFF(%a6),%d0 # fetch size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) neg.l %d0 # get negative of size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) btst &0x7,EXC_SR(%a6) # is trace enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) beq.b iea_fmovm_data_p2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) mov.w EXC_SR(%a6),(EXC_SR-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) mov.l EXC_PC(%a6),(EXC_VOFF-0x2,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) mov.l (%sp)+,(EXC_PC-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) mov.w &0x2024,(EXC_VOFF-0x4,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) pea (%a6,%d0) # create final sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) bra.b iea_fmovm_data_p3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) iea_fmovm_data_p2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) mov.w EXC_SR(%a6),(EXC_SR,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) mov.l (%sp)+,(EXC_PC,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) mov.w &0x00f0,(EXC_VOFF,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) pea (0x4,%a6,%d0) # create final sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) iea_fmovm_data_p3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) clr.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) mov.b EXC_VOFF(%a6),%d1 # fetch strg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) tst.b %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) bpl.b fm_1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845) fmovm.x &0x80,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) fm_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) bpl.b fm_2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) fmovm.x &0x40,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) fm_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) bpl.b fm_3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) fmovm.x &0x20,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) fm_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) bpl.b fm_4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) fmovm.x &0x10,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) fm_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) bpl.b fm_5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) fmovm.x &0x08,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) fm_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) bpl.b fm_6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) fmovm.x &0x04,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) fm_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) bpl.b fm_7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) fmovm.x &0x02,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) addi.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) fm_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) lsl.b &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) bpl.b fm_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) fmovm.x &0x01,(0x4+0x8,%a6,%d0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) fm_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) mov.l 0x4(%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) mov.l 0x8(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) mov.l 0xc(%sp),%a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) mov.l (%sp)+,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) btst &0x7,(%sp) # is trace enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) beq.l _fpsp_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) iea_fmovm_ctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) bsr.l fmovm_ctrl # load ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) iea_fmovm_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) btst &0x7,EXC_SR(%a6) # is trace on?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) bne.b iea_fmovm_trace # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) mov.l EXC_EXTWPTR(%a6),EXC_PC(%a6) # set Next PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) unlk %a6 # unravel the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) bra.l _fpsp_done # exit to os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) # The control reg instruction that took an "Unimplemented Effective Address"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) # exception was being traced. The "Current PC" for the trace frame is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) # PC stacked for Unimp EA. The "Next PC" is in EXC_EXTWPTR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) # After fixing the stack frame, jump to _real_trace().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) # UNIMP EA FRAME TRACE FRAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) # * 0x0 * 0x0f0 * * Current *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) # ***************** * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) # * Current * *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) # * PC * * 0x2 * 0x024 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) # ***************** *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) # * SR * * Next *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) # ***************** * PC *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) # * SR *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) # *****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) # this ain't a pretty solution, but it works:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) # -restore a6 (not with unlk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) # -shift stack frame down over where old a6 used to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) # -add LOCAL_SIZE to stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) iea_fmovm_trace:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) mov.l (%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) mov.w EXC_SR+LOCAL_SIZE(%sp),0x0+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) mov.l EXC_PC+LOCAL_SIZE(%sp),0x8+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) mov.l EXC_EXTWPTR+LOCAL_SIZE(%sp),0x2+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) mov.w &0x2024,0x6+LOCAL_SIZE(%sp) # stk fmt = 0x2; voff = 0x024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) add.l &LOCAL_SIZE,%sp # clear stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) bra.l _real_trace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) # The FPU is disabled and so we should really have taken the "Line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) # F Emulator" exception. So, here we create an 8-word stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) # from our 4-word stack frame. This means we must calculate the length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) # the faulting instruction to get the "next PC". This is trivial for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) # immediate operands but requires some extra work for fmovm dynamic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) # which can use most addressing modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) iea_disabled:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) mov.l (%sp)+,%d0 # restore d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952) link %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) # PC of instruction that took the exception is the PC in the frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) mov.l EXC_PC(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961) mov.l %d0,EXC_OPWORD(%a6) # store OPWORD and EXTWORD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) tst.w %d0 # is instr fmovm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964) bmi.b iea_dis_fmovm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) # instruction is using an extended precision immediate operand. Therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) # the total instruction length is 16 bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967) iea_dis_immed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) mov.l &0x10,%d0 # 16 bytes of instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) bra.b iea_dis_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) iea_dis_fmovm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971) btst &0xe,%d0 # is instr fmovm ctrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) bne.b iea_dis_fmovm_data # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) # the instruction is a fmovm.l with 2 or 3 registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) bfextu %d0{&19:&3},%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) mov.l &0xc,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) cmpi.b %d1,&0x7 # move all regs?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) bne.b iea_dis_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) addq.l &0x4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) bra.b iea_dis_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980) # the instruction is an fmovm.x dynamic which can use many addressing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) # modes and thus can have several different total instruction lengths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) # call fmovm_calc_ea which will go through the ea calc process and,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) # as a by-product, will tell us how long the instruction is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) iea_dis_fmovm_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) bsr.l fmovm_calc_ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) mov.l EXC_EXTWPTR(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988) sub.l EXC_PC(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) iea_dis_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) mov.w %d0,EXC_VOFF(%a6) # store stack shift value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) # here, we actually create the 8-word frame from the 4-word frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997) # with the "next PC" as additional info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) # the <ea> field is let as undefined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) subq.l &0x8,%sp # make room for new stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) mov.l %d0,-(%sp) # save d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001) mov.w 0xc(%sp),0x4(%sp) # move SR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) mov.l 0xe(%sp),0x6(%sp) # move Current PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) mov.w 0x12(%sp),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) mov.l 0x6(%sp),0x10(%sp) # move Current PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) add.l %d0,0x6(%sp) # make Next PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007) mov.w &0x402c,0xa(%sp) # insert offset,frame format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) mov.l (%sp)+,%d0 # restore d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) bra.l _real_fpu_disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012) ##########
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) iea_iacc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) movc %pcr,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) btst &0x1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) bne.b iea_iacc_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) iea_iacc_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025) subq.w &0x8,%sp # make stack frame bigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) mov.l 0x8(%sp),(%sp) # store SR,hi(PC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) mov.w 0xc(%sp),0x4(%sp) # store lo(PC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) mov.w &0x4008,0x6(%sp) # store voff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) mov.l 0x2(%sp),0x8(%sp) # store ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) mov.l &0x09428001,0xc(%sp) # store fslw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032) iea_acc_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) btst &0x5,(%sp) # user or supervisor mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) beq.b iea_acc_done2 # user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) bset &0x2,0xd(%sp) # set supervisor TM bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037) iea_acc_done2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) bra.l _real_access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) iea_dacc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) lea -LOCAL_SIZE(%a6),%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043) movc %pcr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) btst &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) bne.b iea_dacc_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047) fmovm.l LOCAL_SIZE+USER_FPCR(%sp),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) iea_dacc_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) mov.l (%a6),%a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) mov.l 0x4+LOCAL_SIZE(%sp),-0x8+0x4+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) mov.w 0x8+LOCAL_SIZE(%sp),-0x8+0x8+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) mov.w &0x4008,-0x8+0xa+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) mov.l %a0,-0x8+0xc+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055) mov.w %d0,-0x8+0x10+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) mov.w &0x0001,-0x8+0x12+LOCAL_SIZE(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) movm.l LOCAL_SIZE+EXC_DREGS(%sp),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) add.w &LOCAL_SIZE-0x4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) bra.b iea_acc_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) # _fpsp_operr(): 060FPSP entry point for FP Operr exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068) # FP Operand Error exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073) # _real_operr() - "callout" to operating system operr handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) # _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) # store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) # facc_out_{b,w,l}() - store to memory took access error (opcl 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) # - The system stack contains the FP Operr exception frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) # - The fsave frame contains the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) # No access error: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) # - The fsave frame contains the adjusted src op for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) # In a system where the FP Operr exception is enabled, the goal #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) # is to get to the handler specified at _real_operr(). But, on the 060, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090) # for opclass zero and two instruction taking this exception, the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) # input operand in the fsave frame may be incorrect for some cases #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) # and needs to be corrected. This handler calls fix_skewed_ops() to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093) # do just this and then exits through _real_operr(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) # For opclass 3 instructions, the 060 doesn't store the default #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) # operr result out to memory or data register file as it should. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) # This code must emulate the move out before finally exiting through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) # _real_inex(). The move out, if to memory, is performed using #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) # _mem_write() "callout" routines that may return a failing result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) # In this special case, the handler must exit through facc_out() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) # which creates an access error stack frame from the current operr #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101) # stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105) global _fpsp_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) _fpsp_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) btst &13,%d0 # is instr an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127) bne.b foperr_out # fmove out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130) # here, we simply see if the operand in the fsave frame needs to be "unskewed".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) # this would be the case for opclass two operations with a source infinity or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) # denorm operand in the sgl or dbl format. NANs also become skewed, but can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) # cause an operr so we don't need to check for them here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) foperr_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) bra.l _real_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) # the hardware does not save the default result to memory on enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) # operand error exceptions. we do this here before passing control to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) # the user operand error handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) # byte, word, and long destination format operations can pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) # through here. we simply need to test the sign of the src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156) # operand and save the appropriate minimum or maximum integer value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) # to the effective address as pointed to by the stacked effective address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159) # although packed opclass three operations can take operand error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) # exceptions, they won't pass through here since they are caught
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161) # first by the unsupported data format exception handler. that handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) # sends them directly to _real_operr() if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) foperr_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) mov.w FP_SRC_EX(%a6),%d1 # fetch exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) cmpi.w %d1,&0x7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) bne.b foperr_out_not_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) # the operand is either an infinity or a QNAN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) tst.l FP_SRC_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172) bne.b foperr_out_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) mov.l FP_SRC_HI(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) andi.l &0x7fffffff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) beq.b foperr_out_not_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) foperr_out_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177) mov.l FP_SRC_HI(%a6),L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) bra.b foperr_out_jmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) foperr_out_not_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181) mov.l &0x7fffffff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) tst.b FP_SRC_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) bpl.b foperr_out_not_qnan2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) addq.l &0x1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) foperr_out_not_qnan2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) mov.l %d1,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) foperr_out_jmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) bfextu %d0{&19:&3},%d0 # extract dst format field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) mov.w (tbl_operr.b,%pc,%d0.w*2),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) jmp (tbl_operr.b,%pc,%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) tbl_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195) short foperr_out_l - tbl_operr # long word integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) short tbl_operr - tbl_operr # sgl prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) short tbl_operr - tbl_operr # ext prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) short foperr_exit - tbl_operr # packed won't enter here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) short foperr_out_w - tbl_operr # word integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) short tbl_operr - tbl_operr # dbl prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) short foperr_out_b - tbl_operr # byte integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) short tbl_operr - tbl_operr # packed won't enter here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) foperr_out_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) mov.b L_SCR1(%a6),%d0 # load positive default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207) ble.b foperr_out_b_save_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) bsr.l _dmem_write_byte # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) bne.l facc_out_b # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) foperr_out_b_save_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) bsr.l store_dreg_b # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) foperr_out_w:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) mov.w L_SCR1(%a6),%d0 # load positive default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) ble.b foperr_out_w_save_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) bsr.l _dmem_write_word # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) bne.l facc_out_w # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) foperr_out_w_save_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3233) bsr.l store_dreg_w # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3234) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3236) foperr_out_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3237) mov.l L_SCR1(%a6),%d0 # load positive default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3238) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3239) ble.b foperr_out_l_save_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3240) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3241) bsr.l _dmem_write_long # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3243) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3244) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3246) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3247) foperr_out_l_save_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3248) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3249) bsr.l store_dreg_l # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3250) bra.w foperr_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3252) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3253) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3254) # _fpsp_snan(): 060FPSP entry point for FP SNAN exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3255) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3256) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3257) # FP Signalling NAN exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3258) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3259) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3260) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3261) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3262) # _real_snan() - "callout" to operating system SNAN handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3263) # _dmem_write_{byte,word,long}() - store data to mem (opclass 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3264) # store_dreg_{b,w,l}() - store data to data regfile (opclass 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3265) # facc_out_{b,w,l,d,x}() - store to mem took acc error (opcl 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3266) # _calc_ea_fout() - fix An if <ea> is -() or ()+; also get <ea> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3267) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3268) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3269) # - The system stack contains the FP SNAN exception frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3270) # - The fsave frame contains the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3271) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3272) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3273) # No access error: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3274) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3275) # - The fsave frame contains the adjusted src op for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3276) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3277) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3278) # In a system where the FP SNAN exception is enabled, the goal #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3279) # is to get to the handler specified at _real_snan(). But, on the 060, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3280) # for opclass zero and two instructions taking this exception, the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3281) # input operand in the fsave frame may be incorrect for some cases #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3282) # and needs to be corrected. This handler calls fix_skewed_ops() to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3283) # do just this and then exits through _real_snan(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3284) # For opclass 3 instructions, the 060 doesn't store the default #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3285) # SNAN result out to memory or data register file as it should. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3286) # This code must emulate the move out before finally exiting through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3287) # _real_snan(). The move out, if to memory, is performed using #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3288) # _mem_write() "callout" routines that may return a failing result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3289) # In this special case, the handler must exit through facc_out() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3290) # which creates an access error stack frame from the current SNAN #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3291) # stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3292) # For the case of an extended precision opclass 3 instruction, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3293) # if the effective addressing mode was -() or ()+, then the address #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3294) # register must get updated by calling _calc_ea_fout(). If the <ea> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3295) # was -(a7) from supervisor mode, then the exception frame currently #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3296) # on the system stack must be carefully moved "down" to make room #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3297) # for the operand being moved. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3298) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3299) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3301) global _fpsp_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3302) _fpsp_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3304) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3306) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3308) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3309) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3310) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3312) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3313) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3315) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3316) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3317) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3318) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3320) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3322) btst &13,%d0 # is instr an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3323) bne.w fsnan_out # fmove out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3326) # here, we simply see if the operand in the fsave frame needs to be "unskewed".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3327) # this would be the case for opclass two operations with a source infinity or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3328) # denorm operand in the sgl or dbl format. NANs also become skewed and must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3329) # fixed here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3330) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3331) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3333) fsnan_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3334) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3335) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3336) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3338) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3340) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3341) bra.l _real_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3343) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3345) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3346) # the hardware does not save the default result to memory on enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3347) # snan exceptions. we do this here before passing control to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3348) # the user snan handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3349) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3350) # byte, word, long, and packed destination format operations can pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3351) # through here. since packed format operations already were handled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3352) # fpsp_unsupp(), then we need to do nothing else for them here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3353) # for byte, word, and long, we simply need to test the sign of the src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3354) # operand and save the appropriate minimum or maximum integer value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3355) # to the effective address as pointed to by the stacked effective address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3356) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3357) fsnan_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3359) bfextu %d0{&19:&3},%d0 # extract dst format field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3360) mov.b 1+EXC_OPWORD(%a6),%d1 # extract <ea> mode,reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3361) mov.w (tbl_snan.b,%pc,%d0.w*2),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3362) jmp (tbl_snan.b,%pc,%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3364) tbl_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3365) short fsnan_out_l - tbl_snan # long word integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3366) short fsnan_out_s - tbl_snan # sgl prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3367) short fsnan_out_x - tbl_snan # ext prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3368) short tbl_snan - tbl_snan # packed needs no help
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3369) short fsnan_out_w - tbl_snan # word integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3370) short fsnan_out_d - tbl_snan # dbl prec shouldn't happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3371) short fsnan_out_b - tbl_snan # byte integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3372) short tbl_snan - tbl_snan # packed needs no help
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3374) fsnan_out_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3375) mov.b FP_SRC_HI(%a6),%d0 # load upper byte of SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3376) bset &6,%d0 # set SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3377) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3378) ble.b fsnan_out_b_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3379) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3380) bsr.l _dmem_write_byte # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3382) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3383) bne.l facc_out_b # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3385) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3386) fsnan_out_b_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3387) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3388) bsr.l store_dreg_b # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3389) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3391) fsnan_out_w:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3392) mov.w FP_SRC_HI(%a6),%d0 # load upper word of SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3393) bset &14,%d0 # set SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3394) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3395) ble.b fsnan_out_w_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3396) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3397) bsr.l _dmem_write_word # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3399) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3400) bne.l facc_out_w # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3402) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3403) fsnan_out_w_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3404) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3405) bsr.l store_dreg_w # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3406) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3408) fsnan_out_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3409) mov.l FP_SRC_HI(%a6),%d0 # load upper longword of SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3410) bset &30,%d0 # set SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3411) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3412) ble.b fsnan_out_l_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3413) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3414) bsr.l _dmem_write_long # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3416) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3417) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3419) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3420) fsnan_out_l_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3421) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3422) bsr.l store_dreg_l # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3423) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3425) fsnan_out_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3426) cmpi.b %d1,&0x7 # is <ea> mode a data reg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3427) ble.b fsnan_out_d_dn # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3428) mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3429) andi.l &0x80000000,%d0 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3430) ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3431) mov.l FP_SRC_HI(%a6),%d1 # load mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3432) lsr.l &0x8,%d1 # shift mantissa for sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3433) or.l %d1,%d0 # create sgl SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3434) mov.l EXC_EA(%a6),%a0 # pass: <ea> of default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3435) bsr.l _dmem_write_long # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3437) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3438) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3440) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3441) fsnan_out_d_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3442) mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3443) andi.l &0x80000000,%d0 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3444) ori.l &0x7fc00000,%d0 # insert new exponent,SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3445) mov.l %d1,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3446) mov.l FP_SRC_HI(%a6),%d1 # load mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3447) lsr.l &0x8,%d1 # shift mantissa for sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3448) or.l %d1,%d0 # create sgl SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3449) mov.l (%sp)+,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3450) andi.w &0x0007,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3451) bsr.l store_dreg_l # store result to regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3452) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3454) fsnan_out_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3455) mov.l FP_SRC_EX(%a6),%d0 # fetch SNAN sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3456) andi.l &0x80000000,%d0 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3457) ori.l &0x7ff80000,%d0 # insert new exponent,SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3458) mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3459) mov.l %d0,FP_SCR0_EX(%a6) # store to temp space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3460) mov.l &11,%d0 # load shift amt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3461) lsr.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3462) or.l %d1,FP_SCR0_EX(%a6) # create dbl hi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3463) mov.l FP_SRC_HI(%a6),%d1 # load hi mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3464) andi.l &0x000007ff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3465) ror.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3466) mov.l %d1,FP_SCR0_HI(%a6) # store to temp space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3467) mov.l FP_SRC_LO(%a6),%d1 # load lo mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3468) lsr.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3469) or.l %d1,FP_SCR0_HI(%a6) # create dbl lo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3470) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3471) mov.l EXC_EA(%a6),%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3472) movq.l &0x8,%d0 # pass: size of 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3473) bsr.l _dmem_write # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3475) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3476) bne.l facc_out_d # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3478) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3480) # for extended precision, if the addressing mode is pre-decrement or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3481) # post-increment, then the address register did not get updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3482) # in addition, for pre-decrement, the stacked <ea> is incorrect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3483) fsnan_out_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3484) clr.b SPCOND_FLG(%a6) # clear special case flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3486) mov.w FP_SRC_EX(%a6),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3487) clr.w 2+FP_SCR0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3488) mov.l FP_SRC_HI(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3489) bset &30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3490) mov.l %d0,FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3491) mov.l FP_SRC_LO(%a6),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3493) btst &0x5,EXC_SR(%a6) # supervisor mode exception?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3494) bne.b fsnan_out_x_s # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3496) mov.l %usp,%a0 # fetch user stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3497) mov.l %a0,EXC_A7(%a6) # save on stack for calc_ea()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3498) mov.l (%a6),EXC_A6(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3500) bsr.l _calc_ea_fout # find the correct ea,update An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3501) mov.l %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3502) mov.l %a0,EXC_EA(%a6) # stack correct <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3504) mov.l EXC_A7(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3505) mov.l %a0,%usp # restore user stack pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3506) mov.l EXC_A6(%a6),(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3508) fsnan_out_x_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3509) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3510) movq.l &0xc,%d0 # pass: size of extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3511) bsr.l _dmem_write # write the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3513) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3514) bne.l facc_out_x # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3516) bra.w fsnan_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3518) fsnan_out_x_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3519) mov.l (%a6),EXC_A6(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3521) bsr.l _calc_ea_fout # find the correct ea,update An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3522) mov.l %a0,%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3523) mov.l %a0,EXC_EA(%a6) # stack correct <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3525) mov.l EXC_A6(%a6),(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3527) cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3528) bne.b fsnan_out_x_save # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3530) # the operation was "fmove.x SNAN,-(a7)" from supervisor mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3531) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3532) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3533) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3535) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3537) mov.l EXC_A6(%a6),%a6 # restore frame pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3539) mov.l LOCAL_SIZE+EXC_SR(%sp),LOCAL_SIZE+EXC_SR-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3540) mov.l LOCAL_SIZE+EXC_PC+0x2(%sp),LOCAL_SIZE+EXC_PC+0x2-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3541) mov.l LOCAL_SIZE+EXC_EA(%sp),LOCAL_SIZE+EXC_EA-0xc(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3543) mov.l LOCAL_SIZE+FP_SCR0_EX(%sp),LOCAL_SIZE+EXC_SR(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3544) mov.l LOCAL_SIZE+FP_SCR0_HI(%sp),LOCAL_SIZE+EXC_PC+0x2(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3545) mov.l LOCAL_SIZE+FP_SCR0_LO(%sp),LOCAL_SIZE+EXC_EA(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3547) add.l &LOCAL_SIZE-0x8,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3549) bra.l _real_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3551) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3552) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3553) # _fpsp_inex(): 060FPSP entry point for FP Inexact exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3554) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3555) # This handler should be the first code executed upon taking the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3556) # FP Inexact exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3557) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3558) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3559) # _imem_read_long() - read instruction longword #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3560) # fix_skewed_ops() - adjust src operand in fsave frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3561) # set_tag_x() - determine optype of src/dst operands #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3562) # store_fpreg() - store opclass 0 or 2 result to FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3563) # unnorm_fix() - change UNNORM operands to NORM or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3564) # load_fpn2() - load dst operand from FP regfile #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3565) # smovcr() - emulate an "fmovcr" instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3566) # fout() - emulate an opclass 3 instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3567) # tbl_unsupp - add of table of emulation routines for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3568) # _real_inex() - "callout" to operating system inexact handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3569) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3570) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3571) # - The system stack contains the FP Inexact exception frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3572) # - The fsave frame contains the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3573) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3574) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3575) # - The system stack is unchanged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3576) # - The fsave frame contains the adjusted src op for opclass 0,2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3577) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3578) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3579) # In a system where the FP Inexact exception is enabled, the goal #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3580) # is to get to the handler specified at _real_inex(). But, on the 060, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3581) # for opclass zero and two instruction taking this exception, the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3582) # hardware doesn't store the correct result to the destination FP #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3583) # register as did the '040 and '881/2. This handler must emulate the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3584) # instruction in order to get this value and then store it to the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3585) # correct register before calling _real_inex(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3586) # For opclass 3 instructions, the 060 doesn't store the default #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3587) # inexact result out to memory or data register file as it should. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3588) # This code must emulate the move out by calling fout() before finally #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3589) # exiting through _real_inex(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3590) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3591) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3593) global _fpsp_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3594) _fpsp_inex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3596) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3598) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3600) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3601) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3602) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3604) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3605) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3607) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3608) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3609) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3610) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3612) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3614) btst &13,%d0 # is instr an fmove out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3615) bne.w finex_out # fmove out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3618) # the hardware, for "fabs" and "fneg" w/ a long source format, puts the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3619) # longword integer directly into the upper longword of the mantissa along
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3620) # w/ an exponent value of 0x401e. we convert this to extended precision here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3621) bfextu %d0{&19:&3},%d0 # fetch instr size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3622) bne.b finex_cont # instr size is not long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3623) cmpi.w FP_SRC_EX(%a6),&0x401e # is exponent 0x401e?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3624) bne.b finex_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3625) fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3626) fmov.l FP_SRC_HI(%a6),%fp0 # load integer src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3627) fmov.x %fp0,FP_SRC(%a6) # store integer as extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3628) mov.w &0xe001,0x2+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3630) finex_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3631) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3632) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3634) # Here, we zero the ccode and exception byte field since we're going to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3635) # emulate the whole instruction. Notice, though, that we don't kill the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3636) # INEX1 bit. This is because a packed op has long since been converted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3637) # to extended before arriving here. Therefore, we need to retain the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3638) # INEX1 bit from when the operand was first converted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3639) andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3641) fmov.l &0x0,%fpcr # zero current control regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3642) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3644) bfextu EXC_EXTWORD(%a6){&0:&6},%d1 # extract upper 6 of cmdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3645) cmpi.b %d1,&0x17 # is op an fmovecr?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3646) beq.w finex_fmovcr # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3648) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3649) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3650) mov.b %d0,STAG(%a6) # maybe NORM,DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3652) # bits four and five of the fp extension word separate the monadic and dyadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3653) # operations that can pass through fpsp_inex(). remember that fcmp and ftst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3654) # will never take this exception, but fsincos will.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3655) btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3656) beq.b finex_extract # monadic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3658) btst &0x4,1+EXC_CMDREG(%a6) # is operation an fsincos?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3659) bne.b finex_extract # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3661) bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3662) bsr.l load_fpn2 # load dst into FP_DST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3664) lea FP_DST(%a6),%a0 # pass: ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3665) bsr.l set_tag_x # tag the operand type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3666) cmpi.b %d0,&UNNORM # is operand an UNNORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3667) bne.b finex_op2_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3668) bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3669) finex_op2_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3670) mov.b %d0,DTAG(%a6) # save dst optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3672) finex_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3673) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3674) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3676) mov.b 1+EXC_CMDREG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3677) andi.w &0x007f,%d1 # extract extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3679) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3680) lea FP_DST(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3682) mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3683) jsr (tbl_unsupp.l,%pc,%d1.l*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3685) # the operation has been emulated. the result is in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3686) finex_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3687) bfextu EXC_CMDREG(%a6){&6:&3},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3688) bsr.l store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3690) finex_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3691) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3692) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3693) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3695) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3697) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3698) bra.l _real_inex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3700) finex_fmovcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3701) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3702) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3703) mov.b 1+EXC_CMDREG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3704) andi.l &0x0000007f,%d1 # pass rom offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3705) bsr.l smovcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3706) bra.b finex_save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3708) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3710) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3711) # the hardware does not save the default result to memory on enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3712) # inexact exceptions. we do this here before passing control to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3713) # the user inexact handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3714) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3715) # byte, word, and long destination format operations can pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3716) # through here. so can double and single precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3717) # although packed opclass three operations can take inexact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3718) # exceptions, they won't pass through here since they are caught
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3719) # first by the unsupported data format exception handler. that handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3720) # sends them directly to _real_inex() if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3721) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3722) finex_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3724) mov.b &NORM,STAG(%a6) # src is a NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3726) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3727) mov.b FPCR_MODE(%a6),%d0 # pass rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3729) andi.l &0xffff00ff,USER_FPSR(%a6) # zero exception field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3731) lea FP_SRC(%a6),%a0 # pass ptr to src operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3733) bsr.l fout # store the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3735) bra.b finex_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3737) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3738) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3739) # _fpsp_dz(): 060FPSP entry point for FP DZ exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3740) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3741) # This handler should be the first code executed upon taking #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3742) # the FP DZ exception in an operating system. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3743) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3744) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3745) # _imem_read_long() - read instruction longword from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3746) # fix_skewed_ops() - adjust fsave operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3747) # _real_dz() - "callout" exit point from FP DZ handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3748) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3749) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3750) # - The system stack contains the FP DZ exception stack. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3751) # - The fsave frame contains the source operand. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3752) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3753) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3754) # - The system stack contains the FP DZ exception stack. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3755) # - The fsave frame contains the adjusted source operand. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3756) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3757) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3758) # In a system where the DZ exception is enabled, the goal is to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3759) # get to the handler specified at _real_dz(). But, on the 060, when the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3760) # exception is taken, the input operand in the fsave state frame may #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3761) # be incorrect for some cases and need to be adjusted. So, this package #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3762) # adjusts the operand using fix_skewed_ops() and then branches to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3763) # _real_dz(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3764) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3765) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3767) global _fpsp_dz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3768) _fpsp_dz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3770) link.w %a6,&-LOCAL_SIZE # init stack frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3772) fsave FP_SRC(%a6) # grab the "busy" frame
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3774) movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3775) fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3776) fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3778) # the FPIAR holds the "current PC" of the faulting instruction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3779) mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3781) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3782) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3783) bsr.l _imem_read_long # fetch the instruction words
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3784) mov.l %d0,EXC_OPWORD(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3786) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3789) # here, we simply see if the operand in the fsave frame needs to be "unskewed".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3790) # this would be the case for opclass two operations with a source zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3791) # in the sgl or dbl format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3792) lea FP_SRC(%a6),%a0 # pass: ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3793) bsr.l fix_skewed_ops # fix src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3795) fdz_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3796) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3797) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3798) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3800) frestore FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3802) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3803) bra.l _real_dz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3805) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3806) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3807) # _fpsp_fline(): 060FPSP entry point for "Line F emulator" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3808) # exception when the "reduced" version of the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3809) # FPSP is implemented that does not emulate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3810) # FP unimplemented instructions. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3811) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3812) # This handler should be the first code executed upon taking a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3813) # "Line F Emulator" exception in an operating system integrating #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3814) # the reduced version of 060FPSP. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3815) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3816) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3817) # _real_fpu_disabled() - Handle "FPU disabled" exceptions #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3818) # _real_fline() - Handle all other cases (treated equally) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3819) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3820) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3821) # - The system stack contains a "Line F Emulator" exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3822) # stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3823) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3824) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3825) # - The system stack is unchanged. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3826) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3827) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3828) # When a "Line F Emulator" exception occurs in a system where #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3829) # "FPU Unimplemented" instructions will not be emulated, the exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3830) # can occur because then FPU is disabled or the instruction is to be #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3831) # classifed as "Line F". This module determines which case exists and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3832) # calls the appropriate "callout". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3833) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3834) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3836) global _fpsp_fline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3837) _fpsp_fline:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3839) # check to see if the FPU is disabled. if so, jump to the OS entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3840) # point for that condition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3841) cmpi.w 0x6(%sp),&0x402c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3842) beq.l _real_fpu_disabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3844) bra.l _real_fline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3846) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3847) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3848) # _dcalc_ea(): calc correct <ea> from <ea> stacked on exception #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3849) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3850) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3851) # inc_areg() - increment an address register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3852) # dec_areg() - decrement an address register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3853) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3854) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3855) # d0 = number of bytes to adjust <ea> by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3856) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3857) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3858) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3859) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3860) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3861) # "Dummy" CALCulate Effective Address: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3862) # The stacked <ea> for FP unimplemented instructions and opclass #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3863) # two packed instructions is correct with the exception of... #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3864) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3865) # 1) -(An) : The register is not updated regardless of size. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3866) # Also, for extended precision and packed, the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3867) # stacked <ea> value is 8 bytes too big #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3868) # 2) (An)+ : The register is not updated. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3869) # 3) #<data> : The upper longword of the immediate operand is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3870) # stacked b,w,l and s sizes are completely stacked. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3871) # d,x, and p are not. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3872) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3873) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3875) global _dcalc_ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3876) _dcalc_ea:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3877) mov.l %d0, %a0 # move # bytes to %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3879) mov.b 1+EXC_OPWORD(%a6), %d0 # fetch opcode word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3880) mov.l %d0, %d1 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3882) andi.w &0x38, %d0 # extract mode field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3883) andi.l &0x7, %d1 # extract reg field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3885) cmpi.b %d0,&0x18 # is mode (An)+ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3886) beq.b dcea_pi # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3888) cmpi.b %d0,&0x20 # is mode -(An) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3889) beq.b dcea_pd # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3891) or.w %d1,%d0 # concat mode,reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3892) cmpi.b %d0,&0x3c # is mode #<data>?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3894) beq.b dcea_imm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3896) mov.l EXC_EA(%a6),%a0 # return <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3897) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3899) # need to set immediate data flag here since we'll need to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3900) # an imem_read to fetch this later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3901) dcea_imm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3902) mov.b &immed_flg,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3903) lea ([USER_FPIAR,%a6],0x4),%a0 # no; return <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3904) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3906) # here, the <ea> is stacked correctly. however, we must update the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3907) # address register...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3908) dcea_pi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3909) mov.l %a0,%d0 # pass amt to inc by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3910) bsr.l inc_areg # inc addr register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3912) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3913) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3915) # the <ea> is stacked correctly for all but extended and packed which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3916) # the <ea>s are 8 bytes too large.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3917) # it would make no sense to have a pre-decrement to a7 in supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3918) # mode so we don't even worry about this tricky case here : )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3919) dcea_pd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3920) mov.l %a0,%d0 # pass amt to dec by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3921) bsr.l dec_areg # dec addr register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3923) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3925) cmpi.b %d0,&0xc # is opsize ext or packed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3926) beq.b dcea_pd2 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3927) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3928) dcea_pd2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3929) sub.l &0x8,%a0 # correct <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3930) mov.l %a0,EXC_EA(%a6) # put correct <ea> on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3931) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3933) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3934) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3935) # _calc_ea_fout(): calculate correct stacked <ea> for extended #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3936) # and packed data opclass 3 operations. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3937) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3938) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3939) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3940) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3941) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3942) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3943) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3944) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3945) # a0 = return correct effective address #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3946) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3947) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3948) # For opclass 3 extended and packed data operations, the <ea> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3949) # stacked for the exception is incorrect for -(an) and (an)+ addressing #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3950) # modes. Also, while we're at it, the index register itself must get #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3951) # updated. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3952) # So, for -(an), we must subtract 8 off of the stacked <ea> value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3953) # and return that value as the correct <ea> and store that value in An. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3954) # For (an)+, the stacked <ea> is correct but we must adjust An by +12. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3955) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3956) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3958) # This calc_ea is currently used to retrieve the correct <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3959) # for fmove outs of type extended and packed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3960) global _calc_ea_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3961) _calc_ea_fout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3962) mov.b 1+EXC_OPWORD(%a6),%d0 # fetch opcode word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3963) mov.l %d0,%d1 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3965) andi.w &0x38,%d0 # extract mode field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3966) andi.l &0x7,%d1 # extract reg field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3968) cmpi.b %d0,&0x18 # is mode (An)+ ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3969) beq.b ceaf_pi # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3971) cmpi.b %d0,&0x20 # is mode -(An) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3972) beq.w ceaf_pd # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3974) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3975) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3977) # (An)+ : extended and packed fmove out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3978) # : stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3979) # : "An" not updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3980) ceaf_pi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3981) mov.w (tbl_ceaf_pi.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3982) mov.l EXC_EA(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3983) jmp (tbl_ceaf_pi.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3985) swbeg &0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3986) tbl_ceaf_pi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3987) short ceaf_pi0 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3988) short ceaf_pi1 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3989) short ceaf_pi2 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3990) short ceaf_pi3 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3991) short ceaf_pi4 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3992) short ceaf_pi5 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3993) short ceaf_pi6 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3994) short ceaf_pi7 - tbl_ceaf_pi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3996) ceaf_pi0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3997) addi.l &0xc,EXC_DREGS+0x8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3998) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3999) ceaf_pi1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4000) addi.l &0xc,EXC_DREGS+0xc(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4001) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4002) ceaf_pi2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4003) add.l &0xc,%a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4004) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4005) ceaf_pi3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4006) add.l &0xc,%a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4007) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4008) ceaf_pi4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4009) add.l &0xc,%a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4010) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4011) ceaf_pi5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4012) add.l &0xc,%a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4013) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4014) ceaf_pi6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4015) addi.l &0xc,EXC_A6(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4016) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4017) ceaf_pi7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4018) mov.b &mia7_flg,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4019) addi.l &0xc,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4020) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4022) # -(An) : extended and packed fmove out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4023) # : stacked <ea> = actual <ea> + 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4024) # : "An" not updated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4025) ceaf_pd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4026) mov.w (tbl_ceaf_pd.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4027) mov.l EXC_EA(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4028) sub.l &0x8,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4029) sub.l &0x8,EXC_EA(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4030) jmp (tbl_ceaf_pd.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4032) swbeg &0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4033) tbl_ceaf_pd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4034) short ceaf_pd0 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4035) short ceaf_pd1 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4036) short ceaf_pd2 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4037) short ceaf_pd3 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4038) short ceaf_pd4 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4039) short ceaf_pd5 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4040) short ceaf_pd6 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4041) short ceaf_pd7 - tbl_ceaf_pd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4043) ceaf_pd0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4044) mov.l %a0,EXC_DREGS+0x8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4045) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4046) ceaf_pd1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4047) mov.l %a0,EXC_DREGS+0xc(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4048) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4049) ceaf_pd2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4050) mov.l %a0,%a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4051) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4052) ceaf_pd3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4053) mov.l %a0,%a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4054) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4055) ceaf_pd4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4056) mov.l %a0,%a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4057) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4058) ceaf_pd5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4059) mov.l %a0,%a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4060) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4061) ceaf_pd6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4062) mov.l %a0,EXC_A6(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4063) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4064) ceaf_pd7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4065) mov.l %a0,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4066) mov.b &mda7_flg,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4067) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4069) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4070) # This table holds the offsets of the emulation routines for each individual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4071) # math operation relative to the address of this table. Included are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4072) # routines like fadd/fmul/fabs. The transcendentals ARE NOT. This is because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4073) # this table is for the version if the 060FPSP without transcendentals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4074) # The location within the table is determined by the extension bits of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4075) # operation longword.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4076) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4078) swbeg &109
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4079) tbl_unsupp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4080) long fin - tbl_unsupp # 00: fmove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4081) long fint - tbl_unsupp # 01: fint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4082) long tbl_unsupp - tbl_unsupp # 02: fsinh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4083) long fintrz - tbl_unsupp # 03: fintrz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4084) long fsqrt - tbl_unsupp # 04: fsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4085) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4086) long tbl_unsupp - tbl_unsupp # 06: flognp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4087) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4088) long tbl_unsupp - tbl_unsupp # 08: fetoxm1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4089) long tbl_unsupp - tbl_unsupp # 09: ftanh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4090) long tbl_unsupp - tbl_unsupp # 0a: fatan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4091) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4092) long tbl_unsupp - tbl_unsupp # 0c: fasin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4093) long tbl_unsupp - tbl_unsupp # 0d: fatanh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4094) long tbl_unsupp - tbl_unsupp # 0e: fsin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4095) long tbl_unsupp - tbl_unsupp # 0f: ftan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4096) long tbl_unsupp - tbl_unsupp # 10: fetox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4097) long tbl_unsupp - tbl_unsupp # 11: ftwotox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4098) long tbl_unsupp - tbl_unsupp # 12: ftentox
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4099) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4100) long tbl_unsupp - tbl_unsupp # 14: flogn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4101) long tbl_unsupp - tbl_unsupp # 15: flog10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4102) long tbl_unsupp - tbl_unsupp # 16: flog2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4103) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4104) long fabs - tbl_unsupp # 18: fabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4105) long tbl_unsupp - tbl_unsupp # 19: fcosh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4106) long fneg - tbl_unsupp # 1a: fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4107) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4108) long tbl_unsupp - tbl_unsupp # 1c: facos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4109) long tbl_unsupp - tbl_unsupp # 1d: fcos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4110) long tbl_unsupp - tbl_unsupp # 1e: fgetexp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4111) long tbl_unsupp - tbl_unsupp # 1f: fgetman
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4112) long fdiv - tbl_unsupp # 20: fdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4113) long tbl_unsupp - tbl_unsupp # 21: fmod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4114) long fadd - tbl_unsupp # 22: fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4115) long fmul - tbl_unsupp # 23: fmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4116) long fsgldiv - tbl_unsupp # 24: fsgldiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4117) long tbl_unsupp - tbl_unsupp # 25: frem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4118) long tbl_unsupp - tbl_unsupp # 26: fscale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4119) long fsglmul - tbl_unsupp # 27: fsglmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4120) long fsub - tbl_unsupp # 28: fsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4121) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4122) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4123) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4124) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4125) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4126) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4127) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4128) long tbl_unsupp - tbl_unsupp # 30: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4129) long tbl_unsupp - tbl_unsupp # 31: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4130) long tbl_unsupp - tbl_unsupp # 32: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4131) long tbl_unsupp - tbl_unsupp # 33: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4132) long tbl_unsupp - tbl_unsupp # 34: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4133) long tbl_unsupp - tbl_unsupp # 35: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4134) long tbl_unsupp - tbl_unsupp # 36: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4135) long tbl_unsupp - tbl_unsupp # 37: fsincos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4136) long fcmp - tbl_unsupp # 38: fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4137) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4138) long ftst - tbl_unsupp # 3a: ftst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4139) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4140) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4141) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4142) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4143) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4144) long fsin - tbl_unsupp # 40: fsmove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4145) long fssqrt - tbl_unsupp # 41: fssqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4146) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4147) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4148) long fdin - tbl_unsupp # 44: fdmove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4149) long fdsqrt - tbl_unsupp # 45: fdsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4150) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4151) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4152) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4153) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4154) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4155) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4156) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4157) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4158) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4159) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4160) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4161) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4162) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4163) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4164) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4165) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4166) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4167) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4168) long fsabs - tbl_unsupp # 58: fsabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4169) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4170) long fsneg - tbl_unsupp # 5a: fsneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4171) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4172) long fdabs - tbl_unsupp # 5c: fdabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4173) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4174) long fdneg - tbl_unsupp # 5e: fdneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4175) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4176) long fsdiv - tbl_unsupp # 60: fsdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4177) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4178) long fsadd - tbl_unsupp # 62: fsadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4179) long fsmul - tbl_unsupp # 63: fsmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4180) long fddiv - tbl_unsupp # 64: fddiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4181) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4182) long fdadd - tbl_unsupp # 66: fdadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4183) long fdmul - tbl_unsupp # 67: fdmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4184) long fssub - tbl_unsupp # 68: fssub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4185) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4186) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4187) long tbl_unsupp - tbl_unsupp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4188) long fdsub - tbl_unsupp # 6c: fdsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4190) #################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4191) # Add this here so non-fp modules can compile.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4192) # (smovcr is called from fpsp_inex.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4193) global smovcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4194) smovcr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4195) bra.b smovcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4197) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4198) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4199) # fmovm_dynamic(): emulate "fmovm" dynamic instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4200) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4201) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4202) # fetch_dreg() - fetch data register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4203) # {i,d,}mem_read() - fetch data from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4204) # _mem_write() - write data to memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4205) # iea_iacc() - instruction memory access error occurred #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4206) # iea_dacc() - data memory access error occurred #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4207) # restore() - restore An index regs if access error occurred #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4208) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4209) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4210) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4211) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4212) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4213) # If instr is "fmovm Dn,-(A7)" from supervisor mode, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4214) # d0 = size of dump #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4215) # d1 = Dn #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4216) # Else if instruction access error, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4217) # d0 = FSLW #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4218) # Else if data access error, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4219) # d0 = FSLW #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4220) # a0 = address of fault #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4221) # Else #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4222) # none. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4223) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4224) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4225) # The effective address must be calculated since this is entered #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4226) # from an "Unimplemented Effective Address" exception handler. So, we #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4227) # have our own fcalc_ea() routine here. If an access error is flagged #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4228) # by a _{i,d,}mem_read() call, we must exit through the special #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4229) # handler. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4230) # The data register is determined and its value loaded to get the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4231) # string of FP registers affected. This value is used as an index into #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4232) # a lookup table such that we can determine the number of bytes #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4233) # involved. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4234) # If the instruction is "fmovm.x <ea>,Dn", a _mem_read() is used #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4235) # to read in all FP values. Again, _mem_read() may fail and require a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4236) # special exit. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4237) # If the instruction is "fmovm.x DN,<ea>", a _mem_write() is used #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4238) # to write all FP values. _mem_write() may also fail. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4239) # If the instruction is "fmovm.x DN,-(a7)" from supervisor mode, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4240) # then we return the size of the dump and the string to the caller #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4241) # so that the move can occur outside of this routine. This special #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4242) # case is required so that moves to the system stack are handled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4243) # correctly. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4244) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4245) # DYNAMIC: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4246) # fmovm.x dn, <ea> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4247) # fmovm.x <ea>, dn #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4248) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4249) # <WORD 1> <WORD2> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4250) # 1111 0010 00 |<ea>| 11@& 1000 0$$$ 0000 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4251) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4252) # & = (0): predecrement addressing mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4253) # (1): postincrement or control addressing mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4254) # @ = (0): move listed regs from memory to the FPU #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4255) # (1): move listed regs from the FPU to memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4256) # $$$ : index of data register holding reg select mask #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4257) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4258) # NOTES: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4259) # If the data register holds a zero, then the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4260) # instruction is a nop. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4261) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4262) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4264) global fmovm_dynamic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4265) fmovm_dynamic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4267) # extract the data register in which the bit string resides...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4268) mov.b 1+EXC_EXTWORD(%a6),%d1 # fetch extword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4269) andi.w &0x70,%d1 # extract reg bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4270) lsr.b &0x4,%d1 # shift into lo bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4272) # fetch the bit string into d0...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4273) bsr.l fetch_dreg # fetch reg string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4275) andi.l &0x000000ff,%d0 # keep only lo byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4277) mov.l %d0,-(%sp) # save strg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4278) mov.b (tbl_fmovm_size.w,%pc,%d0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4279) mov.l %d0,-(%sp) # save size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4280) bsr.l fmovm_calc_ea # calculate <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4281) mov.l (%sp)+,%d0 # restore size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4282) mov.l (%sp)+,%d1 # restore strg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4284) # if the bit string is a zero, then the operation is a no-op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4285) # but, make sure that we've calculated ea and advanced the opword pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4286) beq.w fmovm_data_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4288) # separate move ins from move outs...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4289) btst &0x5,EXC_EXTWORD(%a6) # is it a move in or out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4290) beq.w fmovm_data_in # it's a move out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4292) #############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4293) # MOVE OUT: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4294) #############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4295) fmovm_data_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4296) btst &0x4,EXC_EXTWORD(%a6) # control or predecrement?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4297) bne.w fmovm_out_ctrl # control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4299) ############################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4300) fmovm_out_predec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4301) # for predecrement mode, the bit string is the opposite of both control
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4302) # operations and postincrement mode. (bit7 = FP7 ... bit0 = FP0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4303) # here, we convert it to be just like the others...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4304) mov.b (tbl_fmovm_convert.w,%pc,%d1.w*1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4306) btst &0x5,EXC_SR(%a6) # user or supervisor mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4307) beq.b fmovm_out_ctrl # user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4309) fmovm_out_predec_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4310) cmpi.b SPCOND_FLG(%a6),&mda7_flg # is <ea> mode -(a7)?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4311) bne.b fmovm_out_ctrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4313) # the operation was unfortunately an: fmovm.x dn,-(sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4314) # called from supervisor mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4315) # we're also passing "size" and "strg" back to the calling routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4316) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4318) ############################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4319) fmovm_out_ctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4320) mov.l %a0,%a1 # move <ea> to a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4322) sub.l %d0,%sp # subtract size of dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4323) lea (%sp),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4325) tst.b %d1 # should FP0 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4326) bpl.b fmovm_out_ctrl_fp1 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4328) mov.l 0x0+EXC_FP0(%a6),(%a0)+ # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4329) mov.l 0x4+EXC_FP0(%a6),(%a0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4330) mov.l 0x8+EXC_FP0(%a6),(%a0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4332) fmovm_out_ctrl_fp1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4333) lsl.b &0x1,%d1 # should FP1 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4334) bpl.b fmovm_out_ctrl_fp2 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4336) mov.l 0x0+EXC_FP1(%a6),(%a0)+ # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4337) mov.l 0x4+EXC_FP1(%a6),(%a0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4338) mov.l 0x8+EXC_FP1(%a6),(%a0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4340) fmovm_out_ctrl_fp2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4341) lsl.b &0x1,%d1 # should FP2 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4342) bpl.b fmovm_out_ctrl_fp3 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4344) fmovm.x &0x20,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4345) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4347) fmovm_out_ctrl_fp3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4348) lsl.b &0x1,%d1 # should FP3 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4349) bpl.b fmovm_out_ctrl_fp4 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4351) fmovm.x &0x10,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4352) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4354) fmovm_out_ctrl_fp4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4355) lsl.b &0x1,%d1 # should FP4 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4356) bpl.b fmovm_out_ctrl_fp5 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4358) fmovm.x &0x08,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4359) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4361) fmovm_out_ctrl_fp5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4362) lsl.b &0x1,%d1 # should FP5 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4363) bpl.b fmovm_out_ctrl_fp6 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4365) fmovm.x &0x04,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4366) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4368) fmovm_out_ctrl_fp6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4369) lsl.b &0x1,%d1 # should FP6 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4370) bpl.b fmovm_out_ctrl_fp7 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4372) fmovm.x &0x02,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4373) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4375) fmovm_out_ctrl_fp7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4376) lsl.b &0x1,%d1 # should FP7 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4377) bpl.b fmovm_out_ctrl_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4379) fmovm.x &0x01,(%a0) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4380) add.l &0xc,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4382) fmovm_out_ctrl_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4383) mov.l %a1,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4385) lea (%sp),%a0 # pass: supervisor src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4386) mov.l %d0,-(%sp) # save size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4387) bsr.l _dmem_write # copy data to user mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4389) mov.l (%sp)+,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4390) add.l %d0,%sp # clear fpreg data from stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4392) tst.l %d1 # did dstore err?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4393) bne.w fmovm_out_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4395) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4397) ############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4398) # MOVE IN: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4399) ############
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4400) fmovm_data_in:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4401) mov.l %a0,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4403) sub.l %d0,%sp # make room for fpregs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4404) lea (%sp),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4406) mov.l %d1,-(%sp) # save bit string for later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4407) mov.l %d0,-(%sp) # save # of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4409) bsr.l _dmem_read # copy data from user mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4411) mov.l (%sp)+,%d0 # retrieve # of bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4413) tst.l %d1 # did dfetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4414) bne.w fmovm_in_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4416) mov.l (%sp)+,%d1 # load bit string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4418) lea (%sp),%a0 # addr of stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4420) tst.b %d1 # should FP0 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4421) bpl.b fmovm_data_in_fp1 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4423) mov.l (%a0)+,0x0+EXC_FP0(%a6) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4424) mov.l (%a0)+,0x4+EXC_FP0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4425) mov.l (%a0)+,0x8+EXC_FP0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4427) fmovm_data_in_fp1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4428) lsl.b &0x1,%d1 # should FP1 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4429) bpl.b fmovm_data_in_fp2 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4431) mov.l (%a0)+,0x0+EXC_FP1(%a6) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4432) mov.l (%a0)+,0x4+EXC_FP1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4433) mov.l (%a0)+,0x8+EXC_FP1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4435) fmovm_data_in_fp2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4436) lsl.b &0x1,%d1 # should FP2 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4437) bpl.b fmovm_data_in_fp3 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4439) fmovm.x (%a0)+,&0x20 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4441) fmovm_data_in_fp3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4442) lsl.b &0x1,%d1 # should FP3 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4443) bpl.b fmovm_data_in_fp4 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4445) fmovm.x (%a0)+,&0x10 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4447) fmovm_data_in_fp4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4448) lsl.b &0x1,%d1 # should FP4 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4449) bpl.b fmovm_data_in_fp5 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4451) fmovm.x (%a0)+,&0x08 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4453) fmovm_data_in_fp5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4454) lsl.b &0x1,%d1 # should FP5 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4455) bpl.b fmovm_data_in_fp6 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4457) fmovm.x (%a0)+,&0x04 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4459) fmovm_data_in_fp6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4460) lsl.b &0x1,%d1 # should FP6 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4461) bpl.b fmovm_data_in_fp7 # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4463) fmovm.x (%a0)+,&0x02 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4465) fmovm_data_in_fp7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4466) lsl.b &0x1,%d1 # should FP7 be moved?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4467) bpl.b fmovm_data_in_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4469) fmovm.x (%a0)+,&0x01 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4471) fmovm_data_in_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4472) add.l %d0,%sp # remove fpregs from stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4473) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4475) #####################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4477) fmovm_data_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4478) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4480) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4482) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4483) # table indexed by the operation's bit string that gives the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4484) # of bytes that will be moved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4485) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4486) # number of bytes = (# of 1's in bit string) * 12(bytes/fpreg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4487) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4488) tbl_fmovm_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4489) byte 0x00,0x0c,0x0c,0x18,0x0c,0x18,0x18,0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4490) byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4491) byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4492) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4493) byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4494) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4495) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4496) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4497) byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4498) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4499) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4500) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4501) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4502) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4503) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4504) byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4505) byte 0x0c,0x18,0x18,0x24,0x18,0x24,0x24,0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4506) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4507) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4508) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4509) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4510) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4511) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4512) byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4513) byte 0x18,0x24,0x24,0x30,0x24,0x30,0x30,0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4514) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4515) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4516) byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4517) byte 0x24,0x30,0x30,0x3c,0x30,0x3c,0x3c,0x48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4518) byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4519) byte 0x30,0x3c,0x3c,0x48,0x3c,0x48,0x48,0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4520) byte 0x3c,0x48,0x48,0x54,0x48,0x54,0x54,0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4522) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4523) # table to convert a pre-decrement bit string into a post-increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4524) # or control bit string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4525) # ex: 0x00 ==> 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4526) # 0x01 ==> 0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4527) # 0x02 ==> 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4528) # .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4529) # .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4530) # 0xfd ==> 0xbf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4531) # 0xfe ==> 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4532) # 0xff ==> 0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4533) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4534) tbl_fmovm_convert:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4535) byte 0x00,0x80,0x40,0xc0,0x20,0xa0,0x60,0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4536) byte 0x10,0x90,0x50,0xd0,0x30,0xb0,0x70,0xf0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4537) byte 0x08,0x88,0x48,0xc8,0x28,0xa8,0x68,0xe8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4538) byte 0x18,0x98,0x58,0xd8,0x38,0xb8,0x78,0xf8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4539) byte 0x04,0x84,0x44,0xc4,0x24,0xa4,0x64,0xe4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4540) byte 0x14,0x94,0x54,0xd4,0x34,0xb4,0x74,0xf4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4541) byte 0x0c,0x8c,0x4c,0xcc,0x2c,0xac,0x6c,0xec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4542) byte 0x1c,0x9c,0x5c,0xdc,0x3c,0xbc,0x7c,0xfc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4543) byte 0x02,0x82,0x42,0xc2,0x22,0xa2,0x62,0xe2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4544) byte 0x12,0x92,0x52,0xd2,0x32,0xb2,0x72,0xf2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4545) byte 0x0a,0x8a,0x4a,0xca,0x2a,0xaa,0x6a,0xea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4546) byte 0x1a,0x9a,0x5a,0xda,0x3a,0xba,0x7a,0xfa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4547) byte 0x06,0x86,0x46,0xc6,0x26,0xa6,0x66,0xe6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4548) byte 0x16,0x96,0x56,0xd6,0x36,0xb6,0x76,0xf6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4549) byte 0x0e,0x8e,0x4e,0xce,0x2e,0xae,0x6e,0xee
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4550) byte 0x1e,0x9e,0x5e,0xde,0x3e,0xbe,0x7e,0xfe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4551) byte 0x01,0x81,0x41,0xc1,0x21,0xa1,0x61,0xe1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4552) byte 0x11,0x91,0x51,0xd1,0x31,0xb1,0x71,0xf1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4553) byte 0x09,0x89,0x49,0xc9,0x29,0xa9,0x69,0xe9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4554) byte 0x19,0x99,0x59,0xd9,0x39,0xb9,0x79,0xf9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4555) byte 0x05,0x85,0x45,0xc5,0x25,0xa5,0x65,0xe5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4556) byte 0x15,0x95,0x55,0xd5,0x35,0xb5,0x75,0xf5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4557) byte 0x0d,0x8d,0x4d,0xcd,0x2d,0xad,0x6d,0xed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4558) byte 0x1d,0x9d,0x5d,0xdd,0x3d,0xbd,0x7d,0xfd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4559) byte 0x03,0x83,0x43,0xc3,0x23,0xa3,0x63,0xe3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4560) byte 0x13,0x93,0x53,0xd3,0x33,0xb3,0x73,0xf3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4561) byte 0x0b,0x8b,0x4b,0xcb,0x2b,0xab,0x6b,0xeb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4562) byte 0x1b,0x9b,0x5b,0xdb,0x3b,0xbb,0x7b,0xfb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4563) byte 0x07,0x87,0x47,0xc7,0x27,0xa7,0x67,0xe7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4564) byte 0x17,0x97,0x57,0xd7,0x37,0xb7,0x77,0xf7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4565) byte 0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4566) byte 0x1f,0x9f,0x5f,0xdf,0x3f,0xbf,0x7f,0xff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4568) global fmovm_calc_ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4569) ###############################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4570) # _fmovm_calc_ea: calculate effective address #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4571) ###############################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4572) fmovm_calc_ea:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4573) mov.l %d0,%a0 # move # bytes to a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4575) # currently, MODE and REG are taken from the EXC_OPWORD. this could be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4576) # easily changed if they were inputs passed in registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4577) mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4578) mov.w %d0,%d1 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4580) andi.w &0x3f,%d0 # extract mode field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4581) andi.l &0x7,%d1 # extract reg field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4583) # jump to the corresponding function for each {MODE,REG} pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4584) mov.w (tbl_fea_mode.b,%pc,%d0.w*2),%d0 # fetch jmp distance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4585) jmp (tbl_fea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4587) swbeg &64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4588) tbl_fea_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4589) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4590) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4591) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4592) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4593) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4594) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4595) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4596) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4598) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4599) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4600) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4601) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4602) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4603) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4604) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4605) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4607) short faddr_ind_a0 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4608) short faddr_ind_a1 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4609) short faddr_ind_a2 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4610) short faddr_ind_a3 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4611) short faddr_ind_a4 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4612) short faddr_ind_a5 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4613) short faddr_ind_a6 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4614) short faddr_ind_a7 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4616) short faddr_ind_p_a0 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4617) short faddr_ind_p_a1 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4618) short faddr_ind_p_a2 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4619) short faddr_ind_p_a3 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4620) short faddr_ind_p_a4 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4621) short faddr_ind_p_a5 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4622) short faddr_ind_p_a6 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4623) short faddr_ind_p_a7 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4625) short faddr_ind_m_a0 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4626) short faddr_ind_m_a1 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4627) short faddr_ind_m_a2 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4628) short faddr_ind_m_a3 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4629) short faddr_ind_m_a4 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4630) short faddr_ind_m_a5 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4631) short faddr_ind_m_a6 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4632) short faddr_ind_m_a7 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4634) short faddr_ind_disp_a0 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4635) short faddr_ind_disp_a1 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4636) short faddr_ind_disp_a2 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4637) short faddr_ind_disp_a3 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4638) short faddr_ind_disp_a4 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4639) short faddr_ind_disp_a5 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4640) short faddr_ind_disp_a6 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4641) short faddr_ind_disp_a7 - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4643) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4644) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4645) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4646) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4647) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4648) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4649) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4650) short faddr_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4652) short fabs_short - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4653) short fabs_long - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4654) short fpc_ind - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4655) short fpc_ind_ext - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4656) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4657) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4658) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4659) short tbl_fea_mode - tbl_fea_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4661) ###################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4662) # Address register indirect: (An) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4663) ###################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4664) faddr_ind_a0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4665) mov.l EXC_DREGS+0x8(%a6),%a0 # Get current a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4666) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4668) faddr_ind_a1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4669) mov.l EXC_DREGS+0xc(%a6),%a0 # Get current a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4670) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4672) faddr_ind_a2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4673) mov.l %a2,%a0 # Get current a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4674) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4676) faddr_ind_a3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4677) mov.l %a3,%a0 # Get current a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4678) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4680) faddr_ind_a4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4681) mov.l %a4,%a0 # Get current a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4682) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4684) faddr_ind_a5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4685) mov.l %a5,%a0 # Get current a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4686) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4688) faddr_ind_a6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4689) mov.l (%a6),%a0 # Get current a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4690) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4692) faddr_ind_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4693) mov.l EXC_A7(%a6),%a0 # Get current a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4694) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4696) #####################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4697) # Address register indirect w/ postincrement: (An)+ #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4698) #####################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4699) faddr_ind_p_a0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4700) mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4701) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4702) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4703) mov.l %d1,EXC_DREGS+0x8(%a6) # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4704) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4705) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4707) faddr_ind_p_a1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4708) mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4709) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4710) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4711) mov.l %d1,EXC_DREGS+0xc(%a6) # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4712) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4713) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4715) faddr_ind_p_a2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4716) mov.l %a2,%d0 # Get current a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4717) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4718) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4719) mov.l %d1,%a2 # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4720) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4721) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4723) faddr_ind_p_a3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4724) mov.l %a3,%d0 # Get current a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4725) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4726) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4727) mov.l %d1,%a3 # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4728) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4729) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4731) faddr_ind_p_a4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4732) mov.l %a4,%d0 # Get current a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4733) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4734) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4735) mov.l %d1,%a4 # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4736) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4737) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4739) faddr_ind_p_a5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4740) mov.l %a5,%d0 # Get current a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4741) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4742) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4743) mov.l %d1,%a5 # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4744) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4745) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4747) faddr_ind_p_a6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4748) mov.l (%a6),%d0 # Get current a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4749) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4750) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4751) mov.l %d1,(%a6) # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4752) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4753) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4755) faddr_ind_p_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4756) mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4758) mov.l EXC_A7(%a6),%d0 # Get current a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4759) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4760) add.l %a0,%d1 # Increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4761) mov.l %d1,EXC_A7(%a6) # Save incr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4762) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4763) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4765) ####################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4766) # Address register indirect w/ predecrement: -(An) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4767) ####################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4768) faddr_ind_m_a0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4769) mov.l EXC_DREGS+0x8(%a6),%d0 # Get current a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4770) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4771) mov.l %d0,EXC_DREGS+0x8(%a6) # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4772) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4773) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4775) faddr_ind_m_a1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4776) mov.l EXC_DREGS+0xc(%a6),%d0 # Get current a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4777) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4778) mov.l %d0,EXC_DREGS+0xc(%a6) # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4779) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4780) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4782) faddr_ind_m_a2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4783) mov.l %a2,%d0 # Get current a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4784) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4785) mov.l %d0,%a2 # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4786) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4787) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4789) faddr_ind_m_a3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4790) mov.l %a3,%d0 # Get current a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4791) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4792) mov.l %d0,%a3 # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4793) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4794) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4796) faddr_ind_m_a4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4797) mov.l %a4,%d0 # Get current a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4798) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4799) mov.l %d0,%a4 # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4800) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4801) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4803) faddr_ind_m_a5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4804) mov.l %a5,%d0 # Get current a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4805) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4806) mov.l %d0,%a5 # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4807) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4808) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4810) faddr_ind_m_a6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4811) mov.l (%a6),%d0 # Get current a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4812) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4813) mov.l %d0,(%a6) # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4814) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4815) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4817) faddr_ind_m_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4818) mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4820) mov.l EXC_A7(%a6),%d0 # Get current a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4821) sub.l %a0,%d0 # Decrement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4822) mov.l %d0,EXC_A7(%a6) # Save decr value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4823) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4824) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4826) ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4827) # Address register indirect w/ displacement: (d16, An) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4828) ########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4829) faddr_ind_disp_a0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4830) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4831) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4832) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4834) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4835) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4837) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4839) add.l EXC_DREGS+0x8(%a6),%a0 # a0 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4840) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4842) faddr_ind_disp_a1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4843) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4844) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4845) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4847) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4848) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4850) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4852) add.l EXC_DREGS+0xc(%a6),%a0 # a1 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4853) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4855) faddr_ind_disp_a2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4856) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4857) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4858) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4860) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4861) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4863) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4865) add.l %a2,%a0 # a2 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4866) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4868) faddr_ind_disp_a3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4869) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4870) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4871) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4873) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4874) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4876) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4878) add.l %a3,%a0 # a3 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4879) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4881) faddr_ind_disp_a4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4882) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4883) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4884) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4886) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4887) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4889) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4891) add.l %a4,%a0 # a4 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4892) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4894) faddr_ind_disp_a5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4895) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4896) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4897) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4899) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4900) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4902) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4904) add.l %a5,%a0 # a5 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4905) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4907) faddr_ind_disp_a6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4908) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4909) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4910) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4912) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4913) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4915) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4917) add.l (%a6),%a0 # a6 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4918) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4920) faddr_ind_disp_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4921) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4922) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4923) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4925) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4926) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4928) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4930) add.l EXC_A7(%a6),%a0 # a7 + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4931) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4933) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4934) # Address register indirect w/ index(8-bit displacement): (d8, An, Xn) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4935) # " " " w/ " (base displacement): (bd, An, Xn) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4936) # Memory indirect postindexed: ([bd, An], Xn, od) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4937) # Memory indirect preindexed: ([bd, An, Xn], od) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4938) ########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4939) faddr_ind_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4940) addq.l &0x8,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4941) bsr.l fetch_dreg # fetch base areg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4942) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4944) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4945) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4946) bsr.l _imem_read_word # fetch extword in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4948) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4949) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4951) mov.l (%sp)+,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4953) btst &0x8,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4954) bne.w fcalc_mem_ind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4956) mov.l %d0,L_SCR1(%a6) # hold opword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4958) mov.l %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4959) rol.w &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4960) andi.w &0xf,%d1 # extract index regno
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4962) # count on fetch_dreg() not to alter a0...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4963) bsr.l fetch_dreg # fetch index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4965) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4966) mov.l L_SCR1(%a6),%d2 # fetch opword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4968) btst &0xb,%d2 # is it word or long?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4969) bne.b faii8_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4970) ext.l %d0 # sign extend word index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4971) faii8_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4972) mov.l %d2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4973) rol.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4974) andi.l &0x3,%d1 # extract scale value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4976) lsl.l %d1,%d0 # shift index by scale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4978) extb.l %d2 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4979) add.l %d2,%d0 # index + disp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4980) add.l %d0,%a0 # An + (index + disp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4982) mov.l (%sp)+,%d2 # restore old d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4983) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4985) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4986) # Absolute short: (XXX).W #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4987) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4988) fabs_short:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4989) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4990) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4991) bsr.l _imem_read_word # fetch short address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4993) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4994) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4996) mov.w %d0,%a0 # return <ea> in a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4997) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4999) ##########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5000) # Absolute long: (XXX).L #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5001) ##########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5002) fabs_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5003) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5004) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5005) bsr.l _imem_read_long # fetch long address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5007) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5008) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5010) mov.l %d0,%a0 # return <ea> in a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5011) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5013) #######################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5014) # Program counter indirect w/ displacement: (d16, PC) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5015) #######################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5016) fpc_ind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5017) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5018) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5019) bsr.l _imem_read_word # fetch word displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5021) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5022) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5024) mov.w %d0,%a0 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5026) add.l EXC_EXTWPTR(%a6),%a0 # pc + d16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5028) # _imem_read_word() increased the extwptr by 2. need to adjust here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5029) subq.l &0x2,%a0 # adjust <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5030) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5032) ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5033) # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5034) # " " w/ " (base displacement): (bd, PC, An) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5035) # PC memory indirect postindexed: ([bd, PC], Xn, od) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5036) # PC memory indirect preindexed: ([bd, PC, Xn], od) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5037) ##########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5038) fpc_ind_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5039) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5040) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5041) bsr.l _imem_read_word # fetch ext word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5043) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5044) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5046) mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5047) subq.l &0x2,%a0 # adjust base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5049) btst &0x8,%d0 # is disp only 8 bits?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5050) bne.w fcalc_mem_ind # calc memory indirect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5052) mov.l %d0,L_SCR1(%a6) # store opword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5054) mov.l %d0,%d1 # make extword copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5055) rol.w &0x4,%d1 # rotate reg num into place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5056) andi.w &0xf,%d1 # extract register number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5058) # count on fetch_dreg() not to alter a0...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5059) bsr.l fetch_dreg # fetch index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5061) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5062) mov.l L_SCR1(%a6),%d2 # fetch opword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5064) btst &0xb,%d2 # is index word or long?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5065) bne.b fpii8_long # long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5066) ext.l %d0 # sign extend word index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5067) fpii8_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5068) mov.l %d2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5069) rol.w &0x7,%d1 # rotate scale value into place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5070) andi.l &0x3,%d1 # extract scale value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5072) lsl.l %d1,%d0 # shift index by scale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5074) extb.l %d2 # sign extend displacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5075) add.l %d2,%d0 # disp + index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5076) add.l %d0,%a0 # An + (index + disp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5078) mov.l (%sp)+,%d2 # restore temp register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5079) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5081) # d2 = index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5082) # d3 = base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5083) # d4 = od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5084) # d5 = extword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5085) fcalc_mem_ind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5086) btst &0x6,%d0 # is the index suppressed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5087) beq.b fcalc_index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5089) movm.l &0x3c00,-(%sp) # save d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5091) mov.l %d0,%d5 # put extword in d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5092) mov.l %a0,%d3 # put base in d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5094) clr.l %d2 # yes, so index = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5095) bra.b fbase_supp_ck
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5097) # index:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5098) fcalc_index:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5099) mov.l %d0,L_SCR1(%a6) # save d0 (opword)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5100) bfextu %d0{&16:&4},%d1 # fetch dreg index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5101) bsr.l fetch_dreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5103) movm.l &0x3c00,-(%sp) # save d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5104) mov.l %d0,%d2 # put index in d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5105) mov.l L_SCR1(%a6),%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5106) mov.l %a0,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5108) btst &0xb,%d5 # is index word or long?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5109) bne.b fno_ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5110) ext.l %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5112) fno_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5113) bfextu %d5{&21:&2},%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5114) lsl.l %d0,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5116) # base address (passed as parameter in d3):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5117) # we clear the value here if it should actually be suppressed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5118) fbase_supp_ck:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5119) btst &0x7,%d5 # is the bd suppressed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5120) beq.b fno_base_sup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5121) clr.l %d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5123) # base displacement:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5124) fno_base_sup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5125) bfextu %d5{&26:&2},%d0 # get bd size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5126) # beq.l fmovm_error # if (size == 0) it's reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5128) cmpi.b %d0,&0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5129) blt.b fno_bd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5130) beq.b fget_word_bd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5132) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5133) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5134) bsr.l _imem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5136) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5137) bne.l fcea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5139) bra.b fchk_ind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5141) fget_word_bd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5142) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5143) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5144) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5146) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5147) bne.l fcea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5149) ext.l %d0 # sign extend bd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5151) fchk_ind:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5152) add.l %d0,%d3 # base += bd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5154) # outer displacement:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5155) fno_bd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5156) bfextu %d5{&30:&2},%d0 # is od suppressed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5157) beq.w faii_bd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5159) cmpi.b %d0,&0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5160) blt.b fnull_od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5161) beq.b fword_od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5163) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5164) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5165) bsr.l _imem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5167) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5168) bne.l fcea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5170) bra.b fadd_them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5172) fword_od:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5173) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5174) addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5175) bsr.l _imem_read_word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5177) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5178) bne.l fcea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5180) ext.l %d0 # sign extend od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5181) bra.b fadd_them
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5183) fnull_od:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5184) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5186) fadd_them:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5187) mov.l %d0,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5189) btst &0x2,%d5 # pre or post indexing?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5190) beq.b fpre_indexed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5192) mov.l %d3,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5193) bsr.l _dmem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5195) tst.l %d1 # did dfetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5196) bne.w fcea_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5198) add.l %d2,%d0 # <ea> += index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5199) add.l %d4,%d0 # <ea> += od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5200) bra.b fdone_ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5202) fpre_indexed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5203) add.l %d2,%d3 # preindexing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5204) mov.l %d3,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5205) bsr.l _dmem_read_long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5207) tst.l %d1 # did dfetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5208) bne.w fcea_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5210) add.l %d4,%d0 # ea += od
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5211) bra.b fdone_ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5213) faii_bd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5214) add.l %d2,%d3 # ea = (base + bd) + index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5215) mov.l %d3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5216) fdone_ea:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5217) mov.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5219) movm.l (%sp)+,&0x003c # restore d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5220) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5222) #########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5223) fcea_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5224) mov.l %d3,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5226) movm.l (%sp)+,&0x003c # restore d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5227) mov.w &0x0101,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5228) bra.l iea_dacc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5230) fcea_iacc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5231) movm.l (%sp)+,&0x003c # restore d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5232) bra.l iea_iacc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5234) fmovm_out_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5235) bsr.l restore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5236) mov.w &0x00e1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5237) bra.b fmovm_err
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5239) fmovm_in_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5240) bsr.l restore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5241) mov.w &0x0161,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5243) fmovm_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5244) mov.l L_SCR1(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5245) bra.l iea_dacc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5247) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5248) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5249) # fmovm_ctrl(): emulate fmovm.l of control registers instr #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5250) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5251) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5252) # _imem_read_long() - read longword from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5253) # iea_iacc() - _imem_read_long() failed; error recovery #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5254) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5255) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5256) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5257) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5258) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5259) # If _imem_read_long() doesn't fail: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5260) # USER_FPCR(a6) = new FPCR value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5261) # USER_FPSR(a6) = new FPSR value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5262) # USER_FPIAR(a6) = new FPIAR value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5263) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5264) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5265) # Decode the instruction type by looking at the extension word #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5266) # in order to see how many control registers to fetch from memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5267) # Fetch them using _imem_read_long(). If this fetch fails, exit through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5268) # the special access error exit handler iea_iacc(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5269) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5270) # Instruction word decoding: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5271) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5272) # fmovem.l #<data>, {FPIAR&|FPCR&|FPSR} #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5273) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5274) # WORD1 WORD2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5275) # 1111 0010 00 111100 100$ $$00 0000 0000 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5276) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5277) # $$$ (100): FPCR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5278) # (010): FPSR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5279) # (001): FPIAR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5280) # (000): FPIAR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5281) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5282) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5284) global fmovm_ctrl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5285) fmovm_ctrl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5286) mov.b EXC_EXTWORD(%a6),%d0 # fetch reg select bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5287) cmpi.b %d0,&0x9c # fpcr & fpsr & fpiar ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5288) beq.w fctrl_in_7 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5289) cmpi.b %d0,&0x98 # fpcr & fpsr ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5290) beq.w fctrl_in_6 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5291) cmpi.b %d0,&0x94 # fpcr & fpiar ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5292) beq.b fctrl_in_5 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5294) # fmovem.l #<data>, fpsr/fpiar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5295) fctrl_in_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5296) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5297) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5298) bsr.l _imem_read_long # fetch FPSR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5300) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5301) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5303) mov.l %d0,USER_FPSR(%a6) # store new FPSR to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5304) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5305) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5306) bsr.l _imem_read_long # fetch FPIAR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5308) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5309) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5311) mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5312) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5314) # fmovem.l #<data>, fpcr/fpiar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5315) fctrl_in_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5316) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5317) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5318) bsr.l _imem_read_long # fetch FPCR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5320) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5321) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5323) mov.l %d0,USER_FPCR(%a6) # store new FPCR to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5324) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5325) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5326) bsr.l _imem_read_long # fetch FPIAR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5328) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5329) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5331) mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5332) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5334) # fmovem.l #<data>, fpcr/fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5335) fctrl_in_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5336) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5337) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5338) bsr.l _imem_read_long # fetch FPCR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5340) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5341) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5343) mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5344) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5345) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5346) bsr.l _imem_read_long # fetch FPSR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5348) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5349) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5351) mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5352) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5354) # fmovem.l #<data>, fpcr/fpsr/fpiar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5355) fctrl_in_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5356) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5357) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5358) bsr.l _imem_read_long # fetch FPCR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5360) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5361) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5363) mov.l %d0,USER_FPCR(%a6) # store new FPCR to mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5364) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5365) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5366) bsr.l _imem_read_long # fetch FPSR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5368) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5369) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5371) mov.l %d0,USER_FPSR(%a6) # store new FPSR to mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5372) mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5373) addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5374) bsr.l _imem_read_long # fetch FPIAR from mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5376) tst.l %d1 # did ifetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5377) bne.l iea_iacc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5379) mov.l %d0,USER_FPIAR(%a6) # store new FPIAR to mem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5380) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5382) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5384) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5385) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5386) # addsub_scaler2(): scale inputs to fadd/fsub such that no #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5387) # OVFL/UNFL exceptions will result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5388) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5389) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5390) # norm() - normalize mantissa after adjusting exponent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5391) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5392) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5393) # FP_SRC(a6) = fp op1(src) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5394) # FP_DST(a6) = fp op2(dst) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5395) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5396) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5397) # FP_SRC(a6) = fp op1 scaled(src) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5398) # FP_DST(a6) = fp op2 scaled(dst) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5399) # d0 = scale amount #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5400) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5401) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5402) # If the DST exponent is > the SRC exponent, set the DST exponent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5403) # equal to 0x3fff and scale the SRC exponent by the value that the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5404) # DST exponent was scaled by. If the SRC exponent is greater or equal, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5405) # do the opposite. Return this scale factor in d0. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5406) # If the two exponents differ by > the number of mantissa bits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5407) # plus two, then set the smallest exponent to a very small value as a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5408) # quick shortcut. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5409) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5410) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5412) global addsub_scaler2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5413) addsub_scaler2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5414) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5415) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5416) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5417) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5418) mov.w SRC_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5419) mov.w DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5420) mov.w %d0,FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5421) mov.w %d1,FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5423) andi.w &0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5424) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5425) mov.w %d0,L_SCR1(%a6) # store src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5426) mov.w %d1,2+L_SCR1(%a6) # store dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5428) cmp.w %d0, %d1 # is src exp >= dst exp?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5429) bge.l src_exp_ge2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5431) # dst exp is > src exp; scale dst to exp = 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5432) dst_exp_gt2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5433) bsr.l scale_to_zero_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5434) mov.l %d0,-(%sp) # save scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5436) cmpi.b STAG(%a6),&DENORM # is dst denormalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5437) bne.b cmpexp12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5439) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5440) bsr.l norm # normalize the denorm; result is new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5441) neg.w %d0 # new exp = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5442) mov.w %d0,L_SCR1(%a6) # inset new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5444) cmpexp12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5445) mov.w 2+L_SCR1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5446) subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5448) cmp.w %d0,L_SCR1(%a6) # is difference >= len(mantissa)+2?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5449) bge.b quick_scale12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5451) mov.w L_SCR1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5452) add.w 0x2(%sp),%d0 # scale src exponent by scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5453) mov.w FP_SCR0_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5454) and.w &0x8000,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5455) or.w %d1,%d0 # concat {sgn,new exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5456) mov.w %d0,FP_SCR0_EX(%a6) # insert new dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5458) mov.l (%sp)+,%d0 # return SCALE factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5459) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5461) quick_scale12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5462) andi.w &0x8000,FP_SCR0_EX(%a6) # zero src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5463) bset &0x0,1+FP_SCR0_EX(%a6) # set exp = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5465) mov.l (%sp)+,%d0 # return SCALE factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5466) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5468) # src exp is >= dst exp; scale src to exp = 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5469) src_exp_ge2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5470) bsr.l scale_to_zero_src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5471) mov.l %d0,-(%sp) # save scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5473) cmpi.b DTAG(%a6),&DENORM # is dst denormalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5474) bne.b cmpexp22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5475) lea FP_SCR1(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5476) bsr.l norm # normalize the denorm; result is new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5477) neg.w %d0 # new exp = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5478) mov.w %d0,2+L_SCR1(%a6) # inset new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5480) cmpexp22:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5481) mov.w L_SCR1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5482) subi.w &mantissalen+2,%d0 # subtract mantissalen+2 from larger exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5484) cmp.w %d0,2+L_SCR1(%a6) # is difference >= len(mantissa)+2?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5485) bge.b quick_scale22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5487) mov.w 2+L_SCR1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5488) add.w 0x2(%sp),%d0 # scale dst exponent by scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5489) mov.w FP_SCR1_EX(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5490) andi.w &0x8000,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5491) or.w %d1,%d0 # concat {sgn,new exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5492) mov.w %d0,FP_SCR1_EX(%a6) # insert new dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5494) mov.l (%sp)+,%d0 # return SCALE factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5495) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5497) quick_scale22:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5498) andi.w &0x8000,FP_SCR1_EX(%a6) # zero dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5499) bset &0x0,1+FP_SCR1_EX(%a6) # set exp = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5501) mov.l (%sp)+,%d0 # return SCALE factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5502) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5504) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5506) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5507) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5508) # scale_to_zero_src(): scale the exponent of extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5509) # value at FP_SCR0(a6). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5510) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5511) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5512) # norm() - normalize the mantissa if the operand was a DENORM #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5513) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5514) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5515) # FP_SCR0(a6) = extended precision operand to be scaled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5516) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5517) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5518) # FP_SCR0(a6) = scaled extended precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5519) # d0 = scale value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5520) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5521) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5522) # Set the exponent of the input operand to 0x3fff. Save the value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5523) # of the difference between the original and new exponent. Then, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5524) # normalize the operand if it was a DENORM. Add this normalization #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5525) # value to the previous value. Return the result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5526) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5527) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5529) global scale_to_zero_src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5530) scale_to_zero_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5531) mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5532) mov.w %d1,%d0 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5534) andi.l &0x7fff,%d1 # extract operand's exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5536) andi.w &0x8000,%d0 # extract operand's sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5537) or.w &0x3fff,%d0 # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5539) mov.w %d0,FP_SCR0_EX(%a6) # insert biased exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5541) cmpi.b STAG(%a6),&DENORM # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5542) beq.b stzs_denorm # normalize the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5544) stzs_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5545) mov.l &0x3fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5546) sub.l %d1,%d0 # scale = BIAS + (-exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5548) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5550) stzs_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5551) lea FP_SCR0(%a6),%a0 # pass ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5552) bsr.l norm # normalize denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5553) neg.l %d0 # new exponent = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5554) mov.l %d0,%d1 # prepare for op_norm call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5555) bra.b stzs_norm # finish scaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5557) ###
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5559) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5560) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5561) # scale_sqrt(): scale the input operand exponent so a subsequent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5562) # fsqrt operation won't take an exception. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5563) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5564) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5565) # norm() - normalize the mantissa if the operand was a DENORM #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5566) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5567) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5568) # FP_SCR0(a6) = extended precision operand to be scaled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5569) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5570) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5571) # FP_SCR0(a6) = scaled extended precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5572) # d0 = scale value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5573) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5574) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5575) # If the input operand is a DENORM, normalize it. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5576) # If the exponent of the input operand is even, set the exponent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5577) # to 0x3ffe and return a scale factor of "(exp-0x3ffe)/2". If the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5578) # exponent of the input operand is off, set the exponent to ox3fff and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5579) # return a scale factor of "(exp-0x3fff)/2". #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5580) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5581) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5583) global scale_sqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5584) scale_sqrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5585) cmpi.b STAG(%a6),&DENORM # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5586) beq.b ss_denorm # normalize the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5588) mov.w FP_SCR0_EX(%a6),%d1 # extract operand's {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5589) andi.l &0x7fff,%d1 # extract operand's exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5591) andi.w &0x8000,FP_SCR0_EX(%a6) # extract operand's sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5593) btst &0x0,%d1 # is exp even or odd?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5594) beq.b ss_norm_even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5596) ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5598) mov.l &0x3fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5599) sub.l %d1,%d0 # scale = BIAS + (-exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5600) asr.l &0x1,%d0 # divide scale factor by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5601) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5603) ss_norm_even:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5604) ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5606) mov.l &0x3ffe,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5607) sub.l %d1,%d0 # scale = BIAS + (-exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5608) asr.l &0x1,%d0 # divide scale factor by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5609) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5611) ss_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5612) lea FP_SCR0(%a6),%a0 # pass ptr to src op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5613) bsr.l norm # normalize denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5615) btst &0x0,%d0 # is exp even or odd?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5616) beq.b ss_denorm_even
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5618) ori.w &0x3fff,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5620) add.l &0x3fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5621) asr.l &0x1,%d0 # divide scale factor by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5622) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5624) ss_denorm_even:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5625) ori.w &0x3ffe,FP_SCR0_EX(%a6) # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5627) add.l &0x3ffe,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5628) asr.l &0x1,%d0 # divide scale factor by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5629) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5631) ###
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5633) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5634) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5635) # scale_to_zero_dst(): scale the exponent of extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5636) # value at FP_SCR1(a6). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5637) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5638) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5639) # norm() - normalize the mantissa if the operand was a DENORM #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5640) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5641) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5642) # FP_SCR1(a6) = extended precision operand to be scaled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5643) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5644) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5645) # FP_SCR1(a6) = scaled extended precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5646) # d0 = scale value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5647) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5648) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5649) # Set the exponent of the input operand to 0x3fff. Save the value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5650) # of the difference between the original and new exponent. Then, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5651) # normalize the operand if it was a DENORM. Add this normalization #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5652) # value to the previous value. Return the result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5653) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5654) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5656) global scale_to_zero_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5657) scale_to_zero_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5658) mov.w FP_SCR1_EX(%a6),%d1 # extract operand's {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5659) mov.w %d1,%d0 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5661) andi.l &0x7fff,%d1 # extract operand's exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5663) andi.w &0x8000,%d0 # extract operand's sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5664) or.w &0x3fff,%d0 # insert new operand's exponent(=0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5666) mov.w %d0,FP_SCR1_EX(%a6) # insert biased exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5668) cmpi.b DTAG(%a6),&DENORM # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5669) beq.b stzd_denorm # normalize the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5671) stzd_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5672) mov.l &0x3fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5673) sub.l %d1,%d0 # scale = BIAS + (-exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5674) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5676) stzd_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5677) lea FP_SCR1(%a6),%a0 # pass ptr to dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5678) bsr.l norm # normalize denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5679) neg.l %d0 # new exponent = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5680) mov.l %d0,%d1 # prepare for op_norm call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5681) bra.b stzd_norm # finish scaling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5683) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5685) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5686) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5687) # res_qnan(): return default result w/ QNAN operand for dyadic #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5688) # res_snan(): return default result w/ SNAN operand for dyadic #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5689) # res_qnan_1op(): return dflt result w/ QNAN operand for monadic #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5690) # res_snan_1op(): return dflt result w/ SNAN operand for monadic #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5691) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5692) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5693) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5694) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5695) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5696) # FP_SRC(a6) = pointer to extended precision src operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5697) # FP_DST(a6) = pointer to extended precision dst operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5698) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5699) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5700) # fp0 = default result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5701) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5702) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5703) # If either operand (but not both operands) of an operation is a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5704) # nonsignalling NAN, then that NAN is returned as the result. If both #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5705) # operands are nonsignalling NANs, then the destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5706) # nonsignalling NAN is returned as the result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5707) # If either operand to an operation is a signalling NAN (SNAN), #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5708) # then, the SNAN bit is set in the FPSR EXC byte. If the SNAN trap #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5709) # enable bit is set in the FPCR, then the trap is taken and the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5710) # destination is not modified. If the SNAN trap enable bit is not set, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5711) # then the SNAN is converted to a nonsignalling NAN (by setting the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5712) # SNAN bit in the operand to one), and the operation continues as #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5713) # described in the preceding paragraph, for nonsignalling NANs. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5714) # Make sure the appropriate FPSR bits are set before exiting. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5715) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5716) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5718) global res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5719) global res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5720) res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5721) res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5722) cmp.b DTAG(%a6), &SNAN # is the dst an SNAN?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5723) beq.b dst_snan2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5724) cmp.b DTAG(%a6), &QNAN # is the dst a QNAN?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5725) beq.b dst_qnan2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5726) src_nan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5727) cmp.b STAG(%a6), &QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5728) beq.b src_qnan2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5729) global res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5730) res_snan_1op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5731) src_snan2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5732) bset &0x6, FP_SRC_HI(%a6) # set SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5733) or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5734) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5735) bra.b nan_comp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5736) global res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5737) res_qnan_1op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5738) src_qnan2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5739) or.l &nan_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5740) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5741) bra.b nan_comp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5742) dst_snan2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5743) or.l &nan_mask+aiop_mask+snan_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5744) bset &0x6, FP_DST_HI(%a6) # set SNAN bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5745) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5746) bra.b nan_comp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5747) dst_qnan2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5748) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5749) cmp.b STAG(%a6), &SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5750) bne nan_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5751) or.l &aiop_mask+snan_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5752) nan_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5753) or.l &nan_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5754) nan_comp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5755) btst &0x7, FTEMP_EX(%a0) # is NAN neg?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5756) beq.b nan_not_neg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5757) or.l &neg_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5758) nan_not_neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5759) fmovm.x (%a0), &0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5760) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5762) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5763) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5764) # res_operr(): return default result during operand error #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5765) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5766) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5767) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5768) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5769) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5770) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5771) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5772) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5773) # fp0 = default operand error result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5774) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5775) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5776) # An nonsignalling NAN is returned as the default result when #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5777) # an operand error occurs for the following cases: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5778) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5779) # Multiply: (Infinity x Zero) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5780) # Divide : (Zero / Zero) || (Infinity / Infinity) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5781) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5782) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5784) global res_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5785) res_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5786) or.l &nan_mask+operr_mask+aiop_mask, USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5787) fmovm.x nan_return(%pc), &0x80
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5788) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5790) nan_return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5791) long 0x7fff0000, 0xffffffff, 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5793) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5794) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5795) # _denorm(): denormalize an intermediate result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5796) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5797) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5798) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5799) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5800) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5801) # a0 = points to the operand to be denormalized #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5802) # (in the internal extended format) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5803) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5804) # d0 = rounding precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5805) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5806) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5807) # a0 = pointer to the denormalized result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5808) # (in the internal extended format) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5809) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5810) # d0 = guard,round,sticky #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5811) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5812) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5813) # According to the exponent underflow threshold for the given #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5814) # precision, shift the mantissa bits to the right in order raise the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5815) # exponent of the operand to the threshold value. While shifting the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5816) # mantissa bits right, maintain the value of the guard, round, and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5817) # sticky bits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5818) # other notes: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5819) # (1) _denorm() is called by the underflow routines #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5820) # (2) _denorm() does NOT affect the status register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5821) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5822) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5824) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5825) # table of exponent threshold values for each precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5826) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5827) tbl_thresh:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5828) short 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5829) short sgl_thresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5830) short dbl_thresh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5832) global _denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5833) _denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5834) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5835) # Load the exponent threshold for the precision selected and check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5836) # to see if (threshold - exponent) is > 65 in which case we can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5837) # simply calculate the sticky bit and zero the mantissa. otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5838) # we have to call the denormalization routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5839) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5840) lsr.b &0x2, %d0 # shift prec to lo bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5841) mov.w (tbl_thresh.b,%pc,%d0.w*2), %d1 # load prec threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5842) mov.w %d1, %d0 # copy d1 into d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5843) sub.w FTEMP_EX(%a0), %d0 # diff = threshold - exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5844) cmpi.w %d0, &66 # is diff > 65? (mant + g,r bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5845) bpl.b denorm_set_stky # yes; just calc sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5847) clr.l %d0 # clear g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5848) btst &inex2_bit, FPSR_EXCEPT(%a6) # yes; was INEX2 set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5849) beq.b denorm_call # no; don't change anything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5850) bset &29, %d0 # yes; set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5852) denorm_call:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5853) bsr.l dnrm_lp # denormalize the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5854) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5856) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5857) # all bit would have been shifted off during the denorm so simply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5858) # calculate if the sticky should be set and clear the entire mantissa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5859) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5860) denorm_set_stky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5861) mov.l &0x20000000, %d0 # set sticky bit in return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5862) mov.w %d1, FTEMP_EX(%a0) # load exp with threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5863) clr.l FTEMP_HI(%a0) # set d1 = 0 (ms mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5864) clr.l FTEMP_LO(%a0) # set d2 = 0 (ms mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5865) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5867) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5868) # dnrm_lp(): normalize exponent/mantissa to specified threshold #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5869) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5870) # INPUT: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5871) # %a0 : points to the operand to be denormalized #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5872) # %d0{31:29} : initial guard,round,sticky #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5873) # %d1{15:0} : denormalization threshold #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5874) # OUTPUT: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5875) # %a0 : points to the denormalized operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5876) # %d0{31:29} : final guard,round,sticky #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5877) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5879) # *** Local Equates *** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5880) set GRS, L_SCR2 # g,r,s temp storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5881) set FTEMP_LO2, L_SCR1 # FTEMP_LO copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5883) global dnrm_lp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5884) dnrm_lp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5886) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5887) # make a copy of FTEMP_LO and place the g,r,s bits directly after it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5888) # in memory so as to make the bitfield extraction for denormalization easier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5889) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5890) mov.l FTEMP_LO(%a0), FTEMP_LO2(%a6) # make FTEMP_LO copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5891) mov.l %d0, GRS(%a6) # place g,r,s after it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5893) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5894) # check to see how much less than the underflow threshold the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5895) # exponent is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5896) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5897) mov.l %d1, %d0 # copy the denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5898) sub.w FTEMP_EX(%a0), %d1 # d1 = threshold - uns exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5899) ble.b dnrm_no_lp # d1 <= 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5900) cmpi.w %d1, &0x20 # is ( 0 <= d1 < 32) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5901) blt.b case_1 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5902) cmpi.w %d1, &0x40 # is (32 <= d1 < 64) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5903) blt.b case_2 # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5904) bra.w case_3 # (d1 >= 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5906) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5907) # No normalization necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5908) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5909) dnrm_no_lp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5910) mov.l GRS(%a6), %d0 # restore original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5911) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5913) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5914) # case (0<d1<32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5915) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5916) # %d0 = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5917) # %d1 = "n" = amt to shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5918) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5919) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5920) # | FTEMP_HI | FTEMP_LO |grs000.........000|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5921) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5922) # <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5923) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5924) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5925) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5926) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5927) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5928) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5929) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5930) # \ \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5931) # <-(n)-><-(32 - n)-><------(32)-------><------(32)------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5932) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5933) # |0.....0| NEW_HI | NEW_FTEMP_LO |grs |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5934) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5935) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5936) case_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5937) mov.l %d2, -(%sp) # create temp storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5939) mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5940) mov.l &32, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5941) sub.w %d1, %d0 # %d0 = 32 - %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5943) cmpi.w %d1, &29 # is shft amt >= 29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5944) blt.b case1_extract # no; no fix needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5945) mov.b GRS(%a6), %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5946) or.b %d2, 3+FTEMP_LO2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5948) case1_extract:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5949) bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_HI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5950) bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new FTEMP_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5951) bfextu FTEMP_LO2(%a6){%d0:&32}, %d0 # %d0 = new G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5953) mov.l %d2, FTEMP_HI(%a0) # store new FTEMP_HI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5954) mov.l %d1, FTEMP_LO(%a0) # store new FTEMP_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5956) bftst %d0{&2:&30} # were bits shifted off?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5957) beq.b case1_sticky_clear # no; go finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5958) bset &rnd_stky_bit, %d0 # yes; set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5960) case1_sticky_clear:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5961) and.l &0xe0000000, %d0 # clear all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5962) mov.l (%sp)+, %d2 # restore temp register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5963) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5965) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5966) # case (32<=d1<64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5967) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5968) # %d0 = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5969) # %d1 = "n" = amt to shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5970) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5971) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5972) # | FTEMP_HI | FTEMP_LO |grs000.........000|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5973) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5974) # <-(32 - n)-><-(n)-><-(32 - n)-><-(n)-><-(32 - n)-><-(n)->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5975) # \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5976) # \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5977) # \ \ -------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5978) # \ -------------------- \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5979) # ------------------- \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5980) # \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5981) # \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5982) # \ \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5983) # <-------(32)------><-(n)-><-(32 - n)-><------(32)------->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5984) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5985) # |0...............0|0....0| NEW_LO |grs |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5986) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5987) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5988) case_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5989) mov.l %d2, -(%sp) # create temp storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5991) mov.w %d0, FTEMP_EX(%a0) # exponent = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5992) subi.w &0x20, %d1 # %d1 now between 0 and 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5993) mov.l &0x20, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5994) sub.w %d1, %d0 # %d0 = 32 - %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5996) # subtle step here; or in the g,r,s at the bottom of FTEMP_LO to minimize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5997) # the number of bits to check for the sticky detect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5998) # it only plays a role in shift amounts of 61-63.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5999) mov.b GRS(%a6), %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6000) or.b %d2, 3+FTEMP_LO2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6002) bfextu FTEMP_HI(%a0){&0:%d0}, %d2 # %d2 = new FTEMP_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6003) bfextu FTEMP_HI(%a0){%d0:&32}, %d1 # %d1 = new G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6005) bftst %d1{&2:&30} # were any bits shifted off?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6006) bne.b case2_set_sticky # yes; set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6007) bftst FTEMP_LO2(%a6){%d0:&31} # were any bits shifted off?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6008) bne.b case2_set_sticky # yes; set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6010) mov.l %d1, %d0 # move new G,R,S to %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6011) bra.b case2_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6013) case2_set_sticky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6014) mov.l %d1, %d0 # move new G,R,S to %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6015) bset &rnd_stky_bit, %d0 # set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6017) case2_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6018) clr.l FTEMP_HI(%a0) # store FTEMP_HI = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6019) mov.l %d2, FTEMP_LO(%a0) # store FTEMP_LO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6020) and.l &0xe0000000, %d0 # clear all but G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6022) mov.l (%sp)+,%d2 # restore temp register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6023) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6025) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6026) # case (d1>=64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6027) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6028) # %d0 = denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6029) # %d1 = amt to shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6030) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6031) case_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6032) mov.w %d0, FTEMP_EX(%a0) # insert denorm threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6034) cmpi.w %d1, &65 # is shift amt > 65?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6035) blt.b case3_64 # no; it's == 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6036) beq.b case3_65 # no; it's == 65
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6038) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6039) # case (d1>65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6040) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6041) # Shift value is > 65 and out of range. All bits are shifted off.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6042) # Return a zero mantissa with the sticky bit set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6043) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6044) clr.l FTEMP_HI(%a0) # clear hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6045) clr.l FTEMP_LO(%a0) # clear lo(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6046) mov.l &0x20000000, %d0 # set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6047) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6049) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6050) # case (d1 == 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6051) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6052) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6053) # | FTEMP_HI | FTEMP_LO |grs000.........000|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6054) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6055) # <-------(32)------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6056) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6057) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6058) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6059) # \ ------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6060) # ------------------------------- \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6061) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6062) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6063) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6064) # <-------(32)------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6065) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6066) # |0...............0|0................0|grs |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6067) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6068) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6069) case3_64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6070) mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6071) mov.l %d0, %d1 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6072) and.l &0xc0000000, %d0 # extract G,R
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6073) and.l &0x3fffffff, %d1 # extract other bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6075) bra.b case3_complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6077) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6078) # case (d1 == 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6079) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6080) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6081) # | FTEMP_HI | FTEMP_LO |grs000.........000|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6082) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6083) # <-------(32)------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6084) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6085) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6086) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6087) # \ ------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6088) # -------------------------------- \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6089) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6090) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6091) # \ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6092) # <-------(31)----->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6093) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6094) # |0...............0|0................0|0rs |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6095) # ---------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6096) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6097) case3_65:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6098) mov.l FTEMP_HI(%a0), %d0 # fetch hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6099) and.l &0x80000000, %d0 # extract R bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6100) lsr.l &0x1, %d0 # shift high bit into R bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6101) and.l &0x7fffffff, %d1 # extract other bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6103) case3_complete:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6104) # last operation done was an "and" of the bits shifted off so the condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6105) # codes are already set so branch accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6106) bne.b case3_set_sticky # yes; go set new sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6107) tst.l FTEMP_LO(%a0) # were any bits shifted off?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6108) bne.b case3_set_sticky # yes; go set new sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6109) tst.b GRS(%a6) # were any bits shifted off?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6110) bne.b case3_set_sticky # yes; go set new sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6112) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6113) # no bits were shifted off so don't set the sticky bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6114) # the guard and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6115) # the entire mantissa is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6116) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6117) clr.l FTEMP_HI(%a0) # clear hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6118) clr.l FTEMP_LO(%a0) # clear lo(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6119) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6121) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6122) # some bits were shifted off so set the sticky bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6123) # the entire mantissa is zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6124) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6125) case3_set_sticky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6126) bset &rnd_stky_bit,%d0 # set new sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6127) clr.l FTEMP_HI(%a0) # clear hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6128) clr.l FTEMP_LO(%a0) # clear lo(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6129) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6131) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6132) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6133) # _round(): round result according to precision/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6134) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6135) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6136) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6137) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6138) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6139) # a0 = ptr to input operand in internal extended format #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6140) # d1(hi) = contains rounding precision: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6141) # ext = $0000xxxx #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6142) # sgl = $0004xxxx #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6143) # dbl = $0008xxxx #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6144) # d1(lo) = contains rounding mode: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6145) # RN = $xxxx0000 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6146) # RZ = $xxxx0001 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6147) # RM = $xxxx0002 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6148) # RP = $xxxx0003 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6149) # d0{31:29} = contains the g,r,s bits (extended) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6150) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6151) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6152) # a0 = pointer to rounded result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6153) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6154) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6155) # On return the value pointed to by a0 is correctly rounded, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6156) # a0 is preserved and the g-r-s bits in d0 are cleared. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6157) # The result is not typed - the tag field is invalid. The #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6158) # result is still in the internal extended format. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6159) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6160) # The INEX bit of USER_FPSR will be set if the rounded result was #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6161) # inexact (i.e. if any of the g-r-s bits were set). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6162) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6163) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6165) global _round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6166) _round:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6167) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6168) # ext_grs() looks at the rounding precision and sets the appropriate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6169) # G,R,S bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6170) # If (G,R,S == 0) then result is exact and round is done, else set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6171) # the inex flag in status reg and continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6172) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6173) bsr.l ext_grs # extract G,R,S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6175) tst.l %d0 # are G,R,S zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6176) beq.w truncate # yes; round is complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6178) or.w &inx2a_mask, 2+USER_FPSR(%a6) # set inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6180) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6181) # Use rounding mode as an index into a jump table for these modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6182) # All of the following assumes grs != 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6183) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6184) mov.w (tbl_mode.b,%pc,%d1.w*2), %a1 # load jump offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6185) jmp (tbl_mode.b,%pc,%a1) # jmp to rnd mode handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6187) tbl_mode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6188) short rnd_near - tbl_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6189) short truncate - tbl_mode # RZ always truncates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6190) short rnd_mnus - tbl_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6191) short rnd_plus - tbl_mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6193) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6194) # ROUND PLUS INFINITY #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6195) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6196) # If sign of fp number = 0 (positive), then add 1 to l. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6197) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6198) rnd_plus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6199) tst.b FTEMP_SGN(%a0) # check for sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6200) bmi.w truncate # if positive then truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6202) mov.l &0xffffffff, %d0 # force g,r,s to be all f's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6203) swap %d1 # set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6205) cmpi.b %d1, &s_mode # is prec = sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6206) beq.w add_sgl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6207) bgt.w add_dbl # no; it's dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6208) bra.w add_ext # no; it's ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6210) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6211) # ROUND MINUS INFINITY #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6212) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6213) # If sign of fp number = 1 (negative), then add 1 to l. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6214) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6215) rnd_mnus:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6216) tst.b FTEMP_SGN(%a0) # check for sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6217) bpl.w truncate # if negative then truncate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6219) mov.l &0xffffffff, %d0 # force g,r,s to be all f's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6220) swap %d1 # set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6222) cmpi.b %d1, &s_mode # is prec = sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6223) beq.w add_sgl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6224) bgt.w add_dbl # no; it's dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6225) bra.w add_ext # no; it's ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6227) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6228) # ROUND NEAREST #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6229) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6230) # 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 6231) # Note that this will round to even in case of a tie. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6232) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6233) rnd_near:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6234) asl.l &0x1, %d0 # shift g-bit to c-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6235) bcc.w truncate # if (g=1) then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6237) swap %d1 # set up d1 for round prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6239) cmpi.b %d1, &s_mode # is prec = sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6240) beq.w add_sgl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6241) bgt.w add_dbl # no; it's dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6242) bra.w add_ext # no; it's ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6244) # *** LOCAL EQUATES ***
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6245) set ad_1_sgl, 0x00000100 # constant to add 1 to l-bit in sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6246) set ad_1_dbl, 0x00000800 # constant to add 1 to l-bit in dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6248) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6249) # ADD SINGLE #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6250) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6251) add_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6252) add.l &ad_1_sgl, FTEMP_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6253) bcc.b scc_clr # no mantissa overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6254) roxr.w FTEMP_HI(%a0) # shift v-bit back in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6255) roxr.w FTEMP_HI+2(%a0) # shift v-bit back in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6256) add.w &0x1, FTEMP_EX(%a0) # and incr exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6257) scc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6258) tst.l %d0 # test for rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6259) bne.b sgl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6260) and.w &0xfe00, FTEMP_HI+2(%a0) # clear the l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6261) sgl_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6262) and.l &0xffffff00, FTEMP_HI(%a0) # truncate bits beyond sgl limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6263) clr.l FTEMP_LO(%a0) # clear d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6264) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6266) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6267) # ADD EXTENDED #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6268) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6269) add_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6270) addq.l &1,FTEMP_LO(%a0) # add 1 to l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6271) bcc.b xcc_clr # test for carry out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6272) addq.l &1,FTEMP_HI(%a0) # propagate carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6273) bcc.b xcc_clr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6274) roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6275) roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6276) roxr.w FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6277) roxr.w FTEMP_LO+2(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6278) add.w &0x1,FTEMP_EX(%a0) # and inc exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6279) xcc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6280) tst.l %d0 # test rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6281) bne.b add_ext_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6282) and.b &0xfe,FTEMP_LO+3(%a0) # clear the l bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6283) add_ext_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6284) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6286) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6287) # ADD DOUBLE #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6288) #########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6289) add_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6290) add.l &ad_1_dbl, FTEMP_LO(%a0) # add 1 to lsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6291) bcc.b dcc_clr # no carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6292) addq.l &0x1, FTEMP_HI(%a0) # propagate carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6293) bcc.b dcc_clr # no carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6295) roxr.w FTEMP_HI(%a0) # mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6296) roxr.w FTEMP_HI+2(%a0) # mant is 0 so restore v-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6297) roxr.w FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6298) roxr.w FTEMP_LO+2(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6299) addq.w &0x1, FTEMP_EX(%a0) # incr exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6300) dcc_clr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6301) tst.l %d0 # test for rs = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6302) bne.b dbl_done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6303) and.w &0xf000, FTEMP_LO+2(%a0) # clear the l-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6305) dbl_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6306) and.l &0xfffff800,FTEMP_LO(%a0) # truncate bits beyond dbl limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6307) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6309) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6310) # Truncate all other bits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6311) ###########################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6312) truncate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6313) swap %d1 # select rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6315) cmpi.b %d1, &s_mode # is prec sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6316) beq.w sgl_done # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6317) bgt.b dbl_done # no; it's dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6318) rts # no; it's ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6321) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6322) # ext_grs(): extract guard, round and sticky bits according to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6323) # rounding precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6324) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6325) # INPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6326) # d0 = extended precision g,r,s (in d0{31:29})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6327) # d1 = {PREC,ROUND}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6328) # OUTPUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6329) # d0{31:29} = guard, round, sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6330) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6331) # The ext_grs extract the guard/round/sticky bits according to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6332) # selected rounding precision. It is called by the round subroutine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6333) # only. All registers except d0 are kept intact. d0 becomes an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6334) # updated guard,round,sticky in d0{31:29}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6335) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6336) # Notes: the ext_grs uses the round PREC, and therefore has to swap d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6337) # prior to usage, and needs to restore d1 to original. this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6338) # routine is tightly tied to the round routine and not meant to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6339) # uphold standard subroutine calling practices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6340) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6342) ext_grs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6343) swap %d1 # have d1.w point to round precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6344) tst.b %d1 # is rnd prec = extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6345) bne.b ext_grs_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6347) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6348) # %d0 actually already hold g,r,s since _round() had it before calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6349) # this function. so, as long as we don't disturb it, we are "returning" it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6350) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6351) ext_grs_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6352) swap %d1 # yes; return to correct positions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6353) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6355) ext_grs_not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6356) movm.l &0x3000, -(%sp) # make some temp registers {d2/d3}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6358) cmpi.b %d1, &s_mode # is rnd prec = sgl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6359) bne.b ext_grs_dbl # no; go handle dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6361) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6362) # sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6363) # 96 64 40 32 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6364) # -----------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6365) # | EXP |XXXXXXX| |xx | |grs|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6366) # -----------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6367) # <--(24)--->nn\ /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6368) # ee ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6369) # ww |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6370) # v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6371) # gr new sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6372) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6373) ext_grs_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6374) bfextu FTEMP_HI(%a0){&24:&2}, %d3 # sgl prec. g-r are 2 bits right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6375) mov.l &30, %d2 # of the sgl prec. limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6376) lsl.l %d2, %d3 # shift g-r bits to MSB of d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6377) mov.l FTEMP_HI(%a0), %d2 # get word 2 for s-bit test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6378) and.l &0x0000003f, %d2 # s bit is the or of all other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6379) bne.b ext_grs_st_stky # bits to the right of g-r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6380) tst.l FTEMP_LO(%a0) # test lower mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6381) bne.b ext_grs_st_stky # if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6382) tst.l %d0 # test original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6383) bne.b ext_grs_st_stky # if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6384) bra.b ext_grs_end_sd # if words 3 and 4 are clr, exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6386) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6387) # dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6388) # 96 64 32 11 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6389) # -----------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6390) # | EXP |XXXXXXX| | |xx |grs|
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6391) # -----------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6392) # nn\ /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6393) # ee -------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6394) # ww |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6395) # v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6396) # gr new sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6397) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6398) ext_grs_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6399) bfextu FTEMP_LO(%a0){&21:&2}, %d3 # dbl-prec. g-r are 2 bits right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6400) mov.l &30, %d2 # of the dbl prec. limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6401) lsl.l %d2, %d3 # shift g-r bits to the MSB of d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6402) mov.l FTEMP_LO(%a0), %d2 # get lower mantissa for s-bit test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6403) and.l &0x000001ff, %d2 # s bit is the or-ing of all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6404) bne.b ext_grs_st_stky # other bits to the right of g-r
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6405) tst.l %d0 # test word original g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6406) bne.b ext_grs_st_stky # if any are set, set sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6407) bra.b ext_grs_end_sd # if clear, exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6409) ext_grs_st_stky:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6410) bset &rnd_stky_bit, %d3 # set sticky bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6411) ext_grs_end_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6412) mov.l %d3, %d0 # return grs to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6414) movm.l (%sp)+, &0xc # restore scratch registers {d2/d3}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6416) swap %d1 # restore d1 to original
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6417) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6419) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6420) # norm(): normalize the mantissa of an extended precision input. the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6421) # input operand should not be normalized already. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6422) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6423) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6424) # norm() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6425) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6426) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6427) # none #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6428) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6429) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6430) # a0 = pointer fp extended precision operand to normalize #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6431) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6432) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6433) # d0 = number of bit positions the mantissa was shifted #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6434) # a0 = the input operand's mantissa is normalized; the exponent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6435) # is unchanged. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6436) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6437) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6438) global norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6439) norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6440) mov.l %d2, -(%sp) # create some temp regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6441) mov.l %d3, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6443) mov.l FTEMP_HI(%a0), %d0 # load hi(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6444) mov.l FTEMP_LO(%a0), %d1 # load lo(mantissa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6446) bfffo %d0{&0:&32}, %d2 # how many places to shift?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6447) beq.b norm_lo # hi(man) is all zeroes!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6449) norm_hi:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6450) lsl.l %d2, %d0 # left shift hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6451) bfextu %d1{&0:%d2}, %d3 # extract lo bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6453) or.l %d3, %d0 # create hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6454) lsl.l %d2, %d1 # create lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6456) mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6457) mov.l %d1, FTEMP_LO(%a0) # store new lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6459) mov.l %d2, %d0 # return shift amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6461) mov.l (%sp)+, %d3 # restore temp regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6462) mov.l (%sp)+, %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6464) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6466) norm_lo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6467) bfffo %d1{&0:&32}, %d2 # how many places to shift?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6468) lsl.l %d2, %d1 # shift lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6469) add.l &32, %d2 # add 32 to shft amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6471) mov.l %d1, FTEMP_HI(%a0) # store hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6472) clr.l FTEMP_LO(%a0) # lo(man) is now zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6474) mov.l %d2, %d0 # return shift amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6476) mov.l (%sp)+, %d3 # restore temp regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6477) mov.l (%sp)+, %d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6479) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6481) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6482) # unnorm_fix(): - changes an UNNORM to one of NORM, DENORM, or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6483) # - returns corresponding optype tag #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6484) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6485) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6486) # unnorm_fix() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6487) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6488) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6489) # norm() - normalize the mantissa #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6490) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6491) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6492) # a0 = pointer to unnormalized extended precision number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6493) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6494) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6495) # d0 = optype tag - is corrected to one of NORM, DENORM, or ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6496) # a0 = input operand has been converted to a norm, denorm, or #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6497) # zero; both the exponent and mantissa are changed. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6498) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6499) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6501) global unnorm_fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6502) unnorm_fix:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6503) bfffo FTEMP_HI(%a0){&0:&32}, %d0 # how many shifts are needed?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6504) bne.b unnorm_shift # hi(man) is not all zeroes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6506) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6507) # hi(man) is all zeroes so see if any bits in lo(man) are set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6508) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6509) unnorm_chk_lo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6510) bfffo FTEMP_LO(%a0){&0:&32}, %d0 # is operand really a zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6511) beq.w unnorm_zero # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6513) add.w &32, %d0 # no; fix shift distance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6515) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6516) # d0 = # shifts needed for complete normalization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6517) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6518) unnorm_shift:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6519) clr.l %d1 # clear top word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6520) mov.w FTEMP_EX(%a0), %d1 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6521) and.w &0x7fff, %d1 # strip off sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6523) cmp.w %d0, %d1 # will denorm push exp < 0?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6524) bgt.b unnorm_nrm_zero # yes; denorm only until exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6526) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6527) # exponent would not go < 0. Therefore, number stays normalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6528) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6529) sub.w %d0, %d1 # shift exponent value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6530) mov.w FTEMP_EX(%a0), %d0 # load old exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6531) and.w &0x8000, %d0 # save old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6532) or.w %d0, %d1 # {sgn,new exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6533) mov.w %d1, FTEMP_EX(%a0) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6535) bsr.l norm # normalize UNNORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6537) mov.b &NORM, %d0 # return new optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6538) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6540) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6541) # exponent would go < 0, so only denormalize until exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6542) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6543) unnorm_nrm_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6544) cmp.b %d1, &32 # is exp <= 32?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6545) bgt.b unnorm_nrm_zero_lrg # no; go handle large exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6547) bfextu FTEMP_HI(%a0){%d1:&32}, %d0 # extract new hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6548) mov.l %d0, FTEMP_HI(%a0) # save new hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6550) mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6551) lsl.l %d1, %d0 # extract new lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6552) mov.l %d0, FTEMP_LO(%a0) # save new lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6554) and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6556) mov.b &DENORM, %d0 # return new optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6557) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6559) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6560) # only mantissa bits set are in lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6561) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6562) unnorm_nrm_zero_lrg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6563) sub.w &32, %d1 # adjust shft amt by 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6565) mov.l FTEMP_LO(%a0), %d0 # fetch old lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6566) lsl.l %d1, %d0 # left shift lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6568) mov.l %d0, FTEMP_HI(%a0) # store new hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6569) clr.l FTEMP_LO(%a0) # lo(man) = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6571) and.w &0x8000, FTEMP_EX(%a0) # set exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6573) mov.b &DENORM, %d0 # return new optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6574) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6576) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6577) # whole mantissa is zero so this UNNORM is actually a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6578) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6579) unnorm_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6580) and.w &0x8000, FTEMP_EX(%a0) # force exponent to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6582) mov.b &ZERO, %d0 # fix optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6583) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6585) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6586) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6587) # set_tag_x(): return the optype of the input ext fp number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6588) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6589) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6590) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6591) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6592) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6593) # a0 = pointer to extended precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6594) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6595) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6596) # d0 = value of type tag #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6597) # one of: NORM, INF, QNAN, SNAN, DENORM, UNNORM, ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6598) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6599) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6600) # Simply test the exponent, j-bit, and mantissa values to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6601) # determine the type of operand. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6602) # If it's an unnormalized zero, alter the operand and force it #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6603) # to be a normal zero. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6604) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6605) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6607) global set_tag_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6608) set_tag_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6609) mov.w FTEMP_EX(%a0), %d0 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6610) andi.w &0x7fff, %d0 # strip off sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6611) cmpi.w %d0, &0x7fff # is (EXP == MAX)?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6612) beq.b inf_or_nan_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6613) not_inf_or_nan_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6614) btst &0x7,FTEMP_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6615) beq.b not_norm_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6616) is_norm_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6617) mov.b &NORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6618) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6619) not_norm_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6620) tst.w %d0 # is exponent = 0?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6621) bne.b is_unnorm_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6622) not_unnorm_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6623) tst.l FTEMP_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6624) bne.b is_denorm_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6625) tst.l FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6626) bne.b is_denorm_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6627) is_zero_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6628) mov.b &ZERO, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6629) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6630) is_denorm_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6631) mov.b &DENORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6632) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6633) # must distinguish now "Unnormalized zeroes" which we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6634) # must convert to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6635) is_unnorm_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6636) tst.l FTEMP_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6637) bne.b is_unnorm_reg_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6638) tst.l FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6639) bne.b is_unnorm_reg_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6640) # it's an "unnormalized zero". let's convert it to an actual zero...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6641) andi.w &0x8000,FTEMP_EX(%a0) # clear exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6642) mov.b &ZERO, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6643) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6644) is_unnorm_reg_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6645) mov.b &UNNORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6646) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6647) inf_or_nan_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6648) tst.l FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6649) bne.b is_nan_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6650) mov.l FTEMP_HI(%a0), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6651) and.l &0x7fffffff, %d0 # msb is a don't care!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6652) bne.b is_nan_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6653) is_inf_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6654) mov.b &INF, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6655) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6656) is_nan_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6657) btst &0x6, FTEMP_HI(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6658) beq.b is_snan_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6659) mov.b &QNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6660) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6661) is_snan_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6662) mov.b &SNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6663) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6665) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6666) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6667) # set_tag_d(): return the optype of the input dbl fp number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6668) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6669) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6670) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6671) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6672) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6673) # a0 = points to double precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6674) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6675) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6676) # d0 = value of type tag #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6677) # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6678) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6679) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6680) # Simply test the exponent, j-bit, and mantissa values to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6681) # determine the type of operand. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6682) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6683) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6685) global set_tag_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6686) set_tag_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6687) mov.l FTEMP(%a0), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6688) mov.l %d0, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6690) andi.l &0x7ff00000, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6691) beq.b zero_or_denorm_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6693) cmpi.l %d0, &0x7ff00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6694) beq.b inf_or_nan_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6696) is_norm_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6697) mov.b &NORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6698) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6699) zero_or_denorm_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6700) and.l &0x000fffff, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6701) bne is_denorm_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6702) tst.l 4+FTEMP(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6703) bne is_denorm_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6704) is_zero_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6705) mov.b &ZERO, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6706) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6707) is_denorm_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6708) mov.b &DENORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6709) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6710) inf_or_nan_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6711) and.l &0x000fffff, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6712) bne is_nan_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6713) tst.l 4+FTEMP(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6714) bne is_nan_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6715) is_inf_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6716) mov.b &INF, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6717) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6718) is_nan_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6719) btst &19, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6720) bne is_qnan_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6721) is_snan_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6722) mov.b &SNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6723) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6724) is_qnan_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6725) mov.b &QNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6726) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6728) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6729) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6730) # set_tag_s(): return the optype of the input sgl fp number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6731) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6732) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6733) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6734) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6735) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6736) # a0 = pointer to single precision operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6737) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6738) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6739) # d0 = value of type tag #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6740) # one of: NORM, INF, QNAN, SNAN, DENORM, ZERO #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6741) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6742) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6743) # Simply test the exponent, j-bit, and mantissa values to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6744) # determine the type of operand. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6745) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6746) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6748) global set_tag_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6749) set_tag_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6750) mov.l FTEMP(%a0), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6751) mov.l %d0, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6753) andi.l &0x7f800000, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6754) beq.b zero_or_denorm_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6756) cmpi.l %d0, &0x7f800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6757) beq.b inf_or_nan_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6759) is_norm_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6760) mov.b &NORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6761) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6762) zero_or_denorm_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6763) and.l &0x007fffff, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6764) bne is_denorm_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6765) is_zero_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6766) mov.b &ZERO, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6767) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6768) is_denorm_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6769) mov.b &DENORM, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6770) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6771) inf_or_nan_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6772) and.l &0x007fffff, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6773) bne is_nan_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6774) is_inf_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6775) mov.b &INF, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6776) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6777) is_nan_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6778) btst &22, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6779) bne is_qnan_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6780) is_snan_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6781) mov.b &SNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6782) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6783) is_qnan_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6784) mov.b &QNAN, %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6785) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6787) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6788) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6789) # unf_res(): routine to produce default underflow result of a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6790) # scaled extended precision number; this is used by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6791) # fadd/fdiv/fmul/etc. emulation routines. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6792) # unf_res4(): same as above but for fsglmul/fsgldiv which use #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6793) # single round prec and extended prec mode. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6794) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6795) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6796) # _denorm() - denormalize according to scale factor #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6797) # _round() - round denormalized number according to rnd prec #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6798) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6799) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6800) # a0 = pointer to extended precison operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6801) # d0 = scale factor #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6802) # d1 = rounding precision/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6803) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6804) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6805) # a0 = pointer to default underflow result in extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6806) # d0.b = result FPSR_cc which caller may or may not want to save #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6807) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6808) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6809) # Convert the input operand to "internal format" which means the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6810) # exponent is extended to 16 bits and the sign is stored in the unused #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6811) # portion of the extended precison operand. Denormalize the number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6812) # according to the scale factor passed in d0. Then, round the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6813) # denormalized result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6814) # Set the FPSR_exc bits as appropriate but return the cc bits in #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6815) # d0 in case the caller doesn't want to save them (as is the case for #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6816) # fmove out). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6817) # unf_res4() for fsglmul/fsgldiv forces the denorm to extended #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6818) # precision and the rounding mode to single. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6819) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6820) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6821) global unf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6822) unf_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6823) mov.l %d1, -(%sp) # save rnd prec,mode on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6824)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6825) btst &0x7, FTEMP_EX(%a0) # make "internal" format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6826) sne FTEMP_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6828) mov.w FTEMP_EX(%a0), %d1 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6829) and.w &0x7fff, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6830) sub.w %d0, %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6831) mov.w %d1, FTEMP_EX(%a0) # insert 16 bit exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6833) mov.l %a0, -(%sp) # save operand ptr during calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6835) mov.l 0x4(%sp),%d0 # pass rnd prec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6836) andi.w &0x00c0,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6837) lsr.w &0x4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6838) bsr.l _denorm # denorm result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6840) mov.l (%sp),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6841) mov.w 0x6(%sp),%d1 # load prec:mode into %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6842) andi.w &0xc0,%d1 # extract rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6843) lsr.w &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6844) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6845) mov.w 0x6(%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6846) andi.w &0x30,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6847) lsr.w &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6848) bsr.l _round # round the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6850) mov.l (%sp)+, %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6852) # result is now rounded properly. convert back to normal format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6853) bclr &0x7, FTEMP_EX(%a0) # clear sgn first; may have residue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6854) tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6855) beq.b unf_res_chkifzero # no; result is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6856) bset &0x7, FTEMP_EX(%a0) # set result sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6857) clr.b FTEMP_SGN(%a0) # clear temp sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6859) # the number may have become zero after rounding. set ccodes accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6860) unf_res_chkifzero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6861) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6862) tst.l FTEMP_HI(%a0) # is value now a zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6863) bne.b unf_res_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6864) tst.l FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6865) bne.b unf_res_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6866) # bset &z_bit, FPSR_CC(%a6) # yes; set zero ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6867) bset &z_bit, %d0 # yes; set zero ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6869) unf_res_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6871) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6872) # can inex1 also be set along with unfl and inex2???
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6873) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6874) # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6875) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6876) btst &inex2_bit, FPSR_EXCEPT(%a6) # is INEX2 set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6877) beq.b unf_res_end # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6878) bset &aunfl_bit, FPSR_AEXCEPT(%a6) # yes; set aunfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6880) unf_res_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6881) add.l &0x4, %sp # clear stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6882) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6884) # unf_res() for fsglmul() and fsgldiv().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6885) global unf_res4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6886) unf_res4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6887) mov.l %d1,-(%sp) # save rnd prec,mode on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6889) btst &0x7,FTEMP_EX(%a0) # make "internal" format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6890) sne FTEMP_SGN(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6892) mov.w FTEMP_EX(%a0),%d1 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6893) and.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6894) sub.w %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6895) mov.w %d1,FTEMP_EX(%a0) # insert 16 bit exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6897) mov.l %a0,-(%sp) # save operand ptr during calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6899) clr.l %d0 # force rnd prec = ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6900) bsr.l _denorm # denorm result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6902) mov.l (%sp),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6903) mov.w &s_mode,%d1 # force rnd prec = sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6904) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6905) mov.w 0x6(%sp),%d1 # load rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6906) andi.w &0x30,%d1 # extract rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6907) lsr.w &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6908) bsr.l _round # round the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6910) mov.l (%sp)+,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6912) # result is now rounded properly. convert back to normal format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6913) bclr &0x7,FTEMP_EX(%a0) # clear sgn first; may have residue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6914) tst.b FTEMP_SGN(%a0) # is "internal result" sign set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6915) beq.b unf_res4_chkifzero # no; result is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6916) bset &0x7,FTEMP_EX(%a0) # set result sgn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6917) clr.b FTEMP_SGN(%a0) # clear temp sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6919) # the number may have become zero after rounding. set ccodes accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6920) unf_res4_chkifzero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6921) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6922) tst.l FTEMP_HI(%a0) # is value now a zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6923) bne.b unf_res4_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6924) tst.l FTEMP_LO(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6925) bne.b unf_res4_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6926) # bset &z_bit,FPSR_CC(%a6) # yes; set zero ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6927) bset &z_bit,%d0 # yes; set zero ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6929) unf_res4_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6931) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6932) # can inex1 also be set along with unfl and inex2???
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6933) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6934) # we know that underflow has occurred. aunfl should be set if INEX2 is also set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6935) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6936) btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6937) beq.b unf_res4_end # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6938) bset &aunfl_bit,FPSR_AEXCEPT(%a6) # yes; set aunfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6940) unf_res4_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6941) add.l &0x4,%sp # clear stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6942) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6944) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6945) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6946) # ovf_res(): routine to produce the default overflow result of #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6947) # an overflowing number. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6948) # ovf_res2(): same as above but the rnd mode/prec are passed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6949) # differently. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6950) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6951) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6952) # none #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6953) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6954) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6955) # d1.b = '-1' => (-); '0' => (+) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6956) # ovf_res(): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6957) # d0 = rnd mode/prec #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6958) # ovf_res2(): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6959) # hi(d0) = rnd prec #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6960) # lo(d0) = rnd mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6961) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6962) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6963) # a0 = points to extended precision result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6964) # d0.b = condition code bits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6965) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6966) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6967) # The default overflow result can be determined by the sign of #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6968) # the result and the rounding mode/prec in effect. These bits are #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6969) # concatenated together to create an index into the default result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6970) # table. A pointer to the correct result is returned in a0. The #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6971) # resulting condition codes are returned in d0 in case the caller #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6972) # doesn't want FPSR_cc altered (as is the case for fmove out). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6973) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6974) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6976) global ovf_res
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6977) ovf_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6978) andi.w &0x10,%d1 # keep result sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6979) lsr.b &0x4,%d0 # shift prec/mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6980) or.b %d0,%d1 # concat the two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6981) mov.w %d1,%d0 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6982) lsl.b &0x1,%d1 # multiply d1 by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6983) bra.b ovf_res_load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6985) global ovf_res2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6986) ovf_res2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6987) and.w &0x10, %d1 # keep result sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6988) or.b %d0, %d1 # insert rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6989) swap %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6990) or.b %d0, %d1 # insert rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6991) mov.w %d1, %d0 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6992) lsl.b &0x1, %d1 # shift left by 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6994) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6995) # use the rounding mode, precision, and result sign as in index into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6996) # two tables below to fetch the default result and the result ccodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6997) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6998) ovf_res_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6999) mov.b (tbl_ovfl_cc.b,%pc,%d0.w*1), %d0 # fetch result ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7000) lea (tbl_ovfl_result.b,%pc,%d1.w*8), %a0 # return result ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7002) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7004) tbl_ovfl_cc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7005) byte 0x2, 0x0, 0x0, 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7006) byte 0x2, 0x0, 0x0, 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7007) byte 0x2, 0x0, 0x0, 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7008) byte 0x0, 0x0, 0x0, 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7009) byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7010) byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7011) byte 0x2+0x8, 0x8, 0x2+0x8, 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7013) tbl_ovfl_result:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7014) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7015) long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7016) long 0x7ffe0000,0xffffffff,0xffffffff,0x00000000 # +EXT; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7017) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7019) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7020) long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7021) long 0x407e0000,0xffffff00,0x00000000,0x00000000 # +SGL; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7022) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7024) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7025) long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7026) long 0x43fe0000,0xffffffff,0xfffff800,0x00000000 # +DBL; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7027) long 0x7fff0000,0x00000000,0x00000000,0x00000000 # +INF; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7029) long 0x00000000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7030) long 0x00000000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7031) long 0x00000000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7032) long 0x00000000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7034) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7035) long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7036) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7037) long 0xfffe0000,0xffffffff,0xffffffff,0x00000000 # -EXT; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7039) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7040) long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7041) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7042) long 0xc07e0000,0xffffff00,0x00000000,0x00000000 # -SGL; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7044) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7045) long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7046) long 0xffff0000,0x00000000,0x00000000,0x00000000 # -INF; RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7047) long 0xc3fe0000,0xffffffff,0xfffff800,0x00000000 # -DBL; RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7049) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7050) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7051) # fout(): move from fp register to memory or data register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7052) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7053) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7054) # _round() - needed to create EXOP for sgl/dbl precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7055) # norm() - needed to create EXOP for extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7056) # ovf_res() - create default overflow result for sgl/dbl precision#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7057) # unf_res() - create default underflow result for sgl/dbl prec. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7058) # dst_dbl() - create rounded dbl precision result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7059) # dst_sgl() - create rounded sgl precision result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7060) # fetch_dreg() - fetch dynamic k-factor reg for packed. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7061) # bindec() - convert FP binary number to packed number. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7062) # _mem_write() - write data to memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7063) # _mem_write2() - write data to memory unless supv mode -(a7) exc.#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7064) # _dmem_write_{byte,word,long}() - write data to memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7065) # store_dreg_{b,w,l}() - store data to data register file. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7066) # facc_out_{b,w,l,d,x}() - data access error occurred. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7067) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7068) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7069) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7070) # d0 = round prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7071) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7072) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7073) # fp0 : intermediate underflow or overflow result if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7074) # OVFL/UNFL occurred for a sgl or dbl operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7075) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7076) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7077) # This routine is accessed by many handlers that need to do an #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7078) # opclass three move of an operand out to memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7079) # Decode an fmove out (opclass 3) instruction to determine if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7080) # it's b,w,l,s,d,x, or p in size. b,w,l can be stored to either a data #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7081) # register or memory. The algorithm uses a standard "fmove" to create #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7082) # the rounded result. Also, since exceptions are disabled, this also #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7083) # create the correct OPERR default result if appropriate. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7084) # For sgl or dbl precision, overflow or underflow can occur. If #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7085) # either occurs and is enabled, the EXOP. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7086) # For extended precision, the stacked <ea> must be fixed along #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7087) # w/ the address index register as appropriate w/ _calc_ea_fout(). If #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7088) # the source is a denorm and if underflow is enabled, an EXOP must be #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7089) # created. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7090) # For packed, the k-factor must be fetched from the instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7091) # word or a data register. The <ea> must be fixed as w/ extended #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7092) # precision. Then, bindec() is called to create the appropriate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7093) # packed result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7094) # If at any time an access error is flagged by one of the move- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7095) # to-memory routines, then a special exit must be made so that the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7096) # access error can be handled properly. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7097) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7098) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7100) global fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7101) fout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7102) bfextu EXC_CMDREG(%a6){&3:&3},%d1 # extract dst fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7103) mov.w (tbl_fout.b,%pc,%d1.w*2),%a1 # use as index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7104) jmp (tbl_fout.b,%pc,%a1) # jump to routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7106) swbeg &0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7107) tbl_fout:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7108) short fout_long - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7109) short fout_sgl - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7110) short fout_ext - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7111) short fout_pack - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7112) short fout_word - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7113) short fout_dbl - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7114) short fout_byte - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7115) short fout_pack - tbl_fout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7117) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7118) # fmove.b out ###################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7119) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7121) # Only "Unimplemented Data Type" exceptions enter here. The operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7122) # is either a DENORM or a NORM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7123) fout_byte:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7124) tst.b STAG(%a6) # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7125) bne.b fout_byte_denorm # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7127) fmovm.x SRC(%a0),&0x80 # load value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7129) fout_byte_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7130) fmov.l %d0,%fpcr # insert rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7132) fmov.b %fp0,%d0 # exec move out w/ correct rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7134) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7135) fmov.l %fpsr,%d1 # fetch FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7136) or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7138) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7139) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7140) beq.b fout_byte_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7142) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7143) bsr.l _dmem_write_byte # write byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7145) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7146) bne.l facc_out_b # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7148) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7150) fout_byte_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7151) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7152) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7153) bsr.l store_dreg_b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7154) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7156) fout_byte_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7157) mov.l SRC_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7158) andi.l &0x80000000,%d1 # keep DENORM sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7159) ori.l &0x00800000,%d1 # make smallest sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7160) fmov.s %d1,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7161) bra.b fout_byte_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7163) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7164) # fmove.w out ###################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7165) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7167) # Only "Unimplemented Data Type" exceptions enter here. The operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7168) # is either a DENORM or a NORM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7169) fout_word:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7170) tst.b STAG(%a6) # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7171) bne.b fout_word_denorm # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7173) fmovm.x SRC(%a0),&0x80 # load value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7175) fout_word_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7176) fmov.l %d0,%fpcr # insert rnd prec:mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7178) fmov.w %fp0,%d0 # exec move out w/ correct rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7180) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7181) fmov.l %fpsr,%d1 # fetch FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7182) or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7184) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7185) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7186) beq.b fout_word_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7188) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7189) bsr.l _dmem_write_word # write word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7191) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7192) bne.l facc_out_w # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7194) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7196) fout_word_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7197) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7198) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7199) bsr.l store_dreg_w
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7200) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7202) fout_word_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7203) mov.l SRC_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7204) andi.l &0x80000000,%d1 # keep DENORM sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7205) ori.l &0x00800000,%d1 # make smallest sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7206) fmov.s %d1,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7207) bra.b fout_word_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7209) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7210) # fmove.l out ###################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7211) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7213) # Only "Unimplemented Data Type" exceptions enter here. The operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7214) # is either a DENORM or a NORM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7215) fout_long:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7216) tst.b STAG(%a6) # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7217) bne.b fout_long_denorm # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7219) fmovm.x SRC(%a0),&0x80 # load value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7221) fout_long_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7222) fmov.l %d0,%fpcr # insert rnd prec:mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7224) fmov.l %fp0,%d0 # exec move out w/ correct rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7226) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7227) fmov.l %fpsr,%d1 # fetch FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7228) or.w %d1,2+USER_FPSR(%a6) # save new exc,accrued bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7230) fout_long_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7231) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7232) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7233) beq.b fout_long_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7235) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7236) bsr.l _dmem_write_long # write long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7238) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7239) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7241) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7243) fout_long_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7244) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7245) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7246) bsr.l store_dreg_l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7247) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7249) fout_long_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7250) mov.l SRC_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7251) andi.l &0x80000000,%d1 # keep DENORM sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7252) ori.l &0x00800000,%d1 # make smallest sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7253) fmov.s %d1,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7254) bra.b fout_long_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7256) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7257) # fmove.x out ###################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7258) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7260) # Only "Unimplemented Data Type" exceptions enter here. The operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7261) # is either a DENORM or a NORM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7262) # The DENORM causes an Underflow exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7263) fout_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7265) # we copy the extended precision result to FP_SCR0 so that the reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7266) # 16-bit field gets zeroed. we do this since we promise not to disturb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7267) # what's at SRC(a0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7268) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7269) clr.w 2+FP_SCR0_EX(%a6) # clear reserved field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7270) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7271) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7273) fmovm.x SRC(%a0),&0x80 # return result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7275) bsr.l _calc_ea_fout # fix stacked <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7277) mov.l %a0,%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7278) lea FP_SCR0(%a6),%a0 # pass: src addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7279) mov.l &0xc,%d0 # pass: opsize is 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7281) # we must not yet write the extended precision data to the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7282) # in the pre-decrement case from supervisor mode or else we'll corrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7283) # the stack frame. so, leave it in FP_SRC for now and deal with it later...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7284) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7285) beq.b fout_ext_a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7287) bsr.l _dmem_write # write ext prec number to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7289) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7290) bne.w fout_ext_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7292) tst.b STAG(%a6) # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7293) bne.b fout_ext_denorm # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7294) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7296) # the number is a DENORM. must set the underflow exception bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7297) fout_ext_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7298) bset &unfl_bit,FPSR_EXCEPT(%a6) # set underflow exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7300) mov.b FPCR_ENABLE(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7301) andi.b &0x0a,%d0 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7302) bne.b fout_ext_exc # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7303) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7305) # we don't want to do the write if the exception occurred in supervisor mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7306) # so _mem_write2() handles this for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7307) fout_ext_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7308) bsr.l _mem_write2 # write ext prec number to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7310) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7311) bne.w fout_ext_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7313) tst.b STAG(%a6) # is operand normalized?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7314) bne.b fout_ext_denorm # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7315) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7317) fout_ext_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7318) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7319) bsr.l norm # normalize the mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7320) neg.w %d0 # new exp = -(shft amt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7321) andi.w &0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7322) andi.w &0x8000,FP_SCR0_EX(%a6) # keep only old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7323) or.w %d0,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7324) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7325) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7327) fout_ext_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7328) mov.l EXC_A6(%a6),(%a6) # fix stacked a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7329) bra.l facc_out_x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7331) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7332) # fmove.s out ###########################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7333) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7334) fout_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7335) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7336) ori.b &s_mode*0x10,%d0 # insert sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7337) mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7339) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7340) # operand is a normalized number. first, we check to see if the move out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7341) # would cause either an underflow or overflow. these cases are handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7342) # separately. otherwise, set the FPCR to the proper rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7343) # execute the move.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7344) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7345) mov.w SRC_EX(%a0),%d0 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7346) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7348) cmpi.w %d0,&SGL_HI # will operand overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7349) bgt.w fout_sgl_ovfl # yes; go handle OVFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7350) beq.w fout_sgl_may_ovfl # maybe; go handle possible OVFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7351) cmpi.w %d0,&SGL_LO # will operand underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7352) blt.w fout_sgl_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7354) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7355) # NORMs(in range) can be stored out by a simple "fmov.s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7356) # Unnormalized inputs can come through this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7357) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7358) fout_sgl_exg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7359) fmovm.x SRC(%a0),&0x80 # fetch fop from stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7361) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7362) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7364) fmov.s %fp0,%d0 # store does convert and round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7366) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7367) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7369) or.w %d1,2+USER_FPSR(%a6) # set possible inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7371) fout_sgl_exg_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7372) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7373) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7374) beq.b fout_sgl_exg_write_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7376) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7377) bsr.l _dmem_write_long # write long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7379) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7380) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7382) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7384) fout_sgl_exg_write_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7385) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7386) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7387) bsr.l store_dreg_l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7388) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7390) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7391) # here, we know that the operand would UNFL if moved out to single prec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7392) # so, denorm and round and then use generic store single routine to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7393) # write the value to memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7394) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7395) fout_sgl_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7396) bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7398) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7399) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7400) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7401) mov.l %a0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7403) clr.l %d0 # pass: S.F. = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7405) cmpi.b STAG(%a6),&DENORM # fetch src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7406) bne.b fout_sgl_unfl_cont # let DENORMs fall through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7408) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7409) bsr.l norm # normalize the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7411) fout_sgl_unfl_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7412) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7413) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7414) bsr.l unf_res # calc default underflow result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7416) lea FP_SCR0(%a6),%a0 # pass: ptr to fop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7417) bsr.l dst_sgl # convert to single prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7419) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7420) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7421) beq.b fout_sgl_unfl_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7423) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7424) bsr.l _dmem_write_long # write long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7426) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7427) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7429) bra.b fout_sgl_unfl_chkexc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7431) fout_sgl_unfl_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7432) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7433) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7434) bsr.l store_dreg_l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7436) fout_sgl_unfl_chkexc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7437) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7438) andi.b &0x0a,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7439) bne.w fout_sd_exc_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7440) addq.l &0x4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7441) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7443) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7444) # it's definitely an overflow so call ovf_res to get the correct answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7445) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7446) fout_sgl_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7447) tst.b 3+SRC_HI(%a0) # is result inexact?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7448) bne.b fout_sgl_ovfl_inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7449) tst.l SRC_LO(%a0) # is result inexact?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7450) bne.b fout_sgl_ovfl_inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7451) ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7452) bra.b fout_sgl_ovfl_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7453) fout_sgl_ovfl_inex2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7454) ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7456) fout_sgl_ovfl_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7457) mov.l %a0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7459) # call ovf_res() w/ sgl prec and the correct rnd mode to create the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7460) # overflow result. DON'T save the returned ccodes from ovf_res() since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7461) # fmove out doesn't alter them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7462) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7463) smi %d1 # set if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7464) mov.l L_SCR3(%a6),%d0 # pass: sgl prec,rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7465) bsr.l ovf_res # calc OVFL result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7466) fmovm.x (%a0),&0x80 # load default overflow result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7467) fmov.s %fp0,%d0 # store to single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7469) mov.b 1+EXC_OPWORD(%a6),%d1 # extract dst mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7470) andi.b &0x38,%d1 # is mode == 0? (Dreg dst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7471) beq.b fout_sgl_ovfl_dn # must save to integer regfile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7473) mov.l EXC_EA(%a6),%a0 # stacked <ea> is correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7474) bsr.l _dmem_write_long # write long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7476) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7477) bne.l facc_out_l # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7479) bra.b fout_sgl_ovfl_chkexc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7481) fout_sgl_ovfl_dn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7482) mov.b 1+EXC_OPWORD(%a6),%d1 # extract Dn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7483) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7484) bsr.l store_dreg_l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7486) fout_sgl_ovfl_chkexc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7487) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7488) andi.b &0x0a,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7489) bne.w fout_sd_exc_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7490) addq.l &0x4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7491) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7493) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7494) # move out MAY overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7495) # (1) force the exp to 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7496) # (2) do a move w/ appropriate rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7497) # (3) if exp still equals zero, then insert original exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7498) # for the correct result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7499) # if exp now equals one, then it overflowed so call ovf_res.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7500) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7501) fout_sgl_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7502) mov.w SRC_EX(%a0),%d1 # fetch current sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7503) andi.w &0x8000,%d1 # keep it,clear exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7504) ori.w &0x3fff,%d1 # insert exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7505) mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7506) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7507) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7509) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7511) fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7512) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7514) fabs.x %fp0 # need absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7515) fcmp.b %fp0,&0x2 # did exponent increase?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7516) fblt.w fout_sgl_exg # no; go finish NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7517) bra.w fout_sgl_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7519) ################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7521) fout_sd_exc_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7522) mov.l (%sp)+,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7524) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7525) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7526) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7528) cmpi.b STAG(%a6),&DENORM # was src a DENORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7529) bne.b fout_sd_exc_cont # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7531) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7532) bsr.l norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7533) neg.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7534) andi.w &0x7fff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7535) bfins %d0,FP_SCR0_EX(%a6){&1:&15}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7536) bra.b fout_sd_exc_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7538) fout_sd_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7539) fout_sd_exc_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7540) mov.l (%sp)+,%a0 # restore a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7542) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7543) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7544) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7546) fout_sd_exc_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7547) bclr &0x7,FP_SCR0_EX(%a6) # clear sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7548) sne.b 2+FP_SCR0_EX(%a6) # set internal sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7549) lea FP_SCR0(%a6),%a0 # pass: ptr to DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7551) mov.b 3+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7552) lsr.b &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7553) andi.w &0x0c,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7554) swap %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7555) mov.b 3+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7556) lsr.b &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7557) andi.w &0x03,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7558) clr.l %d0 # pass: zero g,r,s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7559) bsr.l _round # round the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7561) tst.b 2+FP_SCR0_EX(%a6) # is EXOP negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7562) beq.b fout_sd_exc_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7563) bset &0x7,FP_SCR0_EX(%a6) # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7565) fout_sd_exc_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7566) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7567) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7569) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7570) # fmove.d out ###################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7571) #################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7572) fout_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7573) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7574) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7575) mov.l %d0,L_SCR3(%a6) # save rnd prec,mode on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7577) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7578) # operand is a normalized number. first, we check to see if the move out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7579) # would cause either an underflow or overflow. these cases are handled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7580) # separately. otherwise, set the FPCR to the proper rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7581) # execute the move.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7582) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7583) mov.w SRC_EX(%a0),%d0 # extract exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7584) andi.w &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7586) cmpi.w %d0,&DBL_HI # will operand overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7587) bgt.w fout_dbl_ovfl # yes; go handle OVFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7588) beq.w fout_dbl_may_ovfl # maybe; go handle possible OVFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7589) cmpi.w %d0,&DBL_LO # will operand underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7590) blt.w fout_dbl_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7592) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7593) # NORMs(in range) can be stored out by a simple "fmov.d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7594) # Unnormalized inputs can come through this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7595) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7596) fout_dbl_exg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7597) fmovm.x SRC(%a0),&0x80 # fetch fop from stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7599) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7600) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7602) fmov.d %fp0,L_SCR1(%a6) # store does convert and round
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7604) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7605) fmov.l %fpsr,%d0 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7607) or.w %d0,2+USER_FPSR(%a6) # set possible inex2/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7609) mov.l EXC_EA(%a6),%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7610) lea L_SCR1(%a6),%a0 # pass: src addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7611) movq.l &0x8,%d0 # pass: opsize is 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7612) bsr.l _dmem_write # store dbl fop to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7614) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7615) bne.l facc_out_d # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7617) rts # no; so we're finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7619) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7620) # here, we know that the operand would UNFL if moved out to double prec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7621) # so, denorm and round and then use generic store double routine to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7622) # write the value to memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7623) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7624) fout_dbl_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7625) bset &unfl_bit,FPSR_EXCEPT(%a6) # set UNFL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7627) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7628) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7629) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7630) mov.l %a0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7632) clr.l %d0 # pass: S.F. = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7634) cmpi.b STAG(%a6),&DENORM # fetch src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7635) bne.b fout_dbl_unfl_cont # let DENORMs fall through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7637) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7638) bsr.l norm # normalize the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7640) fout_dbl_unfl_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7641) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7642) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7643) bsr.l unf_res # calc default underflow result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7645) lea FP_SCR0(%a6),%a0 # pass: ptr to fop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7646) bsr.l dst_dbl # convert to single prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7647) mov.l %d0,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7648) mov.l %d1,L_SCR2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7650) mov.l EXC_EA(%a6),%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7651) lea L_SCR1(%a6),%a0 # pass: src addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7652) movq.l &0x8,%d0 # pass: opsize is 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7653) bsr.l _dmem_write # store dbl fop to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7655) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7656) bne.l facc_out_d # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7658) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7659) andi.b &0x0a,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7660) bne.w fout_sd_exc_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7661) addq.l &0x4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7662) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7664) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7665) # it's definitely an overflow so call ovf_res to get the correct answer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7666) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7667) fout_dbl_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7668) mov.w 2+SRC_LO(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7669) andi.w &0x7ff,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7670) bne.b fout_dbl_ovfl_inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7672) ori.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7673) bra.b fout_dbl_ovfl_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7674) fout_dbl_ovfl_inex2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7675) ori.w &ovfinx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex/inex2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7677) fout_dbl_ovfl_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7678) mov.l %a0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7680) # call ovf_res() w/ dbl prec and the correct rnd mode to create the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7681) # overflow result. DON'T save the returned ccodes from ovf_res() since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7682) # fmove out doesn't alter them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7683) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7684) smi %d1 # set if so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7685) mov.l L_SCR3(%a6),%d0 # pass: dbl prec,rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7686) bsr.l ovf_res # calc OVFL result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7687) fmovm.x (%a0),&0x80 # load default overflow result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7688) fmov.d %fp0,L_SCR1(%a6) # store to double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7690) mov.l EXC_EA(%a6),%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7691) lea L_SCR1(%a6),%a0 # pass: src addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7692) movq.l &0x8,%d0 # pass: opsize is 8 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7693) bsr.l _dmem_write # store dbl fop to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7695) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7696) bne.l facc_out_d # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7698) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7699) andi.b &0x0a,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7700) bne.w fout_sd_exc_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7701) addq.l &0x4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7702) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7704) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7705) # move out MAY overflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7706) # (1) force the exp to 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7707) # (2) do a move w/ appropriate rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7708) # (3) if exp still equals zero, then insert original exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7709) # for the correct result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7710) # if exp now equals one, then it overflowed so call ovf_res.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7711) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7712) fout_dbl_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7713) mov.w SRC_EX(%a0),%d1 # fetch current sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7714) andi.w &0x8000,%d1 # keep it,clear exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7715) ori.w &0x3fff,%d1 # insert exp = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7716) mov.w %d1,FP_SCR0_EX(%a6) # insert scaled exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7717) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6) # copy hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7718) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6) # copy lo(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7720) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7722) fmov.x FP_SCR0(%a6),%fp0 # force fop to be rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7723) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7725) fabs.x %fp0 # need absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7726) fcmp.b %fp0,&0x2 # did exponent increase?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7727) fblt.w fout_dbl_exg # no; go finish NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7728) bra.w fout_dbl_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7730) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7731) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7732) # dst_dbl(): create double precision value from extended prec. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7733) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7734) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7735) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7736) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7737) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7738) # a0 = pointer to source operand in extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7739) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7740) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7741) # d0 = hi(double precision result) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7742) # d1 = lo(double precision result) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7743) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7744) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7745) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7746) # Changes extended precision to double precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7747) # Note: no attempt is made to round the extended value to double. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7748) # dbl_sign = ext_sign #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7749) # dbl_exp = ext_exp - $3fff(ext bias) + $7ff(dbl bias) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7750) # get rid of ext integer bit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7751) # dbl_mant = ext_mant{62:12} #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7752) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7753) # --------------- --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7754) # extended -> |s| exp | |1| ms mant | | ls mant | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7755) # --------------- --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7756) # 95 64 63 62 32 31 11 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7757) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7758) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7759) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7760) # v v #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7761) # --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7762) # double -> |s|exp| mant | | mant | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7763) # --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7764) # 63 51 32 31 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7765) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7766) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7768) dst_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7769) clr.l %d0 # clear d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7770) mov.w FTEMP_EX(%a0),%d0 # get exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7771) subi.w &EXT_BIAS,%d0 # subtract extended precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7772) addi.w &DBL_BIAS,%d0 # add double precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7773) tst.b FTEMP_HI(%a0) # is number a denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7774) bmi.b dst_get_dupper # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7775) subq.w &0x1,%d0 # yes; denorm bias = DBL_BIAS - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7776) dst_get_dupper:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7777) swap %d0 # d0 now in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7778) lsl.l &0x4,%d0 # d0 in proper place for dbl prec exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7779) tst.b FTEMP_EX(%a0) # test sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7780) bpl.b dst_get_dman # if positive, go process mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7781) bset &0x1f,%d0 # if negative, set sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7782) dst_get_dman:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7783) mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7784) bfextu %d1{&1:&20},%d1 # get upper 20 bits of ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7785) or.l %d1,%d0 # put these bits in ms word of double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7786) mov.l %d0,L_SCR1(%a6) # put the new exp back on the stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7787) mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7788) mov.l &21,%d0 # load shift count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7789) lsl.l %d0,%d1 # put lower 11 bits in upper bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7790) mov.l %d1,L_SCR2(%a6) # build lower lword in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7791) mov.l FTEMP_LO(%a0),%d1 # get ls mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7792) bfextu %d1{&0:&21},%d0 # get ls 21 bits of double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7793) mov.l L_SCR2(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7794) or.l %d0,%d1 # put them in double result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7795) mov.l L_SCR1(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7796) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7798) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7799) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7800) # dst_sgl(): create single precision value from extended prec #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7801) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7802) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7803) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7804) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7805) # a0 = pointer to source operand in extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7806) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7807) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7808) # d0 = single precision result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7809) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7810) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7811) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7812) # Changes extended precision to single precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7813) # sgl_sign = ext_sign #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7814) # sgl_exp = ext_exp - $3fff(ext bias) + $7f(sgl bias) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7815) # get rid of ext integer bit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7816) # sgl_mant = ext_mant{62:12} #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7817) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7818) # --------------- --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7819) # extended -> |s| exp | |1| ms mant | | ls mant | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7820) # --------------- --------------- --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7821) # 95 64 63 62 40 32 31 12 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7822) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7823) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7824) # | | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7825) # v v #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7826) # --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7827) # single -> |s|exp| mant | #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7828) # --------------- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7829) # 31 22 0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7830) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7831) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7833) dst_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7834) clr.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7835) mov.w FTEMP_EX(%a0),%d0 # get exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7836) subi.w &EXT_BIAS,%d0 # subtract extended precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7837) addi.w &SGL_BIAS,%d0 # add single precision bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7838) tst.b FTEMP_HI(%a0) # is number a denorm?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7839) bmi.b dst_get_supper # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7840) subq.w &0x1,%d0 # yes; denorm bias = SGL_BIAS - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7841) dst_get_supper:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7842) swap %d0 # put exp in upper word of d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7843) lsl.l &0x7,%d0 # shift it into single exp bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7844) tst.b FTEMP_EX(%a0) # test sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7845) bpl.b dst_get_sman # if positive, continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7846) bset &0x1f,%d0 # if negative, put in sign first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7847) dst_get_sman:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7848) mov.l FTEMP_HI(%a0),%d1 # get ms mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7849) andi.l &0x7fffff00,%d1 # get upper 23 bits of ms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7850) lsr.l &0x8,%d1 # and put them flush right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7851) or.l %d1,%d0 # put these bits in ms word of single
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7852) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7854) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7855) fout_pack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7856) bsr.l _calc_ea_fout # fetch the <ea>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7857) mov.l %a0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7859) mov.b STAG(%a6),%d0 # fetch input type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7860) bne.w fout_pack_not_norm # input is not NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7862) fout_pack_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7863) btst &0x4,EXC_CMDREG(%a6) # static or dynamic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7864) beq.b fout_pack_s # static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7866) fout_pack_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7867) mov.b 1+EXC_CMDREG(%a6),%d1 # fetch dynamic reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7868) lsr.b &0x4,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7869) andi.w &0x7,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7871) bsr.l fetch_dreg # fetch Dn w/ k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7873) bra.b fout_pack_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7874) fout_pack_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7875) mov.b 1+EXC_CMDREG(%a6),%d0 # fetch static field
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7877) fout_pack_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7878) bfexts %d0{&25:&7},%d0 # extract k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7879) mov.l %d0,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7881) lea FP_SRC(%a6),%a0 # pass: ptr to input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7883) # bindec is currently scrambling FP_SRC for denorm inputs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7884) # we'll have to change this, but for now, tough luck!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7885) bsr.l bindec # convert xprec to packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7887) # andi.l &0xcfff000f,FP_SCR0(%a6) # clear unused fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7888) andi.l &0xcffff00f,FP_SCR0(%a6) # clear unused fields
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7890) mov.l (%sp)+,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7892) tst.b 3+FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7893) bne.b fout_pack_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7894) tst.l FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7895) bne.b fout_pack_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7896) tst.l FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7897) bne.b fout_pack_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7899) # add the extra condition that only if the k-factor was zero, too, should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7900) # we zero the exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7901) tst.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7902) bne.b fout_pack_set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7903) # "mantissa" is all zero which means that the answer is zero. but, the '040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7904) # algorithm allows the exponent to be non-zero. the 881/2 do not. Therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7905) # if the mantissa is zero, I will zero the exponent, too.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7906) # the question now is whether the exponents sign bit is allowed to be non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7907) # for a zero, also...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7908) andi.w &0xf000,FP_SCR0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7910) fout_pack_set:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7912) lea FP_SCR0(%a6),%a0 # pass: src addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7914) fout_pack_write:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7915) mov.l (%sp)+,%a1 # pass: dst addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7916) mov.l &0xc,%d0 # pass: opsize is 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7918) cmpi.b SPCOND_FLG(%a6),&mda7_flg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7919) beq.b fout_pack_a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7921) bsr.l _dmem_write # write ext prec number to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7923) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7924) bne.w fout_ext_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7926) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7928) # we don't want to do the write if the exception occurred in supervisor mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7929) # so _mem_write2() handles this for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7930) fout_pack_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7931) bsr.l _mem_write2 # write ext prec number to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7933) tst.l %d1 # did dstore fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7934) bne.w fout_ext_err # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7936) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7938) fout_pack_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7939) cmpi.b %d0,&DENORM # is it a DENORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7940) beq.w fout_pack_norm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7941) lea FP_SRC(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7942) clr.w 2+FP_SRC_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7943) cmpi.b %d0,&SNAN # is it an SNAN?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7944) beq.b fout_pack_snan # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7945) bra.b fout_pack_write # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7947) fout_pack_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7948) ori.w &snaniop2_mask,FPSR_EXCEPT(%a6) # set SNAN/AIOP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7949) bset &0x6,FP_SRC_HI(%a6) # set snan bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7950) bra.b fout_pack_write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7952) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7953) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7954) # fmul(): emulates the fmul instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7955) # fsmul(): emulates the fsmul instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7956) # fdmul(): emulates the fdmul instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7957) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7958) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7959) # scale_to_zero_src() - scale src exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7960) # scale_to_zero_dst() - scale dst exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7961) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7962) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7963) # res_qnan() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7964) # res_snan() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7965) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7966) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7967) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7968) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7969) # d0 rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7970) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7971) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7972) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7973) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7974) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7975) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7976) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7977) # norms/denorms into ext/sgl/dbl precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7978) # For norms/denorms, scale the exponents such that a multiply #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7979) # instruction won't cause an exception. Use the regular fmul to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7980) # compute a result. Check if the regular operands would have taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7981) # an exception. If so, return the default overflow/underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7982) # and return the EXOP if exceptions are enabled. Else, scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7983) # result operand to the proper exponent. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7984) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7985) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7987) align 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7988) tbl_fmul_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7989) long 0x3fff - 0x7ffe # ext_max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7990) long 0x3fff - 0x407e # sgl_max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7991) long 0x3fff - 0x43fe # dbl_max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7992) tbl_fmul_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7993) long 0x3fff + 0x0001 # ext_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7994) long 0x3fff - 0x3f80 # sgl_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7995) long 0x3fff - 0x3c00 # dbl_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7997) global fsmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7998) fsmul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7999) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8000) ori.b &s_mode*0x10,%d0 # insert sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8001) bra.b fmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8003) global fdmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8004) fdmul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8005) andi.b &0x30,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8006) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8008) global fmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8009) fmul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8010) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8012) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8013) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8014) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8015) or.b STAG(%a6),%d1 # combine src tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8016) bne.w fmul_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8018) fmul_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8019) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8020) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8021) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8023) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8024) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8025) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8027) bsr.l scale_to_zero_src # scale src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8028) mov.l %d0,-(%sp) # save scale factor 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8030) bsr.l scale_to_zero_dst # scale dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8032) add.l %d0,(%sp) # SCALE_FACTOR = scale1 + scale2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8034) mov.w 2+L_SCR3(%a6),%d1 # fetch precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8035) lsr.b &0x6,%d1 # shift to lo bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8036) mov.l (%sp)+,%d0 # load S.F.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8037) cmp.l %d0,(tbl_fmul_ovfl.w,%pc,%d1.w*4) # would result ovfl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8038) beq.w fmul_may_ovfl # result may rnd to overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8039) blt.w fmul_ovfl # result will overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8041) cmp.l %d0,(tbl_fmul_unfl.w,%pc,%d1.w*4) # would result unfl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8042) beq.w fmul_may_unfl # result may rnd to no unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8043) bgt.w fmul_unfl # result will underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8045) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8046) # NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8047) # - the result of the multiply operation will neither overflow nor underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8048) # - do the multiply to the proper precision and rounding mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8049) # - scale the result exponent using the scale factor. if both operands were
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8050) # normalized then we really don't need to go through this scaling. but for now,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8051) # this will do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8052) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8053) fmul_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8054) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8056) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8057) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8059) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8061) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8062) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8064) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8066) fmul_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8067) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8068) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8069) mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8070) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8071) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8072) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8073) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8074) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8075) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8076) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8077) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8078) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8080) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8081) # OVERFLOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8082) # - the result of the multiply operation is an overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8083) # - do the multiply to the proper precision and rounding mode in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8084) # set the inexact bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8085) # - calculate the default result and return it in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8086) # - if overflow or inexact is enabled, we need a multiply result rounded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8087) # extended precision. if the original operation was extended, then we have this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8088) # result. if the original operation was single or double, we have to do another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8089) # multiply using extended precision and the correct rounding mode. the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8090) # of this operation then has its exponent scaled by -0x6000 to create the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8091) # exceptional operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8092) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8093) fmul_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8094) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8096) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8097) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8099) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8101) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8102) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8104) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8106) # save setting this until now because this is where fmul_may_ovfl may jump in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8107) fmul_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8108) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8110) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8111) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8112) bne.b fmul_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8114) # calculate the default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8115) fmul_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8116) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8117) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8118) mov.l L_SCR3(%a6),%d0 # pass rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8119) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8120) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8121) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8122) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8124) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8125) # OVFL is enabled; Create EXOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8126) # - if precision is extended, then we have the EXOP. simply bias the exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8127) # with an extra -0x6000. if the precision is single or double, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8128) # calculate a result rounded to extended precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8129) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8130) fmul_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8131) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8132) andi.b &0xc0,%d1 # test the rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8133) bne.b fmul_ovfl_ena_sd # it's sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8135) fmul_ovfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8136) fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8138) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8139) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8140) mov.w %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8141) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8142) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8143) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8144) andi.w &0x7fff,%d1 # clear sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8145) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8146) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8147) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8148) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8149) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8150) bra.b fmul_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8152) fmul_ovfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8153) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8155) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8156) andi.b &0x30,%d1 # keep rnd mode only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8157) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8159) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8161) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8162) bra.b fmul_ovfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8164) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8165) # may OVERFLOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8166) # - the result of the multiply operation MAY overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8167) # - do the multiply to the proper precision and rounding mode in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8168) # set the inexact bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8169) # - calculate the default result and return it in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8170) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8171) fmul_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8172) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8174) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8175) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8177) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8179) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8180) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8182) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8184) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8185) fcmp.b %fp1,&0x2 # is |result| >= 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8186) fbge.w fmul_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8188) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8189) bra.w fmul_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8191) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8192) # UNDERFLOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8193) # - the result of the multiply operation is an underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8194) # - do the multiply to the proper precision and rounding mode in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8195) # set the inexact bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8196) # - calculate the default result and return it in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8197) # - if overflow or inexact is enabled, we need a multiply result rounded to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8198) # extended precision. if the original operation was extended, then we have this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8199) # result. if the original operation was single or double, we have to do another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8200) # multiply using extended precision and the correct rounding mode. the result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8201) # of this operation then has its exponent scaled by -0x6000 to create the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8202) # exceptional operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8203) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8204) fmul_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8205) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8207) # for fun, let's use only extended precision, round to zero. then, let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8208) # the unf_res() routine figure out all the rest.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8209) # will we get the correct answer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8210) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8212) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8213) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8215) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8217) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8218) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8220) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8222) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8223) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8224) bne.b fmul_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8226) fmul_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8227) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8229) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8230) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8231) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8232) or.b %d0,FPSR_CC(%a6) # unf_res2 may have set 'Z'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8233) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8234) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8236) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8237) # UNFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8238) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8239) fmul_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8240) fmovm.x FP_SCR1(%a6),&0x40 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8242) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8243) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8244) bne.b fmul_unfl_ena_sd # no, sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8246) # if the rnd mode is anything but RZ, then we have to re-do the above
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8247) # multiplication because we used RZ for all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8248) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8250) fmul_unfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8251) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8253) fmul.x FP_SCR0(%a6),%fp1 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8255) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8257) fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8258) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8259) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8260) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8261) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8262) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8263) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8264) addi.l &0x6000,%d1 # add bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8265) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8266) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8267) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8268) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8269) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8270) bra.w fmul_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8272) fmul_unfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8273) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8274) andi.b &0x30,%d1 # use only rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8275) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8277) bra.b fmul_unfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8279) # MAY UNDERFLOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8280) # -use the correct rounding mode and precision. this code favors operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8281) # that do not underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8282) fmul_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8283) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8285) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8286) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8288) fmul.x FP_SCR0(%a6),%fp0 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8290) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8291) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8293) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8295) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8296) fcmp.b %fp1,&0x2 # is |result| > 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8297) fbgt.w fmul_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8298) fblt.w fmul_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8300) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8301) # we still don't know if underflow occurred. result is ~ equal to 2. but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8302) # we don't know if the result was an underflow that rounded up to a 2 or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8303) # a normalized number that rounded down to a 2. so, redo the entire operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8304) # using RZ as the rounding mode to see what the pre-rounded result is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8305) # this case should be relatively rare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8306) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8307) fmovm.x FP_SCR1(%a6),&0x40 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8309) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8310) andi.b &0xc0,%d1 # keep rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8311) ori.b &rz_mode*0x10,%d1 # insert RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8313) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8314) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8316) fmul.x FP_SCR0(%a6),%fp1 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8318) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8319) fabs.x %fp1 # make absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8320) fcmp.b %fp1,&0x2 # is |result| < 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8321) fbge.w fmul_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8322) bra.w fmul_unfl # yes, underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8324) ################################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8326) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8327) # Multiply: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8328) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8329) fmul_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8330) mov.w (tbl_fmul_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8331) jmp (tbl_fmul_op.b,%pc,%d1.w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8333) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8334) tbl_fmul_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8335) short fmul_norm - tbl_fmul_op # NORM x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8336) short fmul_zero - tbl_fmul_op # NORM x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8337) short fmul_inf_src - tbl_fmul_op # NORM x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8338) short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8339) short fmul_norm - tbl_fmul_op # NORM x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8340) short fmul_res_snan - tbl_fmul_op # NORM x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8341) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8342) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8344) short fmul_zero - tbl_fmul_op # ZERO x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8345) short fmul_zero - tbl_fmul_op # ZERO x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8346) short fmul_res_operr - tbl_fmul_op # ZERO x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8347) short fmul_res_qnan - tbl_fmul_op # ZERO x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8348) short fmul_zero - tbl_fmul_op # ZERO x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8349) short fmul_res_snan - tbl_fmul_op # ZERO x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8350) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8351) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8353) short fmul_inf_dst - tbl_fmul_op # INF x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8354) short fmul_res_operr - tbl_fmul_op # INF x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8355) short fmul_inf_dst - tbl_fmul_op # INF x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8356) short fmul_res_qnan - tbl_fmul_op # INF x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8357) short fmul_inf_dst - tbl_fmul_op # INF x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8358) short fmul_res_snan - tbl_fmul_op # INF x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8359) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8360) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8362) short fmul_res_qnan - tbl_fmul_op # QNAN x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8363) short fmul_res_qnan - tbl_fmul_op # QNAN x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8364) short fmul_res_qnan - tbl_fmul_op # QNAN x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8365) short fmul_res_qnan - tbl_fmul_op # QNAN x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8366) short fmul_res_qnan - tbl_fmul_op # QNAN x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8367) short fmul_res_snan - tbl_fmul_op # QNAN x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8368) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8369) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8371) short fmul_norm - tbl_fmul_op # NORM x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8372) short fmul_zero - tbl_fmul_op # NORM x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8373) short fmul_inf_src - tbl_fmul_op # NORM x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8374) short fmul_res_qnan - tbl_fmul_op # NORM x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8375) short fmul_norm - tbl_fmul_op # NORM x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8376) short fmul_res_snan - tbl_fmul_op # NORM x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8377) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8378) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8380) short fmul_res_snan - tbl_fmul_op # SNAN x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8381) short fmul_res_snan - tbl_fmul_op # SNAN x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8382) short fmul_res_snan - tbl_fmul_op # SNAN x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8383) short fmul_res_snan - tbl_fmul_op # SNAN x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8384) short fmul_res_snan - tbl_fmul_op # SNAN x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8385) short fmul_res_snan - tbl_fmul_op # SNAN x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8386) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8387) short tbl_fmul_op - tbl_fmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8389) fmul_res_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8390) bra.l res_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8391) fmul_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8392) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8393) fmul_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8394) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8396) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8397) # Multiply: (Zero x Zero) || (Zero x norm) || (Zero x denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8398) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8399) global fmul_zero # global for fsglmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8400) fmul_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8401) mov.b SRC_EX(%a0),%d0 # exclusive or the signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8402) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8403) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8404) bpl.b fmul_zero_p # result ZERO is pos.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8405) fmul_zero_n:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8406) fmov.s &0x80000000,%fp0 # load -ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8407) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8408) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8409) fmul_zero_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8410) fmov.s &0x00000000,%fp0 # load +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8411) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8412) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8414) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8415) # Multiply: (inf x inf) || (inf x norm) || (inf x denorm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8416) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8417) # Note: The j-bit for an infinity is a don't-care. However, to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8418) # strictly compatible w/ the 68881/882, we make sure to return an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8419) # INF w/ the j-bit set if the input INF j-bit was set. Destination
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8420) # INFs take priority.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8421) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8422) global fmul_inf_dst # global for fsglmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8423) fmul_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8424) fmovm.x DST(%a1),&0x80 # return INF result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8425) mov.b SRC_EX(%a0),%d0 # exclusive or the signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8426) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8427) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8428) bpl.b fmul_inf_dst_p # result INF is pos.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8429) fmul_inf_dst_n:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8430) fabs.x %fp0 # clear result sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8431) fneg.x %fp0 # set result sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8432) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8433) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8434) fmul_inf_dst_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8435) fabs.x %fp0 # clear result sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8436) mov.b &inf_bmask,FPSR_CC(%a6) # set INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8437) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8439) global fmul_inf_src # global for fsglmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8440) fmul_inf_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8441) fmovm.x SRC(%a0),&0x80 # return INF result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8442) mov.b SRC_EX(%a0),%d0 # exclusive or the signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8443) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8444) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8445) bpl.b fmul_inf_dst_p # result INF is pos.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8446) bra.b fmul_inf_dst_n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8448) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8449) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8450) # fin(): emulates the fmove instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8451) # fsin(): emulates the fsmove instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8452) # fdin(): emulates the fdmove instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8453) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8454) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8455) # norm() - normalize mantissa for EXOP on denorm #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8456) # scale_to_zero_src() - scale src exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8457) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8458) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8459) # res_qnan_1op() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8460) # res_snan_1op() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8461) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8462) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8463) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8464) # d0 = round prec/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8465) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8466) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8467) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8468) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8469) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8470) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8471) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8472) # norms into extended, single, and double precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8473) # Norms can be emulated w/ a regular fmove instruction. For #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8474) # sgl/dbl, must scale exponent and perform an "fmove". Check to see #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8475) # if the result would have overflowed/underflowed. If so, use unf_res() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8476) # or ovf_res() to return the default result. Also return EXOP if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8477) # exception is enabled. If no exception, return the default result. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8478) # Unnorms don't pass through here. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8479) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8480) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8482) global fsin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8483) fsin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8484) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8485) ori.b &s_mode*0x10,%d0 # insert sgl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8486) bra.b fin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8488) global fdin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8489) fdin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8490) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8491) ori.b &d_mode*0x10,%d0 # insert dbl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8493) global fin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8494) fin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8495) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8497) mov.b STAG(%a6),%d1 # fetch src optype tag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8498) bne.w fin_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8500) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8501) # FP MOVE IN: NORMs and DENORMs ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8502) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8503) fin_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8504) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8505) bne.w fin_not_ext # no, so go handle dbl or sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8507) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8508) # precision selected is extended. so...we cannot get an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8509) # or overflow because of rounding to the correct precision. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8510) # skip the scaling and unscaling...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8511) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8512) tst.b SRC_EX(%a0) # is the operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8513) bpl.b fin_norm_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8514) bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8515) fin_norm_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8516) fmovm.x SRC(%a0),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8517) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8519) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8520) # for an extended precision DENORM, the UNFL exception bit is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8521) # the accrued bit is NOT set in this instance(no inexactness!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8522) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8523) fin_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8524) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8525) bne.w fin_not_ext # no, so go handle dbl or sgl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8527) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8528) tst.b SRC_EX(%a0) # is the operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8529) bpl.b fin_denorm_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8530) bset &neg_bit,FPSR_CC(%a6) # yes, so set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8531) fin_denorm_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8532) fmovm.x SRC(%a0),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8533) btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8534) bne.b fin_denorm_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8535) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8537) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8538) # the input is an extended DENORM and underflow is enabled in the FPCR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8539) # normalize the mantissa and add the bias of 0x6000 to the resulting negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8540) # exponent and insert back into the operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8541) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8542) fin_denorm_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8543) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8544) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8545) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8546) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8547) bsr.l norm # normalize result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8548) neg.w %d0 # new exponent = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8549) addi.w &0x6000,%d0 # add new bias to exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8550) mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8551) andi.w &0x8000,%d1 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8552) andi.w &0x7fff,%d0 # clear sign position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8553) or.w %d1,%d0 # concat new exo,old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8554) mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8555) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8556) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8558) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8559) # operand is to be rounded to single or double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8560) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8561) fin_not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8562) cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8563) bne.b fin_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8565) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8566) # operand is to be rounded to single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8567) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8568) fin_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8569) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8570) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8571) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8572) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8574) cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8575) bge.w fin_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8576) cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8577) beq.w fin_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8578) blt.w fin_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8580) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8581) # operand will NOT overflow or underflow when moved into the fp reg file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8582) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8583) fin_sd_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8584) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8585) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8587) fmov.x FP_SCR0(%a6),%fp0 # perform move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8589) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8590) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8592) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8594) fin_sd_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8595) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8596) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8597) mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8598) mov.w %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8599) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8600) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8601) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8602) or.w %d1,%d2 # concat old sign,new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8603) mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8604) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8605) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8606) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8608) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8609) # operand is to be rounded to double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8610) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8611) fin_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8612) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8613) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8614) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8615) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8617) cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8618) bge.w fin_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8619) cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8620) beq.w fin_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8621) blt.w fin_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8622) bra.w fin_sd_normal # no; ho handle normalized op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8624) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8625) # operand WILL underflow when moved in to the fp register file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8626) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8627) fin_sd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8628) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8630) tst.b FP_SCR0_EX(%a6) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8631) bpl.b fin_sd_unfl_tst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8632) bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8634) # if underflow or inexact is enabled, then go calculate the EXOP first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8635) fin_sd_unfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8636) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8637) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8638) bne.b fin_sd_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8640) fin_sd_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8641) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8642) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8643) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8644) or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8645) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8646) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8648) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8649) # operand will underflow AND underflow or inexact is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8650) # Therefore, we must return the result rounded to extended precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8651) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8652) fin_sd_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8653) mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8654) mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8655) mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8657) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8658) mov.w %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8659) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8660) sub.l %d0,%d1 # subtract scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8661) andi.w &0x8000,%d2 # extract old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8662) addi.l &0x6000,%d1 # add new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8663) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8664) or.w %d1,%d2 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8665) mov.w %d2,FP_SCR1_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8666) fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8667) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8668) bra.b fin_sd_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8670) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8671) # operand WILL overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8672) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8673) fin_sd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8674) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8675) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8677) fmov.x FP_SCR0(%a6),%fp0 # perform move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8679) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8680) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8682) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8684) fin_sd_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8685) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8687) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8688) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8689) bne.b fin_sd_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8691) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8692) # OVFL is not enabled; therefore, we must create the default result by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8693) # calling ovf_res().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8694) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8695) fin_sd_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8696) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8697) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8698) mov.l L_SCR3(%a6),%d0 # pass: prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8699) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8700) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8701) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8702) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8704) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8705) # OVFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8706) # the INEX2 bit has already been updated by the round to the correct precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8707) # now, round to extended(and don't alter the FPSR).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8708) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8709) fin_sd_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8710) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8711) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8712) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8713) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8714) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8715) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8716) sub.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8717) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8718) or.w %d2,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8719) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8720) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8721) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8722) bra.b fin_sd_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8724) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8725) # the move in MAY overflow. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8726) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8727) fin_sd_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8728) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8729) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8731) fmov.x FP_SCR0(%a6),%fp0 # perform the move
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8733) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8734) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8736) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8738) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8739) fcmp.b %fp1,&0x2 # is |result| >= 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8740) fbge.w fin_sd_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8742) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8743) bra.w fin_sd_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8745) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8747) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8748) # operand is not a NORM: check its optype and branch accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8749) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8750) fin_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8751) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8752) beq.w fin_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8753) cmpi.b %d1,&SNAN # weed out SNANs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8754) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8755) cmpi.b %d1,&QNAN # weed out QNANs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8756) beq.l res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8758) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8759) # do the fmove in; at this point, only possible ops are ZERO and INF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8760) # use fmov to determine ccodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8761) # prec:mode should be zero at this point but it won't affect answer anyways.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8762) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8763) fmov.x SRC(%a0),%fp0 # do fmove in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8764) fmov.l %fpsr,%d0 # no exceptions possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8765) rol.l &0x8,%d0 # put ccodes in lo byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8766) mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8767) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8769) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8770) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8771) # fdiv(): emulates the fdiv instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8772) # fsdiv(): emulates the fsdiv instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8773) # fddiv(): emulates the fddiv instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8774) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8775) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8776) # scale_to_zero_src() - scale src exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8777) # scale_to_zero_dst() - scale dst exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8778) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8779) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8780) # res_qnan() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8781) # res_snan() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8782) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8783) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8784) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8785) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8786) # d0 rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8787) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8788) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8789) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8790) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8791) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8792) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8793) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8794) # norms/denorms into ext/sgl/dbl precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8795) # For norms/denorms, scale the exponents such that a divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8796) # instruction won't cause an exception. Use the regular fdiv to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8797) # compute a result. Check if the regular operands would have taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8798) # an exception. If so, return the default overflow/underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8799) # and return the EXOP if exceptions are enabled. Else, scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8800) # result operand to the proper exponent. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8801) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8802) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8804) align 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8805) tbl_fdiv_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8806) long 0x3fff - 0x0000 # ext_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8807) long 0x3fff - 0x3f81 # sgl_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8808) long 0x3fff - 0x3c01 # dbl_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8810) tbl_fdiv_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8811) long 0x3fff - 0x7ffe # ext overflow exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8812) long 0x3fff - 0x407e # sgl overflow exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8813) long 0x3fff - 0x43fe # dbl overflow exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8815) global fsdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8816) fsdiv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8817) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8818) ori.b &s_mode*0x10,%d0 # insert sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8819) bra.b fdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8821) global fddiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8822) fddiv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8823) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8824) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8826) global fdiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8827) fdiv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8828) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8830) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8831) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8832) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8833) or.b STAG(%a6),%d1 # combine src tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8835) bne.w fdiv_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8837) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8838) # DIVIDE: NORMs and DENORMs ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8839) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8840) fdiv_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8841) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8842) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8843) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8845) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8846) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8847) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8849) bsr.l scale_to_zero_src # scale src exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8850) mov.l %d0,-(%sp) # save scale factor 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8852) bsr.l scale_to_zero_dst # scale dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8854) neg.l (%sp) # SCALE FACTOR = scale1 - scale2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8855) add.l %d0,(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8857) mov.w 2+L_SCR3(%a6),%d1 # fetch precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8858) lsr.b &0x6,%d1 # shift to lo bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8859) mov.l (%sp)+,%d0 # load S.F.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8860) cmp.l %d0,(tbl_fdiv_ovfl.b,%pc,%d1.w*4) # will result overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8861) ble.w fdiv_may_ovfl # result will overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8863) cmp.l %d0,(tbl_fdiv_unfl.w,%pc,%d1.w*4) # will result underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8864) beq.w fdiv_may_unfl # maybe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8865) bgt.w fdiv_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8867) fdiv_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8868) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8870) fmov.l L_SCR3(%a6),%fpcr # save FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8871) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8873) fdiv.x FP_SCR0(%a6),%fp0 # perform divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8875) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8876) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8878) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8880) fdiv_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8881) fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8882) mov.l %d2,-(%sp) # store d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8883) mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8884) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8885) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8886) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8887) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8888) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8889) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8890) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8891) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8892) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8894) tbl_fdiv_ovfl2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8895) long 0x7fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8896) long 0x407f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8897) long 0x43ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8899) fdiv_no_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8900) mov.l (%sp)+,%d0 # restore scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8901) bra.b fdiv_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8903) fdiv_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8904) mov.l %d0,-(%sp) # save scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8906) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8908) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8909) fmov.l &0x0,%fpsr # set FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8911) fdiv.x FP_SCR0(%a6),%fp0 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8913) fmov.l %fpsr,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8914) fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8916) or.l %d0,USER_FPSR(%a6) # save INEX,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8918) fmovm.x &0x01,-(%sp) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8919) mov.w (%sp),%d0 # fetch new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8920) add.l &0xc,%sp # clear result from stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8921) andi.l &0x7fff,%d0 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8922) sub.l (%sp),%d0 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8923) cmp.l %d0,(tbl_fdiv_ovfl2.b,%pc,%d1.w*4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8924) blt.b fdiv_no_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8925) mov.l (%sp)+,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8927) fdiv_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8928) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8930) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8931) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8932) bne.b fdiv_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8934) fdiv_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8935) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8936) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8937) mov.l L_SCR3(%a6),%d0 # pass prec:rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8938) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8939) or.b %d0,FPSR_CC(%a6) # set INF if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8940) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8941) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8943) fdiv_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8944) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8945) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8946) bne.b fdiv_ovfl_ena_sd # no, do sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8948) fdiv_ovfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8949) fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8951) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8952) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8953) mov.w %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8954) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8955) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8956) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8957) andi.w &0x7fff,%d1 # clear sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8958) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8959) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8960) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8961) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8962) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8963) bra.b fdiv_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8965) fdiv_ovfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8966) fmovm.x FP_SCR1(%a6),&0x80 # load dst operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8968) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8969) andi.b &0x30,%d1 # keep rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8970) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8972) fdiv.x FP_SCR0(%a6),%fp0 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8974) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8975) bra.b fdiv_ovfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8977) fdiv_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8978) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8980) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8982) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8983) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8985) fdiv.x FP_SCR0(%a6),%fp0 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8987) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8988) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8990) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8992) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8993) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8994) bne.b fdiv_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8996) fdiv_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8997) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8999) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9000) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9001) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9002) or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9003) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9004) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9006) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9007) # UNFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9008) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9009) fdiv_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9010) fmovm.x FP_SCR1(%a6),&0x40 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9012) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9013) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9014) bne.b fdiv_unfl_ena_sd # no, sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9016) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9018) fdiv_unfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9019) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9021) fdiv.x FP_SCR0(%a6),%fp1 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9023) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9025) fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9026) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9027) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9028) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9029) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9030) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9031) sub.l %d0,%d1 # add scale factoer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9032) addi.l &0x6000,%d1 # add bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9033) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9034) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9035) mov.w %d1,FP_SCR0_EX(%a6) # insert new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9036) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9037) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9038) bra.w fdiv_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9040) fdiv_unfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9041) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9042) andi.b &0x30,%d1 # use only rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9043) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9045) bra.b fdiv_unfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9047) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9048) # the divide operation MAY underflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9049) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9050) fdiv_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9051) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9053) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9054) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9056) fdiv.x FP_SCR0(%a6),%fp0 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9058) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9059) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9061) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9063) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9064) fcmp.b %fp1,&0x1 # is |result| > 1.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9065) fbgt.w fdiv_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9066) fblt.w fdiv_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9068) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9069) # we still don't know if underflow occurred. result is ~ equal to 1. but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9070) # we don't know if the result was an underflow that rounded up to a 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9071) # or a normalized number that rounded down to a 1. so, redo the entire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9072) # operation using RZ as the rounding mode to see what the pre-rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9073) # result is. this case should be relatively rare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9074) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9075) fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9077) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9078) andi.b &0xc0,%d1 # keep rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9079) ori.b &rz_mode*0x10,%d1 # insert RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9081) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9082) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9084) fdiv.x FP_SCR0(%a6),%fp1 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9086) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9087) fabs.x %fp1 # make absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9088) fcmp.b %fp1,&0x1 # is |result| < 1.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9089) fbge.w fdiv_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9090) bra.w fdiv_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9092) ############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9094) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9095) # Divide: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9096) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9097) fdiv_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9098) mov.w (tbl_fdiv_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9099) jmp (tbl_fdiv_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9101) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9102) tbl_fdiv_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9103) short fdiv_norm - tbl_fdiv_op # NORM / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9104) short fdiv_inf_load - tbl_fdiv_op # NORM / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9105) short fdiv_zero_load - tbl_fdiv_op # NORM / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9106) short fdiv_res_qnan - tbl_fdiv_op # NORM / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9107) short fdiv_norm - tbl_fdiv_op # NORM / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9108) short fdiv_res_snan - tbl_fdiv_op # NORM / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9109) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9110) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9112) short fdiv_zero_load - tbl_fdiv_op # ZERO / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9113) short fdiv_res_operr - tbl_fdiv_op # ZERO / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9114) short fdiv_zero_load - tbl_fdiv_op # ZERO / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9115) short fdiv_res_qnan - tbl_fdiv_op # ZERO / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9116) short fdiv_zero_load - tbl_fdiv_op # ZERO / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9117) short fdiv_res_snan - tbl_fdiv_op # ZERO / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9118) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9119) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9121) short fdiv_inf_dst - tbl_fdiv_op # INF / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9122) short fdiv_inf_dst - tbl_fdiv_op # INF / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9123) short fdiv_res_operr - tbl_fdiv_op # INF / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9124) short fdiv_res_qnan - tbl_fdiv_op # INF / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9125) short fdiv_inf_dst - tbl_fdiv_op # INF / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9126) short fdiv_res_snan - tbl_fdiv_op # INF / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9127) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9128) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9130) short fdiv_res_qnan - tbl_fdiv_op # QNAN / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9131) short fdiv_res_qnan - tbl_fdiv_op # QNAN / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9132) short fdiv_res_qnan - tbl_fdiv_op # QNAN / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9133) short fdiv_res_qnan - tbl_fdiv_op # QNAN / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9134) short fdiv_res_qnan - tbl_fdiv_op # QNAN / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9135) short fdiv_res_snan - tbl_fdiv_op # QNAN / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9136) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9137) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9139) short fdiv_norm - tbl_fdiv_op # DENORM / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9140) short fdiv_inf_load - tbl_fdiv_op # DENORM / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9141) short fdiv_zero_load - tbl_fdiv_op # DENORM / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9142) short fdiv_res_qnan - tbl_fdiv_op # DENORM / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9143) short fdiv_norm - tbl_fdiv_op # DENORM / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9144) short fdiv_res_snan - tbl_fdiv_op # DENORM / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9145) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9146) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9148) short fdiv_res_snan - tbl_fdiv_op # SNAN / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9149) short fdiv_res_snan - tbl_fdiv_op # SNAN / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9150) short fdiv_res_snan - tbl_fdiv_op # SNAN / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9151) short fdiv_res_snan - tbl_fdiv_op # SNAN / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9152) short fdiv_res_snan - tbl_fdiv_op # SNAN / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9153) short fdiv_res_snan - tbl_fdiv_op # SNAN / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9154) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9155) short tbl_fdiv_op - tbl_fdiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9157) fdiv_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9158) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9159) fdiv_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9160) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9161) fdiv_res_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9162) bra.l res_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9164) global fdiv_zero_load # global for fsgldiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9165) fdiv_zero_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9166) mov.b SRC_EX(%a0),%d0 # result sign is exclusive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9167) mov.b DST_EX(%a1),%d1 # or of input signs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9168) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9169) bpl.b fdiv_zero_load_p # result is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9170) fmov.s &0x80000000,%fp0 # load a -ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9171) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9172) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9173) fdiv_zero_load_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9174) fmov.s &0x00000000,%fp0 # load a +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9175) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9176) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9178) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9179) # The destination was In Range and the source was a ZERO. The result,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9180) # Therefore, is an INF w/ the proper sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9181) # So, determine the sign and return a new INF (w/ the j-bit cleared).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9182) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9183) global fdiv_inf_load # global for fsgldiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9184) fdiv_inf_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9185) ori.w &dz_mask+adz_mask,2+USER_FPSR(%a6) # no; set DZ/ADZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9186) mov.b SRC_EX(%a0),%d0 # load both signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9187) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9188) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9189) bpl.b fdiv_inf_load_p # result is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9190) fmov.s &0xff800000,%fp0 # make result -INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9191) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9192) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9193) fdiv_inf_load_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9194) fmov.s &0x7f800000,%fp0 # make result +INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9195) mov.b &inf_bmask,FPSR_CC(%a6) # set INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9196) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9198) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9199) # The destination was an INF w/ an In Range or ZERO source, the result is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9200) # an INF w/ the proper sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9201) # The 68881/882 returns the destination INF w/ the new sign(if the j-bit of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9202) # dst INF is set, then then j-bit of the result INF is also set).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9203) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9204) global fdiv_inf_dst # global for fsgldiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9205) fdiv_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9206) mov.b DST_EX(%a1),%d0 # load both signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9207) mov.b SRC_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9208) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9209) bpl.b fdiv_inf_dst_p # result is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9211) fmovm.x DST(%a1),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9212) fabs.x %fp0 # clear sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9213) fneg.x %fp0 # set sign bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9214) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set INF/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9215) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9217) fdiv_inf_dst_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9218) fmovm.x DST(%a1),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9219) fabs.x %fp0 # return positive INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9220) mov.b &inf_bmask,FPSR_CC(%a6) # set INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9221) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9223) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9224) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9225) # fneg(): emulates the fneg instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9226) # fsneg(): emulates the fsneg instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9227) # fdneg(): emulates the fdneg instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9228) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9229) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9230) # norm() - normalize a denorm to provide EXOP #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9231) # scale_to_zero_src() - scale sgl/dbl source exponent #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9232) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9233) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9234) # res_qnan_1op() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9235) # res_snan_1op() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9236) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9237) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9238) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9239) # d0 = rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9240) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9241) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9242) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9243) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9244) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9245) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9246) # Handle NANs, zeroes, and infinities as special cases. Separate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9247) # norms/denorms into ext/sgl/dbl precisions. Extended precision can be #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9248) # emulated by simply setting sign bit. Sgl/dbl operands must be scaled #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9249) # and an actual fneg performed to see if overflow/underflow would have #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9250) # occurred. If so, return default underflow/overflow result. Else, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9251) # scale the result exponent and return result. FPSR gets set based on #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9252) # the result value. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9253) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9254) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9256) global fsneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9257) fsneg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9258) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9259) ori.b &s_mode*0x10,%d0 # insert sgl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9260) bra.b fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9262) global fdneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9263) fdneg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9264) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9265) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9267) global fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9268) fneg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9269) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9270) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9271) bne.w fneg_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9273) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9274) # NEGATE SIGN : norms and denorms ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9275) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9276) fneg_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9277) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9278) bne.w fneg_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9280) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9281) # precision selected is extended. so...we can not get an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9282) # or overflow because of rounding to the correct precision. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9283) # skip the scaling and unscaling...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9284) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9285) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9286) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9287) mov.w SRC_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9288) eori.w &0x8000,%d0 # negate sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9289) bpl.b fneg_norm_load # sign is positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9290) mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9291) fneg_norm_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9292) mov.w %d0,FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9293) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9294) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9296) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9297) # for an extended precision DENORM, the UNFL exception bit is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9298) # the accrued bit is NOT set in this instance(no inexactness!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9299) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9300) fneg_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9301) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9302) bne.b fneg_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9304) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9306) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9307) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9308) mov.w SRC_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9309) eori.w &0x8000,%d0 # negate sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9310) bpl.b fneg_denorm_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9311) mov.b &neg_bmask,FPSR_CC(%a6) # yes, set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9312) fneg_denorm_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9313) mov.w %d0,FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9314) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9316) btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9317) bne.b fneg_ext_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9318) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9320) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9321) # the input is an extended DENORM and underflow is enabled in the FPCR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9322) # normalize the mantissa and add the bias of 0x6000 to the resulting negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9323) # exponent and insert back into the operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9324) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9325) fneg_ext_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9326) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9327) bsr.l norm # normalize result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9328) neg.w %d0 # new exponent = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9329) addi.w &0x6000,%d0 # add new bias to exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9330) mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9331) andi.w &0x8000,%d1 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9332) andi.w &0x7fff,%d0 # clear sign position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9333) or.w %d1,%d0 # concat old sign, new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9334) mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9335) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9336) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9338) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9339) # operand is either single or double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9340) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9341) fneg_not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9342) cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9343) bne.b fneg_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9345) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9346) # operand is to be rounded to single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9347) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9348) fneg_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9349) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9350) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9351) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9352) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9354) cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9355) bge.w fneg_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9356) cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9357) beq.w fneg_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9358) blt.w fneg_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9360) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9361) # operand will NOT overflow or underflow when moved in to the fp reg file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9362) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9363) fneg_sd_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9364) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9365) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9367) fneg.x FP_SCR0(%a6),%fp0 # perform negation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9369) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9370) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9372) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9374) fneg_sd_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9375) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9376) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9377) mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9378) mov.w %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9379) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9380) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9381) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9382) or.w %d1,%d2 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9383) mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9384) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9385) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9386) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9388) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9389) # operand is to be rounded to double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9390) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9391) fneg_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9392) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9393) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9394) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9395) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9397) cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9398) bge.b fneg_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9399) cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9400) beq.w fneg_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9401) blt.w fneg_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9402) bra.w fneg_sd_normal # no; ho handle normalized op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9404) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9405) # operand WILL underflow when moved in to the fp register file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9406) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9407) fneg_sd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9408) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9410) eori.b &0x80,FP_SCR0_EX(%a6) # negate sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9411) bpl.b fneg_sd_unfl_tst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9412) bset &neg_bit,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9414) # if underflow or inexact is enabled, go calculate EXOP first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9415) fneg_sd_unfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9416) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9417) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9418) bne.b fneg_sd_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9420) fneg_sd_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9421) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9422) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9423) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9424) or.b %d0,FPSR_CC(%a6) # unf_res may have set 'Z'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9425) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9426) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9428) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9429) # operand will underflow AND underflow is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9430) # Therefore, we must return the result rounded to extended precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9431) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9432) fneg_sd_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9433) mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9434) mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9435) mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9437) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9438) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9439) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9440) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9441) sub.l %d0,%d1 # subtract scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9442) addi.l &0x6000,%d1 # add new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9443) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9444) or.w %d2,%d1 # concat new sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9445) mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9446) fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9447) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9448) bra.b fneg_sd_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9450) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9451) # operand WILL overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9452) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9453) fneg_sd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9454) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9455) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9457) fneg.x FP_SCR0(%a6),%fp0 # perform negation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9459) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9460) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9462) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9464) fneg_sd_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9465) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9467) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9468) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9469) bne.b fneg_sd_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9471) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9472) # OVFL is not enabled; therefore, we must create the default result by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9473) # calling ovf_res().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9474) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9475) fneg_sd_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9476) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9477) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9478) mov.l L_SCR3(%a6),%d0 # pass: prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9479) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9480) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9481) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9482) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9484) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9485) # OVFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9486) # the INEX2 bit has already been updated by the round to the correct precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9487) # now, round to extended(and don't alter the FPSR).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9488) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9489) fneg_sd_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9490) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9491) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9492) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9493) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9494) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9495) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9496) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9497) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9498) or.w %d2,%d1 # concat sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9499) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9500) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9501) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9502) bra.b fneg_sd_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9504) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9505) # the move in MAY underflow. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9506) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9507) fneg_sd_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9508) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9509) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9511) fneg.x FP_SCR0(%a6),%fp0 # perform negation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9513) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9514) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9516) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9518) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9519) fcmp.b %fp1,&0x2 # is |result| >= 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9520) fbge.w fneg_sd_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9522) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9523) bra.w fneg_sd_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9525) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9527) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9528) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9529) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9530) fneg_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9531) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9532) beq.w fneg_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9533) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9534) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9535) cmpi.b %d1,&QNAN # weed out QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9536) beq.l res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9538) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9539) # do the fneg; at this point, only possible ops are ZERO and INF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9540) # use fneg to determine ccodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9541) # prec:mode should be zero at this point but it won't affect answer anyways.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9542) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9543) fneg.x SRC_EX(%a0),%fp0 # do fneg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9544) fmov.l %fpsr,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9545) rol.l &0x8,%d0 # put ccodes in lo byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9546) mov.b %d0,FPSR_CC(%a6) # insert correct ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9547) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9549) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9550) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9551) # ftst(): emulates the ftest instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9552) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9553) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9554) # res{s,q}nan_1op() - set NAN result for monadic instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9555) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9556) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9557) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9558) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9559) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9560) # none #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9561) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9562) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9563) # Check the source operand tag (STAG) and set the FPCR according #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9564) # to the operand type and sign. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9565) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9566) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9568) global ftst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9569) ftst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9570) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9571) bne.b ftst_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9573) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9574) # Norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9575) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9576) ftst_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9577) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9578) bmi.b ftst_norm_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9579) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9580) ftst_norm_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9581) mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9582) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9584) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9585) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9586) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9587) ftst_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9588) cmpi.b %d1,&ZERO # weed out ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9589) beq.b ftst_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9590) cmpi.b %d1,&INF # weed out INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9591) beq.b ftst_inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9592) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9593) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9594) cmpi.b %d1,&QNAN # weed out QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9595) beq.l res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9597) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9598) # Denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9599) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9600) ftst_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9601) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9602) bmi.b ftst_denorm_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9603) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9604) ftst_denorm_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9605) mov.b &neg_bmask,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9606) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9608) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9609) # Infinity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9610) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9611) ftst_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9612) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9613) bmi.b ftst_inf_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9614) ftst_inf_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9615) mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9616) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9617) ftst_inf_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9618) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'I','N' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9619) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9621) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9622) # Zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9623) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9624) ftst_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9625) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9626) bmi.b ftst_zero_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9627) ftst_zero_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9628) mov.b &z_bmask,FPSR_CC(%a6) # set 'N' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9629) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9630) ftst_zero_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9631) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9632) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9634) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9635) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9636) # fint(): emulates the fint instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9637) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9638) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9639) # res_{s,q}nan_1op() - set NAN result for monadic operation #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9640) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9641) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9642) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9643) # d0 = round precision/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9644) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9645) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9646) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9647) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9648) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9649) # Separate according to operand type. Unnorms don't pass through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9650) # here. For norms, load the rounding mode/prec, execute a "fint", then #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9651) # store the resulting FPSR bits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9652) # For denorms, force the j-bit to a one and do the same as for #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9653) # norms. Denorms are so low that the answer will either be a zero or a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9654) # one. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9655) # For zeroes/infs/NANs, return the same while setting the FPSR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9656) # as appropriate. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9657) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9658) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9660) global fint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9661) fint:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9662) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9663) bne.b fint_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9665) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9666) # Norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9667) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9668) fint_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9669) andi.b &0x30,%d0 # set prec = ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9671) fmov.l %d0,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9672) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9674) fint.x SRC(%a0),%fp0 # execute fint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9676) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9677) fmov.l %fpsr,%d0 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9678) or.l %d0,USER_FPSR(%a6) # set exception bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9680) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9682) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9683) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9684) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9685) fint_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9686) cmpi.b %d1,&ZERO # weed out ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9687) beq.b fint_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9688) cmpi.b %d1,&INF # weed out INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9689) beq.b fint_inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9690) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9691) beq.b fint_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9692) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9693) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9694) bra.l res_qnan_1op # weed out QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9696) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9697) # Denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9698) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9699) # for DENORMs, the result will be either (+/-)ZERO or (+/-)1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9700) # also, the INEX2 and AINEX exception bits will be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9701) # so, we could either set these manually or force the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9702) # to a very small NORM and ship it to the NORM routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9703) # I do the latter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9704) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9705) fint_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9706) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9707) mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9708) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9709) bra.b fint_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9711) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9712) # Zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9713) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9714) fint_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9715) tst.b SRC_EX(%a0) # is ZERO negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9716) bmi.b fint_zero_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9717) fint_zero_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9718) fmov.s &0x00000000,%fp0 # return +ZERO in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9719) mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9720) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9721) fint_zero_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9722) fmov.s &0x80000000,%fp0 # return -ZERO in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9723) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9724) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9726) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9727) # Infinity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9728) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9729) fint_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9730) fmovm.x SRC(%a0),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9731) tst.b SRC_EX(%a0) # is INF negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9732) bmi.b fint_inf_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9733) fint_inf_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9734) mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9735) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9736) fint_inf_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9737) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9738) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9740) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9741) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9742) # fintrz(): emulates the fintrz instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9743) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9744) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9745) # res_{s,q}nan_1op() - set NAN result for monadic operation #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9746) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9747) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9748) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9749) # d0 = round precision/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9750) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9751) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9752) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9753) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9754) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9755) # Separate according to operand type. Unnorms don't pass through #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9756) # here. For norms, load the rounding mode/prec, execute a "fintrz", #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9757) # then store the resulting FPSR bits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9758) # For denorms, force the j-bit to a one and do the same as for #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9759) # norms. Denorms are so low that the answer will either be a zero or a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9760) # one. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9761) # For zeroes/infs/NANs, return the same while setting the FPSR #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9762) # as appropriate. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9763) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9764) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9766) global fintrz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9767) fintrz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9768) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9769) bne.b fintrz_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9771) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9772) # Norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9773) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9774) fintrz_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9775) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9777) fintrz.x SRC(%a0),%fp0 # execute fintrz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9779) fmov.l %fpsr,%d0 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9780) or.l %d0,USER_FPSR(%a6) # set exception bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9782) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9784) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9785) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9786) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9787) fintrz_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9788) cmpi.b %d1,&ZERO # weed out ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9789) beq.b fintrz_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9790) cmpi.b %d1,&INF # weed out INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9791) beq.b fintrz_inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9792) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9793) beq.b fintrz_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9794) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9795) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9796) bra.l res_qnan_1op # weed out QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9798) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9799) # Denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9800) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9801) # for DENORMs, the result will be (+/-)ZERO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9802) # also, the INEX2 and AINEX exception bits will be set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9803) # so, we could either set these manually or force the DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9804) # to a very small NORM and ship it to the NORM routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9805) # I do the latter.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9806) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9807) fintrz_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9808) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6) # copy sign, zero exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9809) mov.b &0x80,FP_SCR0_HI(%a6) # force DENORM ==> small NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9810) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9811) bra.b fintrz_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9813) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9814) # Zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9815) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9816) fintrz_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9817) tst.b SRC_EX(%a0) # is ZERO negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9818) bmi.b fintrz_zero_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9819) fintrz_zero_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9820) fmov.s &0x00000000,%fp0 # return +ZERO in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9821) mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9822) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9823) fintrz_zero_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9824) fmov.s &0x80000000,%fp0 # return -ZERO in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9825) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9826) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9828) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9829) # Infinity:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9830) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9831) fintrz_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9832) fmovm.x SRC(%a0),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9833) tst.b SRC_EX(%a0) # is INF negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9834) bmi.b fintrz_inf_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9835) fintrz_inf_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9836) mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9837) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9838) fintrz_inf_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9839) mov.b &inf_bmask+neg_bmask,FPSR_CC(%a6) # set 'N','I' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9840) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9842) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9843) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9844) # fabs(): emulates the fabs instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9845) # fsabs(): emulates the fsabs instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9846) # fdabs(): emulates the fdabs instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9847) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9848) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9849) # norm() - normalize denorm mantissa to provide EXOP #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9850) # scale_to_zero_src() - make exponent. = 0; get scale factor #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9851) # unf_res() - calculate underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9852) # ovf_res() - calculate overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9853) # res_{s,q}nan_1op() - set NAN result for monadic operation #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9854) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9855) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9856) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9857) # d0 = rnd precision/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9858) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9859) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9860) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9861) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9862) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9863) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9864) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9865) # norms into extended, single, and double precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9866) # Simply clear sign for extended precision norm. Ext prec denorm #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9867) # gets an EXOP created for it since it's an underflow. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9868) # Double and single precision can overflow and underflow. First, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9869) # scale the operand such that the exponent is zero. Perform an "fabs" #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9870) # using the correct rnd mode/prec. Check to see if the original #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9871) # exponent would take an exception. If so, use unf_res() or ovf_res() #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9872) # to calculate the default result. Also, create the EXOP for the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9873) # exceptional case. If no exception should occur, insert the correct #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9874) # result exponent and return. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9875) # Unnorms don't pass through here. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9876) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9877) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9879) global fsabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9880) fsabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9881) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9882) ori.b &s_mode*0x10,%d0 # insert sgl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9883) bra.b fabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9885) global fdabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9886) fdabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9887) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9888) ori.b &d_mode*0x10,%d0 # insert dbl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9890) global fabs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9891) fabs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9892) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9893) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9894) bne.w fabs_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9896) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9897) # ABSOLUTE VALUE: norms and denorms ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9898) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9899) fabs_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9900) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9901) bne.b fabs_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9903) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9904) # precision selected is extended. so...we can not get an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9905) # or overflow because of rounding to the correct precision. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9906) # skip the scaling and unscaling...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9907) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9908) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9909) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9910) mov.w SRC_EX(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9911) bclr &15,%d1 # force absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9912) mov.w %d1,FP_SCR0_EX(%a6) # insert exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9913) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9914) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9916) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9917) # for an extended precision DENORM, the UNFL exception bit is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9918) # the accrued bit is NOT set in this instance(no inexactness!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9919) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9920) fabs_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9921) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9922) bne.b fabs_not_ext # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9924) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9926) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9927) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9928) mov.w SRC_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9929) bclr &15,%d0 # clear sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9930) mov.w %d0,FP_SCR0_EX(%a6) # insert exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9932) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9934) btst &unfl_bit,FPCR_ENABLE(%a6) # is UNFL enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9935) bne.b fabs_ext_unfl_ena
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9936) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9938) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9939) # the input is an extended DENORM and underflow is enabled in the FPCR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9940) # normalize the mantissa and add the bias of 0x6000 to the resulting negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9941) # exponent and insert back into the operand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9942) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9943) fabs_ext_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9944) lea FP_SCR0(%a6),%a0 # pass: ptr to operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9945) bsr.l norm # normalize result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9946) neg.w %d0 # new exponent = -(shft val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9947) addi.w &0x6000,%d0 # add new bias to exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9948) mov.w FP_SCR0_EX(%a6),%d1 # fetch old sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9949) andi.w &0x8000,%d1 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9950) andi.w &0x7fff,%d0 # clear sign position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9951) or.w %d1,%d0 # concat old sign, new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9952) mov.w %d0,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9953) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9954) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9956) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9957) # operand is either single or double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9958) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9959) fabs_not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9960) cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9961) bne.b fabs_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9963) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9964) # operand is to be rounded to single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9965) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9966) fabs_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9967) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9968) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9969) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9970) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9972) cmpi.l %d0,&0x3fff-0x3f80 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9973) bge.w fabs_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9974) cmpi.l %d0,&0x3fff-0x407e # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9975) beq.w fabs_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9976) blt.w fabs_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9978) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9979) # operand will NOT overflow or underflow when moved in to the fp reg file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9980) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9981) fabs_sd_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9982) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9983) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9985) fabs.x FP_SCR0(%a6),%fp0 # perform absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9987) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9988) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9990) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9992) fabs_sd_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9993) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9994) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9995) mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9996) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9997) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9998) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9999) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10000) or.w %d1,%d2 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10001) mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10002) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10003) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10004) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10006) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10007) # operand is to be rounded to double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10008) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10009) fabs_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10010) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10011) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10012) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10013) bsr.l scale_to_zero_src # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10015) cmpi.l %d0,&0x3fff-0x3c00 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10016) bge.b fabs_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10017) cmpi.l %d0,&0x3fff-0x43fe # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10018) beq.w fabs_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10019) blt.w fabs_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10020) bra.w fabs_sd_normal # no; ho handle normalized op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10022) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10023) # operand WILL underflow when moved in to the fp register file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10024) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10025) fabs_sd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10026) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10028) bclr &0x7,FP_SCR0_EX(%a6) # force absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10030) # if underflow or inexact is enabled, go calculate EXOP first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10031) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10032) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10033) bne.b fabs_sd_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10035) fabs_sd_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10036) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10037) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10038) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10039) or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10040) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10041) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10043) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10044) # operand will underflow AND underflow is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10045) # Therefore, we must return the result rounded to extended precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10046) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10047) fabs_sd_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10048) mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10049) mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10050) mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10052) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10053) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10054) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10055) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10056) sub.l %d0,%d1 # subtract scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10057) addi.l &0x6000,%d1 # add new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10058) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10059) or.w %d2,%d1 # concat new sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10060) mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10061) fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10062) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10063) bra.b fabs_sd_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10065) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10066) # operand WILL overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10067) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10068) fabs_sd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10069) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10070) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10072) fabs.x FP_SCR0(%a6),%fp0 # perform absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10074) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10075) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10077) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10079) fabs_sd_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10080) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10082) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10083) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10084) bne.b fabs_sd_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10086) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10087) # OVFL is not enabled; therefore, we must create the default result by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10088) # calling ovf_res().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10089) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10090) fabs_sd_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10091) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10092) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10093) mov.l L_SCR3(%a6),%d0 # pass: prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10094) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10095) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10096) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10097) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10099) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10100) # OVFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10101) # the INEX2 bit has already been updated by the round to the correct precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10102) # now, round to extended(and don't alter the FPSR).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10103) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10104) fabs_sd_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10105) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10106) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10107) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10108) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10109) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10110) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10111) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10112) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10113) or.w %d2,%d1 # concat sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10114) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10115) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10116) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10117) bra.b fabs_sd_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10119) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10120) # the move in MAY underflow. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10121) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10122) fabs_sd_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10123) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10124) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10126) fabs.x FP_SCR0(%a6),%fp0 # perform absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10128) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10129) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10131) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10133) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10134) fcmp.b %fp1,&0x2 # is |result| >= 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10135) fbge.w fabs_sd_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10137) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10138) bra.w fabs_sd_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10140) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10142) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10143) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10144) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10145) fabs_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10146) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10147) beq.w fabs_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10148) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10149) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10150) cmpi.b %d1,&QNAN # weed out QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10151) beq.l res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10153) fabs.x SRC(%a0),%fp0 # force absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10155) cmpi.b %d1,&INF # weed out INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10156) beq.b fabs_inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10157) fabs_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10158) mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10159) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10160) fabs_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10161) mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10162) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10164) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10165) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10166) # fcmp(): fp compare op routine #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10167) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10168) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10169) # res_qnan() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10170) # res_snan() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10171) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10172) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10173) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10174) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10175) # d0 = round prec/mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10176) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10177) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10178) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10179) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10180) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10181) # Handle NANs and denorms as special cases. For everything else, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10182) # just use the actual fcmp instruction to produce the correct condition #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10183) # codes. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10184) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10185) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10187) global fcmp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10188) fcmp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10189) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10190) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10191) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10192) or.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10193) bne.b fcmp_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10195) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10196) # COMPARE FP OPs : NORMs, ZEROs, INFs, and "corrected" DENORMs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10197) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10198) fcmp_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10199) fmovm.x DST(%a1),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10201) fcmp.x %fp0,SRC(%a0) # do compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10203) fmov.l %fpsr,%d0 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10204) rol.l &0x8,%d0 # extract ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10205) mov.b %d0,FPSR_CC(%a6) # set ccode bits(no exc bits are set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10207) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10209) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10210) # fcmp: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10211) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10212) fcmp_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10213) mov.w (tbl_fcmp_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10214) jmp (tbl_fcmp_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10216) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10217) tbl_fcmp_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10218) short fcmp_norm - tbl_fcmp_op # NORM - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10219) short fcmp_norm - tbl_fcmp_op # NORM - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10220) short fcmp_norm - tbl_fcmp_op # NORM - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10221) short fcmp_res_qnan - tbl_fcmp_op # NORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10222) short fcmp_nrm_dnrm - tbl_fcmp_op # NORM - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10223) short fcmp_res_snan - tbl_fcmp_op # NORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10224) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10225) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10227) short fcmp_norm - tbl_fcmp_op # ZERO - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10228) short fcmp_norm - tbl_fcmp_op # ZERO - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10229) short fcmp_norm - tbl_fcmp_op # ZERO - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10230) short fcmp_res_qnan - tbl_fcmp_op # ZERO - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10231) short fcmp_dnrm_s - tbl_fcmp_op # ZERO - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10232) short fcmp_res_snan - tbl_fcmp_op # ZERO - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10233) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10234) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10236) short fcmp_norm - tbl_fcmp_op # INF - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10237) short fcmp_norm - tbl_fcmp_op # INF - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10238) short fcmp_norm - tbl_fcmp_op # INF - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10239) short fcmp_res_qnan - tbl_fcmp_op # INF - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10240) short fcmp_dnrm_s - tbl_fcmp_op # INF - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10241) short fcmp_res_snan - tbl_fcmp_op # INF - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10242) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10243) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10245) short fcmp_res_qnan - tbl_fcmp_op # QNAN - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10246) short fcmp_res_qnan - tbl_fcmp_op # QNAN - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10247) short fcmp_res_qnan - tbl_fcmp_op # QNAN - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10248) short fcmp_res_qnan - tbl_fcmp_op # QNAN - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10249) short fcmp_res_qnan - tbl_fcmp_op # QNAN - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10250) short fcmp_res_snan - tbl_fcmp_op # QNAN - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10251) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10252) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10254) short fcmp_dnrm_nrm - tbl_fcmp_op # DENORM - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10255) short fcmp_dnrm_d - tbl_fcmp_op # DENORM - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10256) short fcmp_dnrm_d - tbl_fcmp_op # DENORM - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10257) short fcmp_res_qnan - tbl_fcmp_op # DENORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10258) short fcmp_dnrm_sd - tbl_fcmp_op # DENORM - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10259) short fcmp_res_snan - tbl_fcmp_op # DENORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10260) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10261) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10263) short fcmp_res_snan - tbl_fcmp_op # SNAN - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10264) short fcmp_res_snan - tbl_fcmp_op # SNAN - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10265) short fcmp_res_snan - tbl_fcmp_op # SNAN - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10266) short fcmp_res_snan - tbl_fcmp_op # SNAN - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10267) short fcmp_res_snan - tbl_fcmp_op # SNAN - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10268) short fcmp_res_snan - tbl_fcmp_op # SNAN - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10269) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10270) short tbl_fcmp_op - tbl_fcmp_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10272) # unlike all other functions for QNAN and SNAN, fcmp does NOT set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10273) # 'N' bit for a negative QNAN or SNAN input so we must squelch it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10274) fcmp_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10275) bsr.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10276) andi.b &0xf7,FPSR_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10277) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10278) fcmp_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10279) bsr.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10280) andi.b &0xf7,FPSR_CC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10281) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10283) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10284) # DENORMs are a little more difficult.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10285) # If you have a 2 DENORMs, then you can just force the j-bit to a one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10286) # and use the fcmp_norm routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10287) # If you have a DENORM and an INF or ZERO, just force the DENORM's j-bit to a one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10288) # and use the fcmp_norm routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10289) # If you have a DENORM and a NORM with opposite signs, then use fcmp_norm, also.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10290) # But with a DENORM and a NORM of the same sign, the neg bit is set if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10291) # (1) signs are (+) and the DENORM is the dst or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10292) # (2) signs are (-) and the DENORM is the src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10293) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10295) fcmp_dnrm_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10296) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10297) mov.l SRC_HI(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10298) bset &31,%d0 # DENORM src; make into small norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10299) mov.l %d0,FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10300) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10301) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10302) bra.w fcmp_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10304) fcmp_dnrm_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10305) mov.l DST_EX(%a1),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10306) mov.l DST_HI(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10307) bset &31,%d0 # DENORM src; make into small norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10308) mov.l %d0,FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10309) mov.l DST_LO(%a1),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10310) lea FP_SCR0(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10311) bra.w fcmp_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10313) fcmp_dnrm_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10314) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10315) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10316) mov.l DST_HI(%a1),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10317) bset &31,%d0 # DENORM dst; make into small norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10318) mov.l %d0,FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10319) mov.l SRC_HI(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10320) bset &31,%d0 # DENORM dst; make into small norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10321) mov.l %d0,FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10322) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10323) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10324) lea FP_SCR1(%a6),%a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10325) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10326) bra.w fcmp_norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10328) fcmp_nrm_dnrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10329) mov.b SRC_EX(%a0),%d0 # determine if like signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10330) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10331) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10332) bmi.w fcmp_dnrm_s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10334) # signs are the same, so must determine the answer ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10335) tst.b %d0 # is src op negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10336) bmi.b fcmp_nrm_dnrm_m # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10337) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10338) fcmp_nrm_dnrm_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10339) mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10340) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10342) fcmp_dnrm_nrm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10343) mov.b SRC_EX(%a0),%d0 # determine if like signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10344) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10345) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10346) bmi.w fcmp_dnrm_d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10348) # signs are the same, so must determine the answer ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10349) tst.b %d0 # is src op negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10350) bpl.b fcmp_dnrm_nrm_m # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10351) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10352) fcmp_dnrm_nrm_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10353) mov.b &neg_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10354) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10356) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10357) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10358) # fsglmul(): emulates the fsglmul instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10359) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10360) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10361) # scale_to_zero_src() - scale src exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10362) # scale_to_zero_dst() - scale dst exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10363) # unf_res4() - return default underflow result for sglop #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10364) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10365) # res_qnan() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10366) # res_snan() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10367) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10368) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10369) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10370) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10371) # d0 rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10372) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10373) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10374) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10375) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10376) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10377) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10378) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10379) # norms/denorms into ext/sgl/dbl precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10380) # For norms/denorms, scale the exponents such that a multiply #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10381) # instruction won't cause an exception. Use the regular fsglmul to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10382) # compute a result. Check if the regular operands would have taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10383) # an exception. If so, return the default overflow/underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10384) # and return the EXOP if exceptions are enabled. Else, scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10385) # result operand to the proper exponent. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10386) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10387) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10389) global fsglmul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10390) fsglmul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10391) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10393) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10394) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10395) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10396) or.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10398) bne.w fsglmul_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10400) fsglmul_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10401) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10402) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10403) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10405) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10406) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10407) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10409) bsr.l scale_to_zero_src # scale exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10410) mov.l %d0,-(%sp) # save scale factor 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10412) bsr.l scale_to_zero_dst # scale dst exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10414) add.l (%sp)+,%d0 # SCALE_FACTOR = scale1 + scale2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10416) cmpi.l %d0,&0x3fff-0x7ffe # would result ovfl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10417) beq.w fsglmul_may_ovfl # result may rnd to overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10418) blt.w fsglmul_ovfl # result will overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10420) cmpi.l %d0,&0x3fff+0x0001 # would result unfl?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10421) beq.w fsglmul_may_unfl # result may rnd to no unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10422) bgt.w fsglmul_unfl # result will underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10424) fsglmul_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10425) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10427) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10428) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10430) fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10432) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10433) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10435) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10437) fsglmul_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10438) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10439) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10440) mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10441) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10442) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10443) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10444) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10445) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10446) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10447) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10448) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10449) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10451) fsglmul_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10452) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10454) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10455) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10457) fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10459) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10460) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10462) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10464) fsglmul_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10466) # save setting this until now because this is where fsglmul_may_ovfl may jump in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10467) or.l &ovfl_inx_mask, USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10469) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10470) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10471) bne.b fsglmul_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10473) fsglmul_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10474) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10475) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10476) mov.l L_SCR3(%a6),%d0 # pass prec:rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10477) andi.b &0x30,%d0 # force prec = ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10478) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10479) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10480) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10481) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10483) fsglmul_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10484) fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10486) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10487) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10488) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10489) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10490) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10491) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10492) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10493) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10494) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10495) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10496) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10497) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10498) bra.b fsglmul_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10500) fsglmul_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10501) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10503) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10504) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10506) fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10508) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10509) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10511) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10513) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10514) fcmp.b %fp1,&0x2 # is |result| >= 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10515) fbge.w fsglmul_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10517) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10518) bra.w fsglmul_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10520) fsglmul_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10521) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10523) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10525) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10526) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10528) fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10530) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10531) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10533) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10535) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10536) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10537) bne.b fsglmul_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10539) fsglmul_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10540) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10542) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10543) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10544) bsr.l unf_res4 # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10545) or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10546) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10547) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10549) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10550) # UNFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10551) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10552) fsglmul_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10553) fmovm.x FP_SCR1(%a6),&0x40 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10555) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10556) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10558) fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10560) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10562) fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10563) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10564) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10565) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10566) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10567) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10568) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10569) addi.l &0x6000,%d1 # add bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10570) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10571) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10572) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10573) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10574) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10575) bra.w fsglmul_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10577) fsglmul_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10578) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10580) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10581) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10583) fsglmul.x FP_SCR0(%a6),%fp0 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10585) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10586) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10588) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10590) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10591) fcmp.b %fp1,&0x2 # is |result| > 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10592) fbgt.w fsglmul_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10593) fblt.w fsglmul_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10595) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10596) # we still don't know if underflow occurred. result is ~ equal to 2. but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10597) # we don't know if the result was an underflow that rounded up to a 2 or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10598) # a normalized number that rounded down to a 2. so, redo the entire operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10599) # using RZ as the rounding mode to see what the pre-rounded result is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10600) # this case should be relatively rare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10601) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10602) fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10604) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10605) andi.b &0xc0,%d1 # keep rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10606) ori.b &rz_mode*0x10,%d1 # insert RZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10608) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10609) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10611) fsglmul.x FP_SCR0(%a6),%fp1 # execute sgl multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10613) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10614) fabs.x %fp1 # make absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10615) fcmp.b %fp1,&0x2 # is |result| < 2.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10616) fbge.w fsglmul_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10617) bra.w fsglmul_unfl # yes, underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10619) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10621) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10622) # Single Precision Multiply: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10623) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10624) fsglmul_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10625) mov.w (tbl_fsglmul_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10626) jmp (tbl_fsglmul_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10628) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10629) tbl_fsglmul_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10630) short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10631) short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10632) short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10633) short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10634) short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10635) short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10636) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10637) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10639) short fsglmul_zero - tbl_fsglmul_op # ZERO x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10640) short fsglmul_zero - tbl_fsglmul_op # ZERO x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10641) short fsglmul_res_operr - tbl_fsglmul_op # ZERO x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10642) short fsglmul_res_qnan - tbl_fsglmul_op # ZERO x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10643) short fsglmul_zero - tbl_fsglmul_op # ZERO x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10644) short fsglmul_res_snan - tbl_fsglmul_op # ZERO x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10645) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10646) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10648) short fsglmul_inf_dst - tbl_fsglmul_op # INF x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10649) short fsglmul_res_operr - tbl_fsglmul_op # INF x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10650) short fsglmul_inf_dst - tbl_fsglmul_op # INF x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10651) short fsglmul_res_qnan - tbl_fsglmul_op # INF x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10652) short fsglmul_inf_dst - tbl_fsglmul_op # INF x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10653) short fsglmul_res_snan - tbl_fsglmul_op # INF x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10654) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10655) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10657) short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10658) short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10659) short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10660) short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10661) short fsglmul_res_qnan - tbl_fsglmul_op # QNAN x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10662) short fsglmul_res_snan - tbl_fsglmul_op # QNAN x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10663) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10664) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10666) short fsglmul_norm - tbl_fsglmul_op # NORM x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10667) short fsglmul_zero - tbl_fsglmul_op # NORM x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10668) short fsglmul_inf_src - tbl_fsglmul_op # NORM x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10669) short fsglmul_res_qnan - tbl_fsglmul_op # NORM x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10670) short fsglmul_norm - tbl_fsglmul_op # NORM x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10671) short fsglmul_res_snan - tbl_fsglmul_op # NORM x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10672) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10673) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10675) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10676) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10677) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10678) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10679) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10680) short fsglmul_res_snan - tbl_fsglmul_op # SNAN x SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10681) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10682) short tbl_fsglmul_op - tbl_fsglmul_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10684) fsglmul_res_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10685) bra.l res_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10686) fsglmul_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10687) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10688) fsglmul_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10689) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10690) fsglmul_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10691) bra.l fmul_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10692) fsglmul_inf_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10693) bra.l fmul_inf_src
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10694) fsglmul_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10695) bra.l fmul_inf_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10697) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10698) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10699) # fsgldiv(): emulates the fsgldiv instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10700) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10701) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10702) # scale_to_zero_src() - scale src exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10703) # scale_to_zero_dst() - scale dst exponent to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10704) # unf_res4() - return default underflow result for sglop #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10705) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10706) # res_qnan() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10707) # res_snan() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10708) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10709) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10710) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10711) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10712) # d0 rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10713) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10714) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10715) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10716) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10717) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10718) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10719) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10720) # norms/denorms into ext/sgl/dbl precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10721) # For norms/denorms, scale the exponents such that a divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10722) # instruction won't cause an exception. Use the regular fsgldiv to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10723) # compute a result. Check if the regular operands would have taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10724) # an exception. If so, return the default overflow/underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10725) # and return the EXOP if exceptions are enabled. Else, scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10726) # result operand to the proper exponent. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10727) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10728) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10730) global fsgldiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10731) fsgldiv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10732) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10734) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10735) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10736) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10737) or.b STAG(%a6),%d1 # combine src tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10739) bne.w fsgldiv_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10741) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10742) # DIVIDE: NORMs and DENORMs ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10743) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10744) fsgldiv_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10745) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10746) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10747) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10749) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10750) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10751) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10753) bsr.l scale_to_zero_src # calculate scale factor 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10754) mov.l %d0,-(%sp) # save scale factor 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10756) bsr.l scale_to_zero_dst # calculate scale factor 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10758) neg.l (%sp) # S.F. = scale1 - scale2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10759) add.l %d0,(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10761) mov.w 2+L_SCR3(%a6),%d1 # fetch precision,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10762) lsr.b &0x6,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10763) mov.l (%sp)+,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10764) cmpi.l %d0,&0x3fff-0x7ffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10765) ble.w fsgldiv_may_ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10767) cmpi.l %d0,&0x3fff-0x0000 # will result underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10768) beq.w fsgldiv_may_unfl # maybe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10769) bgt.w fsgldiv_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10771) fsgldiv_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10772) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10774) fmov.l L_SCR3(%a6),%fpcr # save FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10775) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10777) fsgldiv.x FP_SCR0(%a6),%fp0 # perform sgl divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10779) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10780) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10782) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10784) fsgldiv_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10785) fmovm.x &0x80,FP_SCR0(%a6) # store result on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10786) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10787) mov.w FP_SCR0_EX(%a6),%d1 # load {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10788) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10789) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10790) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10791) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10792) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10793) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10794) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10795) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10796) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10798) fsgldiv_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10799) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10801) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10802) fmov.l &0x0,%fpsr # set FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10804) fsgldiv.x FP_SCR0(%a6),%fp0 # execute divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10806) fmov.l %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10807) fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10809) or.l %d1,USER_FPSR(%a6) # save INEX,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10811) fmovm.x &0x01,-(%sp) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10812) mov.w (%sp),%d1 # fetch new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10813) add.l &0xc,%sp # clear result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10814) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10815) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10816) cmp.l %d1,&0x7fff # did divide overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10817) blt.b fsgldiv_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10819) fsgldiv_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10820) or.w &ovfl_inx_mask,2+USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10822) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10823) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10824) bne.b fsgldiv_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10826) fsgldiv_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10827) btst &neg_bit,FPSR_CC(%a6) # is result negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10828) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10829) mov.l L_SCR3(%a6),%d0 # pass prec:rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10830) andi.b &0x30,%d0 # kill precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10831) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10832) or.b %d0,FPSR_CC(%a6) # set INF if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10833) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10834) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10836) fsgldiv_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10837) fmovm.x &0x80,FP_SCR0(%a6) # move result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10839) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10840) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10841) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10842) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10843) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10844) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10845) subi.l &0x6000,%d1 # subtract new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10846) andi.w &0x7fff,%d1 # clear ms bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10847) or.w %d2,%d1 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10848) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10849) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10850) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10851) bra.b fsgldiv_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10853) fsgldiv_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10854) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10856) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10858) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10859) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10861) fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10863) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10864) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10866) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10868) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10869) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10870) bne.b fsgldiv_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10872) fsgldiv_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10873) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10875) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10876) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10877) bsr.l unf_res4 # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10878) or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10879) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10880) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10882) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10883) # UNFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10884) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10885) fsgldiv_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10886) fmovm.x FP_SCR1(%a6),&0x40 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10888) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10889) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10891) fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10893) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10895) fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10896) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10897) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10898) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10899) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10900) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10901) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10902) addi.l &0x6000,%d1 # add bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10903) andi.w &0x7fff,%d1 # clear top bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10904) or.w %d2,%d1 # concat old sign, new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10905) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10906) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10907) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10908) bra.b fsgldiv_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10910) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10911) # the divide operation MAY underflow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10912) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10913) fsgldiv_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10914) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10916) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10917) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10919) fsgldiv.x FP_SCR0(%a6),%fp0 # execute sgl divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10921) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10922) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10924) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10926) fabs.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10927) fcmp.b %fp1,&0x1 # is |result| > 1.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10928) fbgt.w fsgldiv_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10929) fblt.w fsgldiv_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10931) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10932) # we still don't know if underflow occurred. result is ~ equal to 1. but,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10933) # we don't know if the result was an underflow that rounded up to a 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10934) # or a normalized number that rounded down to a 1. so, redo the entire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10935) # operation using RZ as the rounding mode to see what the pre-rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10936) # result is. this case should be relatively rare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10937) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10938) fmovm.x FP_SCR1(%a6),&0x40 # load dst op into %fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10940) clr.l %d1 # clear scratch register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10941) ori.b &rz_mode*0x10,%d1 # force RZ rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10943) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10944) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10946) fsgldiv.x FP_SCR0(%a6),%fp1 # execute sgl divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10948) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10949) fabs.x %fp1 # make absolute value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10950) fcmp.b %fp1,&0x1 # is |result| < 1.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10951) fbge.w fsgldiv_normal_exit # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10952) bra.w fsgldiv_unfl # yes; underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10954) ############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10956) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10957) # Divide: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10958) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10959) fsgldiv_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10960) mov.w (tbl_fsgldiv_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10961) jmp (tbl_fsgldiv_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10963) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10964) tbl_fsgldiv_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10965) short fsgldiv_norm - tbl_fsgldiv_op # NORM / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10966) short fsgldiv_inf_load - tbl_fsgldiv_op # NORM / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10967) short fsgldiv_zero_load - tbl_fsgldiv_op # NORM / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10968) short fsgldiv_res_qnan - tbl_fsgldiv_op # NORM / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10969) short fsgldiv_norm - tbl_fsgldiv_op # NORM / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10970) short fsgldiv_res_snan - tbl_fsgldiv_op # NORM / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10971) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10972) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10974) short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10975) short fsgldiv_res_operr - tbl_fsgldiv_op # ZERO / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10976) short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10977) short fsgldiv_res_qnan - tbl_fsgldiv_op # ZERO / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10978) short fsgldiv_zero_load - tbl_fsgldiv_op # ZERO / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10979) short fsgldiv_res_snan - tbl_fsgldiv_op # ZERO / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10980) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10981) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10983) short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10984) short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10985) short fsgldiv_res_operr - tbl_fsgldiv_op # INF / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10986) short fsgldiv_res_qnan - tbl_fsgldiv_op # INF / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10987) short fsgldiv_inf_dst - tbl_fsgldiv_op # INF / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10988) short fsgldiv_res_snan - tbl_fsgldiv_op # INF / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10989) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10990) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10992) short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10993) short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10994) short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10995) short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10996) short fsgldiv_res_qnan - tbl_fsgldiv_op # QNAN / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10997) short fsgldiv_res_snan - tbl_fsgldiv_op # QNAN / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10998) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10999) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11001) short fsgldiv_norm - tbl_fsgldiv_op # DENORM / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11002) short fsgldiv_inf_load - tbl_fsgldiv_op # DENORM / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11003) short fsgldiv_zero_load - tbl_fsgldiv_op # DENORM / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11004) short fsgldiv_res_qnan - tbl_fsgldiv_op # DENORM / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11005) short fsgldiv_norm - tbl_fsgldiv_op # DENORM / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11006) short fsgldiv_res_snan - tbl_fsgldiv_op # DENORM / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11007) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11008) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11010) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11011) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11012) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11013) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11014) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11015) short fsgldiv_res_snan - tbl_fsgldiv_op # SNAN / SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11016) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11017) short tbl_fsgldiv_op - tbl_fsgldiv_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11019) fsgldiv_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11020) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11021) fsgldiv_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11022) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11023) fsgldiv_res_operr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11024) bra.l res_operr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11025) fsgldiv_inf_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11026) bra.l fdiv_inf_load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11027) fsgldiv_zero_load:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11028) bra.l fdiv_zero_load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11029) fsgldiv_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11030) bra.l fdiv_inf_dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11032) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11033) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11034) # fadd(): emulates the fadd instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11035) # fsadd(): emulates the fadd instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11036) # fdadd(): emulates the fdadd instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11037) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11038) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11039) # addsub_scaler2() - scale the operands so they won't take exc #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11040) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11041) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11042) # res_qnan() - set QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11043) # res_snan() - set SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11044) # res_operr() - set OPERR result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11045) # scale_to_zero_src() - set src operand exponent equal to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11046) # scale_to_zero_dst() - set dst operand exponent equal to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11047) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11048) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11049) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11050) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11051) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11052) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11053) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11054) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11055) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11056) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11057) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11058) # norms into extended, single, and double precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11059) # Do addition after scaling exponents such that exception won't #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11060) # occur. Then, check result exponent to see if exception would have #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11061) # occurred. If so, return default result and maybe EXOP. Else, insert #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11062) # the correct result exponent and return. Set FPSR bits as appropriate. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11063) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11064) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11066) global fsadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11067) fsadd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11068) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11069) ori.b &s_mode*0x10,%d0 # insert sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11070) bra.b fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11072) global fdadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11073) fdadd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11074) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11075) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11077) global fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11078) fadd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11079) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11081) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11082) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11083) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11084) or.b STAG(%a6),%d1 # combine src tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11086) bne.w fadd_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11088) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11089) # ADD: norms and denorms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11090) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11091) fadd_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11092) bsr.l addsub_scaler2 # scale exponents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11094) fadd_zero_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11095) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11097) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11098) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11100) fadd.x FP_SCR0(%a6),%fp0 # execute add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11102) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11103) fmov.l %fpsr,%d1 # fetch INEX2,N,Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11105) or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11107) fbeq.w fadd_zero_exit # if result is zero, end now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11109) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11111) fmovm.x &0x01,-(%sp) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11113) mov.w 2+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11114) lsr.b &0x6,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11116) mov.w (%sp),%d2 # fetch new sign, exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11117) andi.l &0x7fff,%d2 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11118) sub.l %d0,%d2 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11120) cmp.l %d2,(tbl_fadd_ovfl.b,%pc,%d1.w*4) # is it an overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11121) bge.b fadd_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11123) cmp.l %d2,(tbl_fadd_unfl.b,%pc,%d1.w*4) # is it an underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11124) blt.w fadd_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11125) beq.w fadd_may_unfl # maybe; go find out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11127) fadd_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11128) mov.w (%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11129) andi.w &0x8000,%d1 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11130) or.w %d2,%d1 # concat sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11131) mov.w %d1,(%sp) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11133) fmovm.x (%sp)+,&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11135) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11136) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11138) fadd_zero_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11139) # fmov.s &0x00000000,%fp0 # return zero in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11140) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11142) tbl_fadd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11143) long 0x7fff # ext ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11144) long 0x407f # sgl ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11145) long 0x43ff # dbl ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11147) tbl_fadd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11148) long 0x0000 # ext unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11149) long 0x3f81 # sgl unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11150) long 0x3c01 # dbl unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11152) fadd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11153) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11155) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11156) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11157) bne.b fadd_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11159) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11160) fadd_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11161) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11162) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11163) mov.l L_SCR3(%a6),%d0 # pass prec:rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11164) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11165) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11166) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11167) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11168) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11170) fadd_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11171) mov.b L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11172) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11173) bne.b fadd_ovfl_ena_sd # no; prec = sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11175) fadd_ovfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11176) mov.w (%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11177) andi.w &0x8000,%d1 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11178) subi.l &0x6000,%d2 # add extra bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11179) andi.w &0x7fff,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11180) or.w %d2,%d1 # concat sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11181) mov.w %d1,(%sp) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11183) fmovm.x (%sp)+,&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11184) bra.b fadd_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11186) fadd_ovfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11187) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11189) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11190) andi.b &0x30,%d1 # keep rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11191) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11193) fadd.x FP_SCR0(%a6),%fp0 # execute add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11195) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11197) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11198) fmovm.x &0x01,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11199) bra.b fadd_ovfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11201) fadd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11202) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11204) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11206) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11208) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11209) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11211) fadd.x FP_SCR0(%a6),%fp0 # execute add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11213) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11214) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11216) or.l %d1,USER_FPSR(%a6) # save INEX,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11218) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11219) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11220) bne.b fadd_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11222) fadd_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11223) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11225) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11226) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11227) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11228) or.b %d0,FPSR_CC(%a6) # 'Z' bit may have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11229) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11230) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11231) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11233) fadd_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11234) fmovm.x FP_SCR1(%a6),&0x40 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11236) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11237) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11238) bne.b fadd_unfl_ena_sd # no; sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11240) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11242) fadd_unfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11243) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11245) fadd.x FP_SCR0(%a6),%fp1 # execute multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11247) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11249) fmovm.x &0x40,FP_SCR0(%a6) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11250) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11251) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11252) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11253) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11254) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11255) addi.l &0x6000,%d1 # add new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11256) andi.w &0x7fff,%d1 # clear top bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11257) or.w %d2,%d1 # concat sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11258) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11259) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11260) bra.w fadd_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11262) fadd_unfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11263) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11264) andi.b &0x30,%d1 # use only rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11265) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11267) bra.b fadd_unfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11269) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11270) # result is equal to the smallest normalized number in the selected precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11271) # if the precision is extended, this result could not have come from an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11272) # underflow that rounded up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11273) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11274) fadd_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11275) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11276) andi.b &0xc0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11277) beq.w fadd_normal # yes; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11279) mov.l 0x4(%sp),%d1 # extract hi(man)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11280) cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11281) bne.w fadd_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11283) tst.l 0x8(%sp) # is lo(man) = 0x0?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11284) bne.w fadd_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11286) btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11287) beq.w fadd_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11289) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11290) # ok, so now the result has a exponent equal to the smallest normalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11291) # exponent for the selected precision. also, the mantissa is equal to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11292) # 0x8000000000000000 and this mantissa is the result of rounding non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11293) # g,r,s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11294) # now, we must determine whether the pre-rounded result was an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11295) # rounded "up" or a normalized number rounded "down".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11296) # so, we do this be re-executing the add using RZ as the rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11297) # seeing if the new result is smaller or equal to the current result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11298) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11299) fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11301) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11302) andi.b &0xc0,%d1 # keep rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11303) ori.b &rz_mode*0x10,%d1 # insert rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11304) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11305) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11307) fadd.x FP_SCR0(%a6),%fp1 # execute add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11309) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11311) fabs.x %fp0 # compare absolute values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11312) fabs.x %fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11313) fcmp.x %fp0,%fp1 # is first result > second?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11315) fbgt.w fadd_unfl # yes; it's an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11316) bra.w fadd_normal # no; it's not an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11318) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11320) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11321) # Add: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11322) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11323) fadd_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11324) mov.w (tbl_fadd_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11325) jmp (tbl_fadd_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11327) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11328) tbl_fadd_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11329) short fadd_norm - tbl_fadd_op # NORM + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11330) short fadd_zero_src - tbl_fadd_op # NORM + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11331) short fadd_inf_src - tbl_fadd_op # NORM + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11332) short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11333) short fadd_norm - tbl_fadd_op # NORM + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11334) short fadd_res_snan - tbl_fadd_op # NORM + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11335) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11336) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11338) short fadd_zero_dst - tbl_fadd_op # ZERO + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11339) short fadd_zero_2 - tbl_fadd_op # ZERO + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11340) short fadd_inf_src - tbl_fadd_op # ZERO + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11341) short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11342) short fadd_zero_dst - tbl_fadd_op # ZERO + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11343) short fadd_res_snan - tbl_fadd_op # NORM + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11344) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11345) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11347) short fadd_inf_dst - tbl_fadd_op # INF + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11348) short fadd_inf_dst - tbl_fadd_op # INF + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11349) short fadd_inf_2 - tbl_fadd_op # INF + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11350) short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11351) short fadd_inf_dst - tbl_fadd_op # INF + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11352) short fadd_res_snan - tbl_fadd_op # NORM + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11353) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11354) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11356) short fadd_res_qnan - tbl_fadd_op # QNAN + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11357) short fadd_res_qnan - tbl_fadd_op # QNAN + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11358) short fadd_res_qnan - tbl_fadd_op # QNAN + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11359) short fadd_res_qnan - tbl_fadd_op # QNAN + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11360) short fadd_res_qnan - tbl_fadd_op # QNAN + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11361) short fadd_res_snan - tbl_fadd_op # QNAN + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11362) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11363) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11365) short fadd_norm - tbl_fadd_op # DENORM + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11366) short fadd_zero_src - tbl_fadd_op # DENORM + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11367) short fadd_inf_src - tbl_fadd_op # DENORM + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11368) short fadd_res_qnan - tbl_fadd_op # NORM + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11369) short fadd_norm - tbl_fadd_op # DENORM + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11370) short fadd_res_snan - tbl_fadd_op # NORM + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11371) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11372) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11374) short fadd_res_snan - tbl_fadd_op # SNAN + NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11375) short fadd_res_snan - tbl_fadd_op # SNAN + ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11376) short fadd_res_snan - tbl_fadd_op # SNAN + INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11377) short fadd_res_snan - tbl_fadd_op # SNAN + QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11378) short fadd_res_snan - tbl_fadd_op # SNAN + DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11379) short fadd_res_snan - tbl_fadd_op # SNAN + SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11380) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11381) short tbl_fadd_op - tbl_fadd_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11383) fadd_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11384) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11385) fadd_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11386) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11388) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11389) # both operands are ZEROes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11390) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11391) fadd_zero_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11392) mov.b SRC_EX(%a0),%d0 # are the signs opposite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11393) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11394) eor.b %d0,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11395) bmi.w fadd_zero_2_chk_rm # weed out (-ZERO)+(+ZERO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11397) # the signs are the same. so determine whether they are positive or negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11398) # and return the appropriately signed zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11399) tst.b %d0 # are ZEROes positive or negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11400) bmi.b fadd_zero_rm # negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11401) fmov.s &0x00000000,%fp0 # return +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11402) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11403) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11405) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11406) # the ZEROes have opposite signs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11407) # - Therefore, we return +ZERO if the rounding modes are RN,RZ, or RP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11408) # - -ZERO is returned in the case of RM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11409) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11410) fadd_zero_2_chk_rm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11411) mov.b 3+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11412) andi.b &0x30,%d1 # extract rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11413) cmpi.b %d1,&rm_mode*0x10 # is rnd mode == RM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11414) beq.b fadd_zero_rm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11415) fmov.s &0x00000000,%fp0 # return +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11416) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11417) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11419) fadd_zero_rm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11420) fmov.s &0x80000000,%fp0 # return -ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11421) mov.b &neg_bmask+z_bmask,FPSR_CC(%a6) # set NEG/Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11422) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11424) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11425) # one operand is a ZERO and the other is a DENORM or NORM. scale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11426) # the DENORM or NORM and jump to the regular fadd routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11427) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11428) fadd_zero_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11429) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11430) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11431) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11432) bsr.l scale_to_zero_src # scale the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11433) clr.w FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11434) clr.l FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11435) clr.l FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11436) bra.w fadd_zero_entry # go execute fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11438) fadd_zero_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11439) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11440) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11441) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11442) bsr.l scale_to_zero_dst # scale the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11443) clr.w FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11444) clr.l FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11445) clr.l FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11446) bra.w fadd_zero_entry # go execute fadd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11448) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11449) # both operands are INFs. an OPERR will result if the INFs have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11450) # different signs. else, an INF of the same sign is returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11451) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11452) fadd_inf_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11453) mov.b SRC_EX(%a0),%d0 # exclusive or the signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11454) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11455) eor.b %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11456) bmi.l res_operr # weed out (-INF)+(+INF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11458) # ok, so it's not an OPERR. but, we do have to remember to return the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11459) # src INF since that's where the 881/882 gets the j-bit from...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11461) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11462) # operands are INF and one of {ZERO, INF, DENORM, NORM}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11463) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11464) fadd_inf_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11465) fmovm.x SRC(%a0),&0x80 # return src INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11466) tst.b SRC_EX(%a0) # is INF positive?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11467) bpl.b fadd_inf_done # yes; we're done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11468) mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11469) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11471) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11472) # operands are INF and one of {ZERO, INF, DENORM, NORM}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11473) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11474) fadd_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11475) fmovm.x DST(%a1),&0x80 # return dst INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11476) tst.b DST_EX(%a1) # is INF positive?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11477) bpl.b fadd_inf_done # yes; we're done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11478) mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11479) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11481) fadd_inf_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11482) mov.b &inf_bmask,FPSR_CC(%a6) # set INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11483) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11485) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11486) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11487) # fsub(): emulates the fsub instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11488) # fssub(): emulates the fssub instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11489) # fdsub(): emulates the fdsub instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11490) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11491) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11492) # addsub_scaler2() - scale the operands so they won't take exc #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11493) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11494) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11495) # res_qnan() - set QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11496) # res_snan() - set SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11497) # res_operr() - set OPERR result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11498) # scale_to_zero_src() - set src operand exponent equal to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11499) # scale_to_zero_dst() - set dst operand exponent equal to zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11500) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11501) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11502) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11503) # a1 = pointer to extended precision destination operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11504) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11505) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11506) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11507) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11508) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11509) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11510) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11511) # norms into extended, single, and double precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11512) # Do subtraction after scaling exponents such that exception won't#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11513) # occur. Then, check result exponent to see if exception would have #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11514) # occurred. If so, return default result and maybe EXOP. Else, insert #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11515) # the correct result exponent and return. Set FPSR bits as appropriate. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11516) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11517) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11519) global fssub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11520) fssub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11521) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11522) ori.b &s_mode*0x10,%d0 # insert sgl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11523) bra.b fsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11525) global fdsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11526) fdsub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11527) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11528) ori.b &d_mode*0x10,%d0 # insert dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11530) global fsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11531) fsub:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11532) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11534) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11535) mov.b DTAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11536) lsl.b &0x3,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11537) or.b STAG(%a6),%d1 # combine src tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11539) bne.w fsub_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11541) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11542) # SUB: norms and denorms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11543) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11544) fsub_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11545) bsr.l addsub_scaler2 # scale exponents
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11547) fsub_zero_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11548) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11550) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11551) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11553) fsub.x FP_SCR0(%a6),%fp0 # execute subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11555) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11556) fmov.l %fpsr,%d1 # fetch INEX2, N, Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11558) or.l %d1,USER_FPSR(%a6) # save exc and ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11560) fbeq.w fsub_zero_exit # if result zero, end now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11562) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11564) fmovm.x &0x01,-(%sp) # save result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11566) mov.w 2+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11567) lsr.b &0x6,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11569) mov.w (%sp),%d2 # fetch new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11570) andi.l &0x7fff,%d2 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11571) sub.l %d0,%d2 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11573) cmp.l %d2,(tbl_fsub_ovfl.b,%pc,%d1.w*4) # is it an overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11574) bge.b fsub_ovfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11576) cmp.l %d2,(tbl_fsub_unfl.b,%pc,%d1.w*4) # is it an underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11577) blt.w fsub_unfl # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11578) beq.w fsub_may_unfl # maybe; go find out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11580) fsub_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11581) mov.w (%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11582) andi.w &0x8000,%d1 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11583) or.w %d2,%d1 # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11584) mov.w %d1,(%sp) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11586) fmovm.x (%sp)+,&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11588) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11589) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11591) fsub_zero_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11592) # fmov.s &0x00000000,%fp0 # return zero in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11593) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11595) tbl_fsub_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11596) long 0x7fff # ext ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11597) long 0x407f # sgl ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11598) long 0x43ff # dbl ovfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11600) tbl_fsub_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11601) long 0x0000 # ext unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11602) long 0x3f81 # sgl unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11603) long 0x3c01 # dbl unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11605) fsub_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11606) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11608) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11609) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11610) bne.b fsub_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11612) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11613) fsub_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11614) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11615) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11616) mov.l L_SCR3(%a6),%d0 # pass prec:rnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11617) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11618) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11619) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11620) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11621) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11623) fsub_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11624) mov.b L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11625) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11626) bne.b fsub_ovfl_ena_sd # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11628) fsub_ovfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11629) mov.w (%sp),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11630) andi.w &0x8000,%d1 # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11631) subi.l &0x6000,%d2 # subtract new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11632) andi.w &0x7fff,%d2 # clear top bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11633) or.w %d2,%d1 # concat sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11634) mov.w %d1,(%sp) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11636) fmovm.x (%sp)+,&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11637) bra.b fsub_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11639) fsub_ovfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11640) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11642) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11643) andi.b &0x30,%d1 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11644) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11646) fsub.x FP_SCR0(%a6),%fp0 # execute subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11648) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11650) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11651) fmovm.x &0x01,-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11652) bra.b fsub_ovfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11654) fsub_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11655) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11657) add.l &0xc,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11659) fmovm.x FP_SCR1(%a6),&0x80 # load dst op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11661) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11662) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11664) fsub.x FP_SCR0(%a6),%fp0 # execute subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11666) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11667) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11669) or.l %d1,USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11671) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11672) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11673) bne.b fsub_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11675) fsub_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11676) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11678) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11679) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11680) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11681) or.b %d0,FPSR_CC(%a6) # 'Z' may have been set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11682) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11683) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11684) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11686) fsub_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11687) fmovm.x FP_SCR1(%a6),&0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11689) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11690) andi.b &0xc0,%d1 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11691) bne.b fsub_unfl_ena_sd # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11693) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11695) fsub_unfl_ena_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11696) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11698) fsub.x FP_SCR0(%a6),%fp1 # execute subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11700) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11702) fmovm.x &0x40,FP_SCR0(%a6) # store result to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11703) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11704) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11705) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11706) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11707) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11708) addi.l &0x6000,%d1 # subtract new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11709) andi.w &0x7fff,%d1 # clear top bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11710) or.w %d2,%d1 # concat sgn,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11711) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11712) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11713) bra.w fsub_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11715) fsub_unfl_ena_sd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11716) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11717) andi.b &0x30,%d1 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11718) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11720) bra.b fsub_unfl_ena_cont
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11722) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11723) # result is equal to the smallest normalized number in the selected precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11724) # if the precision is extended, this result could not have come from an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11725) # underflow that rounded up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11726) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11727) fsub_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11728) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11729) andi.b &0xc0,%d1 # fetch rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11730) beq.w fsub_normal # yes; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11732) mov.l 0x4(%sp),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11733) cmpi.l %d1,&0x80000000 # is hi(man) = 0x80000000?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11734) bne.w fsub_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11736) tst.l 0x8(%sp) # is lo(man) = 0x0?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11737) bne.w fsub_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11739) btst &inex2_bit,FPSR_EXCEPT(%a6) # is INEX2 set?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11740) beq.w fsub_normal # no; no underflow occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11742) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11743) # ok, so now the result has a exponent equal to the smallest normalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11744) # exponent for the selected precision. also, the mantissa is equal to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11745) # 0x8000000000000000 and this mantissa is the result of rounding non-zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11746) # g,r,s.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11747) # now, we must determine whether the pre-rounded result was an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11748) # rounded "up" or a normalized number rounded "down".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11749) # so, we do this be re-executing the add using RZ as the rounding mode and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11750) # seeing if the new result is smaller or equal to the current result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11751) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11752) fmovm.x FP_SCR1(%a6),&0x40 # load dst op into fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11754) mov.l L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11755) andi.b &0xc0,%d1 # keep rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11756) ori.b &rz_mode*0x10,%d1 # insert rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11757) fmov.l %d1,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11758) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11760) fsub.x FP_SCR0(%a6),%fp1 # execute subtract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11762) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11764) fabs.x %fp0 # compare absolute values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11765) fabs.x %fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11766) fcmp.x %fp0,%fp1 # is first result > second?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11768) fbgt.w fsub_unfl # yes; it's an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11769) bra.w fsub_normal # no; it's not an underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11771) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11773) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11774) # Sub: inputs are not both normalized; what are they?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11775) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11776) fsub_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11777) mov.w (tbl_fsub_op.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11778) jmp (tbl_fsub_op.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11780) swbeg &48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11781) tbl_fsub_op:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11782) short fsub_norm - tbl_fsub_op # NORM - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11783) short fsub_zero_src - tbl_fsub_op # NORM - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11784) short fsub_inf_src - tbl_fsub_op # NORM - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11785) short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11786) short fsub_norm - tbl_fsub_op # NORM - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11787) short fsub_res_snan - tbl_fsub_op # NORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11788) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11789) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11791) short fsub_zero_dst - tbl_fsub_op # ZERO - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11792) short fsub_zero_2 - tbl_fsub_op # ZERO - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11793) short fsub_inf_src - tbl_fsub_op # ZERO - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11794) short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11795) short fsub_zero_dst - tbl_fsub_op # ZERO - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11796) short fsub_res_snan - tbl_fsub_op # NORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11797) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11798) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11800) short fsub_inf_dst - tbl_fsub_op # INF - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11801) short fsub_inf_dst - tbl_fsub_op # INF - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11802) short fsub_inf_2 - tbl_fsub_op # INF - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11803) short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11804) short fsub_inf_dst - tbl_fsub_op # INF - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11805) short fsub_res_snan - tbl_fsub_op # NORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11806) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11807) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11809) short fsub_res_qnan - tbl_fsub_op # QNAN - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11810) short fsub_res_qnan - tbl_fsub_op # QNAN - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11811) short fsub_res_qnan - tbl_fsub_op # QNAN - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11812) short fsub_res_qnan - tbl_fsub_op # QNAN - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11813) short fsub_res_qnan - tbl_fsub_op # QNAN - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11814) short fsub_res_snan - tbl_fsub_op # QNAN - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11815) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11816) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11818) short fsub_norm - tbl_fsub_op # DENORM - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11819) short fsub_zero_src - tbl_fsub_op # DENORM - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11820) short fsub_inf_src - tbl_fsub_op # DENORM - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11821) short fsub_res_qnan - tbl_fsub_op # NORM - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11822) short fsub_norm - tbl_fsub_op # DENORM - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11823) short fsub_res_snan - tbl_fsub_op # NORM - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11824) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11825) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11827) short fsub_res_snan - tbl_fsub_op # SNAN - NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11828) short fsub_res_snan - tbl_fsub_op # SNAN - ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11829) short fsub_res_snan - tbl_fsub_op # SNAN - INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11830) short fsub_res_snan - tbl_fsub_op # SNAN - QNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11831) short fsub_res_snan - tbl_fsub_op # SNAN - DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11832) short fsub_res_snan - tbl_fsub_op # SNAN - SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11833) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11834) short tbl_fsub_op - tbl_fsub_op #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11836) fsub_res_qnan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11837) bra.l res_qnan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11838) fsub_res_snan:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11839) bra.l res_snan
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11841) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11842) # both operands are ZEROes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11843) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11844) fsub_zero_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11845) mov.b SRC_EX(%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11846) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11847) eor.b %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11848) bpl.b fsub_zero_2_chk_rm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11850) # the signs are opposite, so, return a ZERO w/ the sign of the dst ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11851) tst.b %d0 # is dst negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11852) bmi.b fsub_zero_2_rm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11853) fmov.s &0x00000000,%fp0 # no; return +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11854) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11855) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11857) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11858) # the ZEROes have the same signs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11859) # - Therefore, we return +ZERO if the rounding mode is RN,RZ, or RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11860) # - -ZERO is returned in the case of RM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11861) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11862) fsub_zero_2_chk_rm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11863) mov.b 3+L_SCR3(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11864) andi.b &0x30,%d1 # extract rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11865) cmpi.b %d1,&rm_mode*0x10 # is rnd mode = RM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11866) beq.b fsub_zero_2_rm # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11867) fmov.s &0x00000000,%fp0 # no; return +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11868) mov.b &z_bmask,FPSR_CC(%a6) # set Z
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11869) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11871) fsub_zero_2_rm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11872) fmov.s &0x80000000,%fp0 # return -ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11873) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set Z/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11874) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11876) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11877) # one operand is a ZERO and the other is a DENORM or a NORM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11878) # scale the DENORM or NORM and jump to the regular fsub routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11879) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11880) fsub_zero_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11881) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11882) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11883) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11884) bsr.l scale_to_zero_src # scale the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11885) clr.w FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11886) clr.l FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11887) clr.l FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11888) bra.w fsub_zero_entry # go execute fsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11890) fsub_zero_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11891) mov.w DST_EX(%a1),FP_SCR1_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11892) mov.l DST_HI(%a1),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11893) mov.l DST_LO(%a1),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11894) bsr.l scale_to_zero_dst # scale the operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11895) clr.w FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11896) clr.l FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11897) clr.l FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11898) bra.w fsub_zero_entry # go execute fsub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11900) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11901) # both operands are INFs. an OPERR will result if the INFs have the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11902) # same signs. else,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11903) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11904) fsub_inf_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11905) mov.b SRC_EX(%a0),%d0 # exclusive or the signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11906) mov.b DST_EX(%a1),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11907) eor.b %d1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11908) bpl.l res_operr # weed out (-INF)+(+INF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11910) # ok, so it's not an OPERR. but we do have to remember to return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11911) # the src INF since that's where the 881/882 gets the j-bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11913) fsub_inf_src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11914) fmovm.x SRC(%a0),&0x80 # return src INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11915) fneg.x %fp0 # invert sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11916) fbge.w fsub_inf_done # sign is now positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11917) mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11918) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11920) fsub_inf_dst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11921) fmovm.x DST(%a1),&0x80 # return dst INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11922) tst.b DST_EX(%a1) # is INF negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11923) bpl.b fsub_inf_done # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11924) mov.b &neg_bmask+inf_bmask,FPSR_CC(%a6) # set INF/NEG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11925) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11927) fsub_inf_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11928) mov.b &inf_bmask,FPSR_CC(%a6) # set INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11929) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11931) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11932) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11933) # fsqrt(): emulates the fsqrt instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11934) # fssqrt(): emulates the fssqrt instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11935) # fdsqrt(): emulates the fdsqrt instruction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11936) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11937) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11938) # scale_sqrt() - scale the source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11939) # unf_res() - return default underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11940) # ovf_res() - return default overflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11941) # res_qnan_1op() - return QNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11942) # res_snan_1op() - return SNAN result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11943) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11944) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11945) # a0 = pointer to extended precision source operand #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11946) # d0 rnd prec,mode #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11947) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11948) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11949) # fp0 = result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11950) # fp1 = EXOP (if exception occurred) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11951) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11952) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11953) # Handle NANs, infinities, and zeroes as special cases. Divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11954) # norms/denorms into ext/sgl/dbl precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11955) # For norms/denorms, scale the exponents such that a sqrt #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11956) # instruction won't cause an exception. Use the regular fsqrt to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11957) # compute a result. Check if the regular operands would have taken #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11958) # an exception. If so, return the default overflow/underflow result #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11959) # and return the EXOP if exceptions are enabled. Else, scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11960) # result operand to the proper exponent. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11961) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11962) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11963)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11964) global fssqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11965) fssqrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11966) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11967) ori.b &s_mode*0x10,%d0 # insert sgl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11968) bra.b fsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11970) global fdsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11971) fdsqrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11972) andi.b &0x30,%d0 # clear rnd prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11973) ori.b &d_mode*0x10,%d0 # insert dbl precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11975) global fsqrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11976) fsqrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11977) mov.l %d0,L_SCR3(%a6) # store rnd info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11978) clr.w %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11979) mov.b STAG(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11980) bne.w fsqrt_not_norm # optimize on non-norm input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11982) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11983) # SQUARE ROOT: norms and denorms ONLY!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11984) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11985) fsqrt_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11986) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11987) bmi.l res_operr # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11989) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11990) bne.b fsqrt_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11992) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11993) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11995) fsqrt.x (%a0),%fp0 # execute square root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11997) fmov.l %fpsr,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11998) or.l %d1,USER_FPSR(%a6) # set N,INEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12000) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12002) fsqrt_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12003) tst.b SRC_EX(%a0) # is operand negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12004) bmi.l res_operr # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12006) andi.b &0xc0,%d0 # is precision extended?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12007) bne.b fsqrt_not_ext # no; go handle sgl or dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12009) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12010) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12011) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12013) bsr.l scale_sqrt # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12015) bra.w fsqrt_sd_normal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12017) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12018) # operand is either single or double
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12019) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12020) fsqrt_not_ext:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12021) cmpi.b %d0,&s_mode*0x10 # separate sgl/dbl prec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12022) bne.w fsqrt_dbl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12024) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12025) # operand is to be rounded to single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12026) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12027) fsqrt_sgl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12028) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12029) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12030) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12032) bsr.l scale_sqrt # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12034) cmpi.l %d0,&0x3fff-0x3f81 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12035) beq.w fsqrt_sd_may_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12036) bgt.w fsqrt_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12037) cmpi.l %d0,&0x3fff-0x407f # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12038) beq.w fsqrt_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12039) blt.w fsqrt_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12041) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12042) # operand will NOT overflow or underflow when moved in to the fp reg file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12043) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12044) fsqrt_sd_normal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12045) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12046) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12048) fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12050) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12051) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12053) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12055) fsqrt_sd_normal_exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12056) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12057) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12058) mov.w FP_SCR0_EX(%a6),%d1 # load sgn,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12059) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12060) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12061) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12062) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12063) or.w %d1,%d2 # concat old sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12064) mov.w %d2,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12065) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12066) fmovm.x FP_SCR0(%a6),&0x80 # return result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12067) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12069) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12070) # operand is to be rounded to double precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12071) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12072) fsqrt_dbl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12073) mov.w SRC_EX(%a0),FP_SCR0_EX(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12074) mov.l SRC_HI(%a0),FP_SCR0_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12075) mov.l SRC_LO(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12077) bsr.l scale_sqrt # calculate scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12079) cmpi.l %d0,&0x3fff-0x3c01 # will move in underflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12080) beq.w fsqrt_sd_may_unfl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12081) bgt.b fsqrt_sd_unfl # yes; go handle underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12082) cmpi.l %d0,&0x3fff-0x43ff # will move in overflow?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12083) beq.w fsqrt_sd_may_ovfl # maybe; go check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12084) blt.w fsqrt_sd_ovfl # yes; go handle overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12085) bra.w fsqrt_sd_normal # no; ho handle normalized op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12087) # we're on the line here and the distinguising characteristic is whether
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12088) # the exponent is 3fff or 3ffe. if it's 3ffe, then it's a safe number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12089) # elsewise fall through to underflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12090) fsqrt_sd_may_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12091) btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12092) bne.w fsqrt_sd_normal # yes, so no underflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12094) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12095) # operand WILL underflow when moved in to the fp register file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12096) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12097) fsqrt_sd_unfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12098) bset &unfl_bit,FPSR_EXCEPT(%a6) # set unfl exc bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12100) fmov.l &rz_mode*0x10,%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12101) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12103) fsqrt.x FP_SCR0(%a6),%fp0 # execute square root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12105) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12106) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12108) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12110) # if underflow or inexact is enabled, go calculate EXOP first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12111) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12112) andi.b &0x0b,%d1 # is UNFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12113) bne.b fsqrt_sd_unfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12115) fsqrt_sd_unfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12116) fmovm.x &0x80,FP_SCR0(%a6) # store out result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12118) lea FP_SCR0(%a6),%a0 # pass: result addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12119) mov.l L_SCR3(%a6),%d1 # pass: rnd prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12120) bsr.l unf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12121) or.b %d0,FPSR_CC(%a6) # set possible 'Z' ccode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12122) fmovm.x FP_SCR0(%a6),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12123) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12125) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12126) # operand will underflow AND underflow is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12127) # Therefore, we must return the result rounded to extended precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12128) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12129) fsqrt_sd_unfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12130) mov.l FP_SCR0_HI(%a6),FP_SCR1_HI(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12131) mov.l FP_SCR0_LO(%a6),FP_SCR1_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12132) mov.w FP_SCR0_EX(%a6),%d1 # load current exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12134) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12135) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12136) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12137) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12138) sub.l %d0,%d1 # subtract scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12139) addi.l &0x6000,%d1 # add new bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12140) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12141) or.w %d2,%d1 # concat new sign,new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12142) mov.w %d1,FP_SCR1_EX(%a6) # insert new exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12143) fmovm.x FP_SCR1(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12144) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12145) bra.b fsqrt_sd_unfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12147) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12148) # operand WILL overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12149) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12150) fsqrt_sd_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12151) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12152) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12154) fsqrt.x FP_SCR0(%a6),%fp0 # perform square root
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12156) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12157) fmov.l %fpsr,%d1 # save FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12159) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12161) fsqrt_sd_ovfl_tst:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12162) or.l &ovfl_inx_mask,USER_FPSR(%a6) # set ovfl/aovfl/ainex
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12164) mov.b FPCR_ENABLE(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12165) andi.b &0x13,%d1 # is OVFL or INEX enabled?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12166) bne.b fsqrt_sd_ovfl_ena # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12168) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12169) # OVFL is not enabled; therefore, we must create the default result by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12170) # calling ovf_res().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12171) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12172) fsqrt_sd_ovfl_dis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12173) btst &neg_bit,FPSR_CC(%a6) # is result negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12174) sne %d1 # set sign param accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12175) mov.l L_SCR3(%a6),%d0 # pass: prec,mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12176) bsr.l ovf_res # calculate default result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12177) or.b %d0,FPSR_CC(%a6) # set INF,N if applicable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12178) fmovm.x (%a0),&0x80 # return default result in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12179) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12181) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12182) # OVFL is enabled.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12183) # the INEX2 bit has already been updated by the round to the correct precision.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12184) # now, round to extended(and don't alter the FPSR).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12185) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12186) fsqrt_sd_ovfl_ena:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12187) mov.l %d2,-(%sp) # save d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12188) mov.w FP_SCR0_EX(%a6),%d1 # fetch {sgn,exp}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12189) mov.l %d1,%d2 # make a copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12190) andi.l &0x7fff,%d1 # strip sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12191) andi.w &0x8000,%d2 # keep old sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12192) sub.l %d0,%d1 # add scale factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12193) subi.l &0x6000,%d1 # subtract bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12194) andi.w &0x7fff,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12195) or.w %d2,%d1 # concat sign,exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12196) mov.w %d1,FP_SCR0_EX(%a6) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12197) fmovm.x FP_SCR0(%a6),&0x40 # return EXOP in fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12198) mov.l (%sp)+,%d2 # restore d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12199) bra.b fsqrt_sd_ovfl_dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12201) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12202) # the move in MAY underflow. so...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12203) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12204) fsqrt_sd_may_ovfl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12205) btst &0x0,1+FP_SCR0_EX(%a6) # is exponent 0x3fff?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12206) bne.w fsqrt_sd_ovfl # yes, so overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12208) fmov.l &0x0,%fpsr # clear FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12209) fmov.l L_SCR3(%a6),%fpcr # set FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12211) fsqrt.x FP_SCR0(%a6),%fp0 # perform absolute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12213) fmov.l %fpsr,%d1 # save status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12214) fmov.l &0x0,%fpcr # clear FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12216) or.l %d1,USER_FPSR(%a6) # save INEX2,N
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12218) fmov.x %fp0,%fp1 # make a copy of result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12219) fcmp.b %fp1,&0x1 # is |result| >= 1.b?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12220) fbge.w fsqrt_sd_ovfl_tst # yes; overflow has occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12222) # no, it didn't overflow; we have correct result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12223) bra.w fsqrt_sd_normal_exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12225) ##########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12227) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12228) # input is not normalized; what is it?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12229) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12230) fsqrt_not_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12231) cmpi.b %d1,&DENORM # weed out DENORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12232) beq.w fsqrt_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12233) cmpi.b %d1,&ZERO # weed out ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12234) beq.b fsqrt_zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12235) cmpi.b %d1,&INF # weed out INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12236) beq.b fsqrt_inf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12237) cmpi.b %d1,&SNAN # weed out SNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12238) beq.l res_snan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12239) bra.l res_qnan_1op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12241) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12242) # fsqrt(+0) = +0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12243) # fsqrt(-0) = -0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12244) # fsqrt(+INF) = +INF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12245) # fsqrt(-INF) = OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12246) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12247) fsqrt_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12248) tst.b SRC_EX(%a0) # is ZERO positive or negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12249) bmi.b fsqrt_zero_m # negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12250) fsqrt_zero_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12251) fmov.s &0x00000000,%fp0 # return +ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12252) mov.b &z_bmask,FPSR_CC(%a6) # set 'Z' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12253) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12254) fsqrt_zero_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12255) fmov.s &0x80000000,%fp0 # return -ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12256) mov.b &z_bmask+neg_bmask,FPSR_CC(%a6) # set 'Z','N' ccode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12257) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12259) fsqrt_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12260) tst.b SRC_EX(%a0) # is INF positive or negative?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12261) bmi.l res_operr # negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12262) fsqrt_inf_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12263) fmovm.x SRC(%a0),&0x80 # return +INF in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12264) mov.b &inf_bmask,FPSR_CC(%a6) # set 'I' ccode bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12265) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12267) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12268) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12269) # fetch_dreg(): fetch register according to index in d1 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12270) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12271) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12272) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12273) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12274) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12275) # d1 = index of register to fetch from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12276) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12277) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12278) # d0 = value of register fetched #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12279) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12280) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12281) # According to the index value in d1 which can range from zero #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12282) # to fifteen, load the corresponding register file value (where #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12283) # address register indexes start at 8). D0/D1/A0/A1/A6/A7 are on the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12284) # stack. The rest should still be in their original places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12285) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12286) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12288) # this routine leaves d1 intact for subsequent store_dreg calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12289) global fetch_dreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12290) fetch_dreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12291) mov.w (tbl_fdreg.b,%pc,%d1.w*2),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12292) jmp (tbl_fdreg.b,%pc,%d0.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12294) tbl_fdreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12295) short fdreg0 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12296) short fdreg1 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12297) short fdreg2 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12298) short fdreg3 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12299) short fdreg4 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12300) short fdreg5 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12301) short fdreg6 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12302) short fdreg7 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12303) short fdreg8 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12304) short fdreg9 - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12305) short fdrega - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12306) short fdregb - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12307) short fdregc - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12308) short fdregd - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12309) short fdrege - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12310) short fdregf - tbl_fdreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12312) fdreg0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12313) mov.l EXC_DREGS+0x0(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12314) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12315) fdreg1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12316) mov.l EXC_DREGS+0x4(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12317) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12318) fdreg2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12319) mov.l %d2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12320) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12321) fdreg3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12322) mov.l %d3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12323) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12324) fdreg4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12325) mov.l %d4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12326) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12327) fdreg5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12328) mov.l %d5,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12329) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12330) fdreg6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12331) mov.l %d6,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12332) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12333) fdreg7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12334) mov.l %d7,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12335) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12336) fdreg8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12337) mov.l EXC_DREGS+0x8(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12338) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12339) fdreg9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12340) mov.l EXC_DREGS+0xc(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12341) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12342) fdrega:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12343) mov.l %a2,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12344) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12345) fdregb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12346) mov.l %a3,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12347) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12348) fdregc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12349) mov.l %a4,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12350) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12351) fdregd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12352) mov.l %a5,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12353) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12354) fdrege:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12355) mov.l (%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12356) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12357) fdregf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12358) mov.l EXC_A7(%a6),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12359) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12361) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12362) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12363) # store_dreg_l(): store longword to data register specified by d1 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12364) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12365) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12366) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12367) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12368) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12369) # d0 = longowrd value to store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12370) # d1 = index of register to fetch from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12371) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12372) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12373) # (data register is updated) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12374) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12375) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12376) # According to the index value in d1, store the longword value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12377) # in d0 to the corresponding data register. D0/D1 are on the stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12378) # while the rest are in their initial places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12379) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12380) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12382) global store_dreg_l
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12383) store_dreg_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12384) mov.w (tbl_sdregl.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12385) jmp (tbl_sdregl.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12387) tbl_sdregl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12388) short sdregl0 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12389) short sdregl1 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12390) short sdregl2 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12391) short sdregl3 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12392) short sdregl4 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12393) short sdregl5 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12394) short sdregl6 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12395) short sdregl7 - tbl_sdregl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12397) sdregl0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12398) mov.l %d0,EXC_DREGS+0x0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12399) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12400) sdregl1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12401) mov.l %d0,EXC_DREGS+0x4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12402) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12403) sdregl2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12404) mov.l %d0,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12405) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12406) sdregl3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12407) mov.l %d0,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12408) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12409) sdregl4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12410) mov.l %d0,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12411) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12412) sdregl5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12413) mov.l %d0,%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12414) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12415) sdregl6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12416) mov.l %d0,%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12417) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12418) sdregl7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12419) mov.l %d0,%d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12420) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12422) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12423) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12424) # store_dreg_w(): store word to data register specified by d1 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12425) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12426) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12427) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12428) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12429) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12430) # d0 = word value to store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12431) # d1 = index of register to fetch from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12432) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12433) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12434) # (data register is updated) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12435) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12436) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12437) # According to the index value in d1, store the word value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12438) # in d0 to the corresponding data register. D0/D1 are on the stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12439) # while the rest are in their initial places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12440) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12441) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12443) global store_dreg_w
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12444) store_dreg_w:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12445) mov.w (tbl_sdregw.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12446) jmp (tbl_sdregw.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12448) tbl_sdregw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12449) short sdregw0 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12450) short sdregw1 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12451) short sdregw2 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12452) short sdregw3 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12453) short sdregw4 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12454) short sdregw5 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12455) short sdregw6 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12456) short sdregw7 - tbl_sdregw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12458) sdregw0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12459) mov.w %d0,2+EXC_DREGS+0x0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12460) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12461) sdregw1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12462) mov.w %d0,2+EXC_DREGS+0x4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12463) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12464) sdregw2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12465) mov.w %d0,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12466) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12467) sdregw3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12468) mov.w %d0,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12469) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12470) sdregw4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12471) mov.w %d0,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12472) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12473) sdregw5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12474) mov.w %d0,%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12475) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12476) sdregw6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12477) mov.w %d0,%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12478) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12479) sdregw7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12480) mov.w %d0,%d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12481) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12483) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12484) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12485) # store_dreg_b(): store byte to data register specified by d1 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12486) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12487) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12488) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12489) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12490) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12491) # d0 = byte value to store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12492) # d1 = index of register to fetch from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12493) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12494) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12495) # (data register is updated) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12496) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12497) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12498) # According to the index value in d1, store the byte value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12499) # in d0 to the corresponding data register. D0/D1 are on the stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12500) # while the rest are in their initial places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12501) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12502) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12504) global store_dreg_b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12505) store_dreg_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12506) mov.w (tbl_sdregb.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12507) jmp (tbl_sdregb.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12509) tbl_sdregb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12510) short sdregb0 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12511) short sdregb1 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12512) short sdregb2 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12513) short sdregb3 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12514) short sdregb4 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12515) short sdregb5 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12516) short sdregb6 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12517) short sdregb7 - tbl_sdregb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12519) sdregb0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12520) mov.b %d0,3+EXC_DREGS+0x0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12521) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12522) sdregb1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12523) mov.b %d0,3+EXC_DREGS+0x4(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12524) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12525) sdregb2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12526) mov.b %d0,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12527) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12528) sdregb3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12529) mov.b %d0,%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12530) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12531) sdregb4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12532) mov.b %d0,%d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12533) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12534) sdregb5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12535) mov.b %d0,%d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12536) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12537) sdregb6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12538) mov.b %d0,%d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12539) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12540) sdregb7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12541) mov.b %d0,%d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12542) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12544) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12545) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12546) # inc_areg(): increment an address register by the value in d0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12547) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12548) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12549) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12550) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12551) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12552) # d0 = amount to increment by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12553) # d1 = index of address register to increment #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12554) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12555) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12556) # (address register is updated) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12557) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12558) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12559) # Typically used for an instruction w/ a post-increment <ea>, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12560) # this routine adds the increment value in d0 to the address register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12561) # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12562) # in their original places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12563) # For a7, if the increment amount is one, then we have to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12564) # increment by two. For any a7 update, set the mia7_flag so that if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12565) # an access error exception occurs later in emulation, this address #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12566) # register update can be undone. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12567) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12568) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12570) global inc_areg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12571) inc_areg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12572) mov.w (tbl_iareg.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12573) jmp (tbl_iareg.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12575) tbl_iareg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12576) short iareg0 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12577) short iareg1 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12578) short iareg2 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12579) short iareg3 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12580) short iareg4 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12581) short iareg5 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12582) short iareg6 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12583) short iareg7 - tbl_iareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12585) iareg0: add.l %d0,EXC_DREGS+0x8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12586) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12587) iareg1: add.l %d0,EXC_DREGS+0xc(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12588) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12589) iareg2: add.l %d0,%a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12590) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12591) iareg3: add.l %d0,%a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12592) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12593) iareg4: add.l %d0,%a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12594) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12595) iareg5: add.l %d0,%a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12596) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12597) iareg6: add.l %d0,(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12598) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12599) iareg7: mov.b &mia7_flg,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12600) cmpi.b %d0,&0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12601) beq.b iareg7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12602) add.l %d0,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12603) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12604) iareg7b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12605) addq.l &0x2,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12606) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12608) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12609) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12610) # dec_areg(): decrement an address register by the value in d0 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12611) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12612) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12613) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12614) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12615) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12616) # d0 = amount to decrement by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12617) # d1 = index of address register to decrement #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12618) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12619) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12620) # (address register is updated) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12621) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12622) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12623) # Typically used for an instruction w/ a pre-decrement <ea>, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12624) # this routine adds the decrement value in d0 to the address register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12625) # specified by d1. A0/A1/A6/A7 reside on the stack. The rest reside #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12626) # in their original places. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12627) # For a7, if the decrement amount is one, then we have to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12628) # decrement by two. For any a7 update, set the mda7_flag so that if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12629) # an access error exception occurs later in emulation, this address #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12630) # register update can be undone. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12631) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12632) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12634) global dec_areg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12635) dec_areg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12636) mov.w (tbl_dareg.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12637) jmp (tbl_dareg.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12639) tbl_dareg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12640) short dareg0 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12641) short dareg1 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12642) short dareg2 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12643) short dareg3 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12644) short dareg4 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12645) short dareg5 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12646) short dareg6 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12647) short dareg7 - tbl_dareg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12649) dareg0: sub.l %d0,EXC_DREGS+0x8(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12650) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12651) dareg1: sub.l %d0,EXC_DREGS+0xc(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12652) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12653) dareg2: sub.l %d0,%a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12654) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12655) dareg3: sub.l %d0,%a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12656) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12657) dareg4: sub.l %d0,%a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12658) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12659) dareg5: sub.l %d0,%a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12660) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12661) dareg6: sub.l %d0,(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12662) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12663) dareg7: mov.b &mda7_flg,SPCOND_FLG(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12664) cmpi.b %d0,&0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12665) beq.b dareg7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12666) sub.l %d0,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12667) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12668) dareg7b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12669) subq.l &0x2,EXC_A7(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12670) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12672) ##############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12674) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12675) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12676) # load_fpn1(): load FP register value into FP_SRC(a6). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12677) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12678) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12679) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12680) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12681) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12682) # d0 = index of FP register to load #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12683) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12684) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12685) # FP_SRC(a6) = value loaded from FP register file #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12686) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12687) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12688) # Using the index in d0, load FP_SRC(a6) with a number from the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12689) # FP register file. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12690) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12691) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12693) global load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12694) load_fpn1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12695) mov.w (tbl_load_fpn1.b,%pc,%d0.w*2), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12696) jmp (tbl_load_fpn1.b,%pc,%d0.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12698) tbl_load_fpn1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12699) short load_fpn1_0 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12700) short load_fpn1_1 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12701) short load_fpn1_2 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12702) short load_fpn1_3 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12703) short load_fpn1_4 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12704) short load_fpn1_5 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12705) short load_fpn1_6 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12706) short load_fpn1_7 - tbl_load_fpn1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12708) load_fpn1_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12709) mov.l 0+EXC_FP0(%a6), 0+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12710) mov.l 4+EXC_FP0(%a6), 4+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12711) mov.l 8+EXC_FP0(%a6), 8+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12712) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12713) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12714) load_fpn1_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12715) mov.l 0+EXC_FP1(%a6), 0+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12716) mov.l 4+EXC_FP1(%a6), 4+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12717) mov.l 8+EXC_FP1(%a6), 8+FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12718) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12719) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12720) load_fpn1_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12721) fmovm.x &0x20, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12722) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12723) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12724) load_fpn1_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12725) fmovm.x &0x10, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12726) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12727) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12728) load_fpn1_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12729) fmovm.x &0x08, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12730) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12731) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12732) load_fpn1_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12733) fmovm.x &0x04, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12734) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12735) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12736) load_fpn1_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12737) fmovm.x &0x02, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12738) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12739) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12740) load_fpn1_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12741) fmovm.x &0x01, FP_SRC(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12742) lea FP_SRC(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12743) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12745) #############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12747) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12748) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12749) # load_fpn2(): load FP register value into FP_DST(a6). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12750) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12751) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12752) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12753) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12754) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12755) # d0 = index of FP register to load #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12756) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12757) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12758) # FP_DST(a6) = value loaded from FP register file #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12759) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12760) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12761) # Using the index in d0, load FP_DST(a6) with a number from the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12762) # FP register file. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12763) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12764) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12766) global load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12767) load_fpn2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12768) mov.w (tbl_load_fpn2.b,%pc,%d0.w*2), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12769) jmp (tbl_load_fpn2.b,%pc,%d0.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12771) tbl_load_fpn2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12772) short load_fpn2_0 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12773) short load_fpn2_1 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12774) short load_fpn2_2 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12775) short load_fpn2_3 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12776) short load_fpn2_4 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12777) short load_fpn2_5 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12778) short load_fpn2_6 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12779) short load_fpn2_7 - tbl_load_fpn2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12781) load_fpn2_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12782) mov.l 0+EXC_FP0(%a6), 0+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12783) mov.l 4+EXC_FP0(%a6), 4+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12784) mov.l 8+EXC_FP0(%a6), 8+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12785) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12786) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12787) load_fpn2_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12788) mov.l 0+EXC_FP1(%a6), 0+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12789) mov.l 4+EXC_FP1(%a6), 4+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12790) mov.l 8+EXC_FP1(%a6), 8+FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12791) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12792) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12793) load_fpn2_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12794) fmovm.x &0x20, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12795) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12796) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12797) load_fpn2_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12798) fmovm.x &0x10, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12799) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12800) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12801) load_fpn2_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12802) fmovm.x &0x08, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12803) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12804) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12805) load_fpn2_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12806) fmovm.x &0x04, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12807) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12808) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12809) load_fpn2_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12810) fmovm.x &0x02, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12811) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12812) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12813) load_fpn2_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12814) fmovm.x &0x01, FP_DST(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12815) lea FP_DST(%a6), %a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12816) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12818) #############################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12820) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12821) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12822) # store_fpreg(): store an fp value to the fpreg designated d0. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12823) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12824) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12825) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12826) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12827) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12828) # fp0 = extended precision value to store #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12829) # d0 = index of floating-point register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12830) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12831) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12832) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12833) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12834) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12835) # Store the value in fp0 to the FP register designated by the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12836) # value in d0. The FP number can be DENORM or SNAN so we have to be #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12837) # careful that we don't take an exception here. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12838) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12839) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12841) global store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12842) store_fpreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12843) mov.w (tbl_store_fpreg.b,%pc,%d0.w*2), %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12844) jmp (tbl_store_fpreg.b,%pc,%d0.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12846) tbl_store_fpreg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12847) short store_fpreg_0 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12848) short store_fpreg_1 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12849) short store_fpreg_2 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12850) short store_fpreg_3 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12851) short store_fpreg_4 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12852) short store_fpreg_5 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12853) short store_fpreg_6 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12854) short store_fpreg_7 - tbl_store_fpreg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12856) store_fpreg_0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12857) fmovm.x &0x80, EXC_FP0(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12858) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12859) store_fpreg_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12860) fmovm.x &0x80, EXC_FP1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12861) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12862) store_fpreg_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12863) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12864) fmovm.x (%sp)+, &0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12865) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12866) store_fpreg_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12867) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12868) fmovm.x (%sp)+, &0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12869) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12870) store_fpreg_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12871) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12872) fmovm.x (%sp)+, &0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12873) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12874) store_fpreg_5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12875) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12876) fmovm.x (%sp)+, &0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12877) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12878) store_fpreg_6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12879) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12880) fmovm.x (%sp)+, &0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12881) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12882) store_fpreg_7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12883) fmovm.x &0x01, -(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12884) fmovm.x (%sp)+, &0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12885) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12887) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12888) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12889) # get_packed(): fetch a packed operand from memory and then #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12890) # convert it to a floating-point binary number. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12891) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12892) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12893) # _dcalc_ea() - calculate the correct <ea> #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12894) # _mem_read() - fetch the packed operand from memory #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12895) # facc_in_x() - the fetch failed so jump to special exit code #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12896) # decbin() - convert packed to binary extended precision #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12897) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12898) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12899) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12900) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12901) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12902) # If no failure on _mem_read(): #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12903) # FP_SRC(a6) = packed operand now as a binary FP number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12904) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12905) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12906) # Get the correct <ea> which is the value on the exception stack #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12907) # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12908) # Then, fetch the operand from memory. If the fetch fails, exit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12909) # through facc_in_x(). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12910) # If the packed operand is a ZERO,NAN, or INF, convert it to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12911) # its binary representation here. Else, call decbin() which will #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12912) # convert the packed value to an extended precision binary value. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12913) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12914) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12916) # the stacked <ea> for packed is correct except for -(An).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12917) # the base reg must be updated for both -(An) and (An)+.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12918) global get_packed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12919) get_packed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12920) mov.l &0xc,%d0 # packed is 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12921) bsr.l _dcalc_ea # fetch <ea>; correct An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12923) lea FP_SRC(%a6),%a1 # pass: ptr to super dst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12924) mov.l &0xc,%d0 # pass: 12 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12925) bsr.l _dmem_read # read packed operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12927) tst.l %d1 # did dfetch fail?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12928) bne.l facc_in_x # yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12930) # The packed operand is an INF or a NAN if the exponent field is all ones.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12931) bfextu FP_SRC(%a6){&1:&15},%d0 # get exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12932) cmpi.w %d0,&0x7fff # INF or NAN?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12933) bne.b gp_try_zero # no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12934) rts # operand is an INF or NAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12936) # The packed operand is a zero if the mantissa is all zero, else it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12937) # a normal packed op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12938) gp_try_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12939) mov.b 3+FP_SRC(%a6),%d0 # get byte 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12940) andi.b &0x0f,%d0 # clear all but last nybble
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12941) bne.b gp_not_spec # not a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12942) tst.l FP_SRC_HI(%a6) # is lw 2 zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12943) bne.b gp_not_spec # not a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12944) tst.l FP_SRC_LO(%a6) # is lw 3 zero?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12945) bne.b gp_not_spec # not a zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12946) rts # operand is a ZERO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12947) gp_not_spec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12948) lea FP_SRC(%a6),%a0 # pass: ptr to packed op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12949) bsr.l decbin # convert to extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12950) fmovm.x &0x80,FP_SRC(%a6) # make this the srcop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12951) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12953) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12954) # decbin(): Converts normalized packed bcd value pointed to by register #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12955) # a0 to extended-precision value in fp0. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12956) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12957) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12958) # a0 = pointer to normalized packed bcd value #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12959) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12960) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12961) # fp0 = exact fp representation of the packed bcd value. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12962) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12963) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12964) # Expected is a normal bcd (i.e. non-exceptional; all inf, zero, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12965) # and NaN operands are dispatched without entering this routine) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12966) # value in 68881/882 format at location (a0). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12967) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12968) # A1. Convert the bcd exponent to binary by successive adds and #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12969) # muls. Set the sign according to SE. Subtract 16 to compensate #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12970) # for the mantissa which is to be interpreted as 17 integer #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12971) # digits, rather than 1 integer and 16 fraction digits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12972) # Note: this operation can never overflow. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12973) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12974) # A2. Convert the bcd mantissa to binary by successive #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12975) # adds and muls in FP0. Set the sign according to SM. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12976) # The mantissa digits will be converted with the decimal point #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12977) # assumed following the least-significant digit. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12978) # Note: this operation can never overflow. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12979) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12980) # A3. Count the number of leading/trailing zeros in the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12981) # bcd string. If SE is positive, count the leading zeros; #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12982) # if negative, count the trailing zeros. Set the adjusted #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12983) # exponent equal to the exponent from A1 and the zero count #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12984) # added if SM = 1 and subtracted if SM = 0. Scale the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12985) # mantissa the equivalent of forcing in the bcd value: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12986) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12987) # SM = 0 a non-zero digit in the integer position #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12988) # SM = 1 a non-zero digit in Mant0, lsd of the fraction #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12989) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12990) # this will insure that any value, regardless of its #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12991) # representation (ex. 0.1E2, 1E1, 10E0, 100E-1), is converted #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12992) # consistently. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12993) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12994) # A4. Calculate the factor 10^exp in FP1 using a table of #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12995) # 10^(2^n) values. To reduce the error in forming factors #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12996) # greater than 10^27, a directed rounding scheme is used with #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12997) # tables rounded to RN, RM, and RP, according to the table #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12998) # in the comments of the pwrten section. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12999) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13000) # A5. Form the final binary number by scaling the mantissa by #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13001) # the exponent factor. This is done by multiplying the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13002) # mantissa in FP0 by the factor in FP1 if the adjusted #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13003) # exponent sign is positive, and dividing FP0 by FP1 if #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13004) # it is negative. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13005) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13006) # Clean up and return. Check if the final mul or div was inexact. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13007) # If so, set INEX1 in USER_FPSR. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13008) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13009) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13010)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13011) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13012) # PTENRN, PTENRM, and PTENRP are arrays of powers of 10 rounded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13013) # to nearest, minus, and plus, respectively. The tables include
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13014) # 10**{1,2,4,8,16,32,64,128,256,512,1024,2048,4096}. No rounding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13015) # is required until the power is greater than 27, however, all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13016) # tables include the first 5 for ease of indexing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13017) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13018) RTABLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13019) byte 0,0,0,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13020) byte 2,3,2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13021) byte 2,3,3,2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13022) byte 3,2,2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13024) set FNIBS,7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13025) set FSTRT,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13027) set ESTRT,4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13028) set EDIGITS,2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13030) global decbin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13031) decbin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13032) mov.l 0x0(%a0),FP_SCR0_EX(%a6) # make a copy of input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13033) mov.l 0x4(%a0),FP_SCR0_HI(%a6) # so we don't alter it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13034) mov.l 0x8(%a0),FP_SCR0_LO(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13036) lea FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13038) movm.l &0x3c00,-(%sp) # save d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13039) fmovm.x &0x1,-(%sp) # save fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13040) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13041) # Calculate exponent:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13042) # 1. Copy bcd value in memory for use as a working copy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13043) # 2. Calculate absolute value of exponent in d1 by mul and add.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13044) # 3. Correct for exponent sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13045) # 4. Subtract 16 to compensate for interpreting the mant as all integer digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13046) # (i.e., all digits assumed left of the decimal point.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13047) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13048) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13049) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13050) # calc_e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13051) # (*) d0: temp digit storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13052) # (*) d1: accumulator for binary exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13053) # (*) d2: digit count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13054) # (*) d3: offset pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13055) # ( ) d4: first word of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13056) # ( ) a0: pointer to working bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13057) # ( ) a6: pointer to original bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13058) # (*) FP_SCR1: working copy of original bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13059) # (*) L_SCR1: copy of original exponent word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13060) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13061) calc_e:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13062) mov.l &EDIGITS,%d2 # # of nibbles (digits) in fraction part
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13063) mov.l &ESTRT,%d3 # counter to pick up digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13064) mov.l (%a0),%d4 # get first word of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13065) clr.l %d1 # zero d1 for accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13066) e_gd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13067) mulu.l &0xa,%d1 # mul partial product by one digit place
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13068) bfextu %d4{%d3:&4},%d0 # get the digit and zero extend into d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13069) add.l %d0,%d1 # d1 = d1 + d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13070) addq.b &4,%d3 # advance d3 to the next digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13071) dbf.w %d2,e_gd # if we have used all 3 digits, exit loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13072) btst &30,%d4 # get SE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13073) beq.b e_pos # don't negate if pos
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13074) neg.l %d1 # negate before subtracting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13075) e_pos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13076) sub.l &16,%d1 # sub to compensate for shift of mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13077) bge.b e_save # if still pos, do not neg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13078) neg.l %d1 # now negative, make pos and set SE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13079) or.l &0x40000000,%d4 # set SE in d4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13080) or.l &0x40000000,(%a0) # and in working bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13081) e_save:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13082) mov.l %d1,-(%sp) # save exp on stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13083) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13084) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13085) # Calculate mantissa:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13086) # 1. Calculate absolute value of mantissa in fp0 by mul and add.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13087) # 2. Correct for mantissa sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13088) # (i.e., all digits assumed left of the decimal point.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13089) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13090) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13091) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13092) # calc_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13093) # (*) d0: temp digit storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13094) # (*) d1: lword counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13095) # (*) d2: digit count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13096) # (*) d3: offset pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13097) # ( ) d4: words 2 and 3 of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13098) # ( ) a0: pointer to working bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13099) # ( ) a6: pointer to original bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13100) # (*) fp0: mantissa accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13101) # ( ) FP_SCR1: working copy of original bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13102) # ( ) L_SCR1: copy of original exponent word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13103) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13104) calc_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13105) mov.l &1,%d1 # word counter, init to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13106) fmov.s &0x00000000,%fp0 # accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13107) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13108) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13109) # Since the packed number has a long word between the first & second parts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13110) # get the integer digit then skip down & get the rest of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13111) # mantissa. We will unroll the loop once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13112) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13113) bfextu (%a0){&28:&4},%d0 # integer part is ls digit in long word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13114) fadd.b %d0,%fp0 # add digit to sum in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13115) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13116) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13117) # Get the rest of the mantissa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13118) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13119) loadlw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13120) mov.l (%a0,%d1.L*4),%d4 # load mantissa lonqword into d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13121) mov.l &FSTRT,%d3 # counter to pick up digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13122) mov.l &FNIBS,%d2 # reset number of digits per a0 ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13123) md2b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13124) fmul.s &0x41200000,%fp0 # fp0 = fp0 * 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13125) bfextu %d4{%d3:&4},%d0 # get the digit and zero extend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13126) fadd.b %d0,%fp0 # fp0 = fp0 + digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13127) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13128) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13129) # If all the digits (8) in that long word have been converted (d2=0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13130) # then inc d1 (=2) to point to the next long word and reset d3 to 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13131) # to initialize the digit offset, and set d2 to 7 for the digit count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13132) # else continue with this long word.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13133) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13134) addq.b &4,%d3 # advance d3 to the next digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13135) dbf.w %d2,md2b # check for last digit in this lw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13136) nextlw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13137) addq.l &1,%d1 # inc lw pointer in mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13138) cmp.l %d1,&2 # test for last lw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13139) ble.b loadlw # if not, get last one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13140) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13141) # Check the sign of the mant and make the value in fp0 the same sign.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13142) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13143) m_sign:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13144) btst &31,(%a0) # test sign of the mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13145) beq.b ap_st_z # if clear, go to append/strip zeros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13146) fneg.x %fp0 # if set, negate fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13147) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13148) # Append/strip zeros:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13149) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13150) # For adjusted exponents which have an absolute value greater than 27*,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13151) # this routine calculates the amount needed to normalize the mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13152) # for the adjusted exponent. That number is subtracted from the exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13153) # if the exp was positive, and added if it was negative. The purpose
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13154) # of this is to reduce the value of the exponent and the possibility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13155) # of error in calculation of pwrten.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13156) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13157) # 1. Branch on the sign of the adjusted exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13158) # 2p.(positive exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13159) # 2. Check M16 and the digits in lwords 2 and 3 in descending order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13160) # 3. Add one for each zero encountered until a non-zero digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13161) # 4. Subtract the count from the exp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13162) # 5. Check if the exp has crossed zero in #3 above; make the exp abs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13163) # and set SE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13164) # 6. Multiply the mantissa by 10**count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13165) # 2n.(negative exp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13166) # 2. Check the digits in lwords 3 and 2 in descending order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13167) # 3. Add one for each zero encountered until a non-zero digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13168) # 4. Add the count to the exp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13169) # 5. Check if the exp has crossed zero in #3 above; clear SE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13170) # 6. Divide the mantissa by 10**count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13171) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13172) # *Why 27? If the adjusted exponent is within -28 < expA < 28, than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13173) # any adjustment due to append/strip zeros will drive the resultane
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13174) # exponent towards zero. Since all pwrten constants with a power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13175) # of 27 or less are exact, there is no need to use this routine to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13176) # attempt to lessen the resultant exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13177) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13178) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13179) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13180) # ap_st_z:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13181) # (*) d0: temp digit storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13182) # (*) d1: zero count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13183) # (*) d2: digit count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13184) # (*) d3: offset pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13185) # ( ) d4: first word of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13186) # (*) d5: lword counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13187) # ( ) a0: pointer to working bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13188) # ( ) FP_SCR1: working copy of original bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13189) # ( ) L_SCR1: copy of original exponent word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13190) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13191) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13192) # First check the absolute value of the exponent to see if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13193) # routine is necessary. If so, then check the sign of the exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13194) # and do append (+) or strip (-) zeros accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13195) # This section handles a positive adjusted exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13196) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13197) ap_st_z:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13198) mov.l (%sp),%d1 # load expA for range test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13199) cmp.l %d1,&27 # test is with 27
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13200) ble.w pwrten # if abs(expA) <28, skip ap/st zeros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13201) btst &30,(%a0) # check sign of exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13202) bne.b ap_st_n # if neg, go to neg side
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13203) clr.l %d1 # zero count reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13204) mov.l (%a0),%d4 # load lword 1 to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13205) bfextu %d4{&28:&4},%d0 # get M16 in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13206) bne.b ap_p_fx # if M16 is non-zero, go fix exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13207) addq.l &1,%d1 # inc zero count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13208) mov.l &1,%d5 # init lword counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13209) mov.l (%a0,%d5.L*4),%d4 # get lword 2 to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13210) bne.b ap_p_cl # if lw 2 is zero, skip it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13211) addq.l &8,%d1 # and inc count by 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13212) addq.l &1,%d5 # inc lword counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13213) mov.l (%a0,%d5.L*4),%d4 # get lword 3 to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13214) ap_p_cl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13215) clr.l %d3 # init offset reg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13216) mov.l &7,%d2 # init digit counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13217) ap_p_gd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13218) bfextu %d4{%d3:&4},%d0 # get digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13219) bne.b ap_p_fx # if non-zero, go to fix exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13220) addq.l &4,%d3 # point to next digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13221) addq.l &1,%d1 # inc digit counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13222) dbf.w %d2,ap_p_gd # get next digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13223) ap_p_fx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13224) mov.l %d1,%d0 # copy counter to d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13225) mov.l (%sp),%d1 # get adjusted exp from memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13226) sub.l %d0,%d1 # subtract count from exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13227) bge.b ap_p_fm # if still pos, go to pwrten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13228) neg.l %d1 # now its neg; get abs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13229) mov.l (%a0),%d4 # load lword 1 to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13230) or.l &0x40000000,%d4 # and set SE in d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13231) or.l &0x40000000,(%a0) # and in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13232) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13233) # Calculate the mantissa multiplier to compensate for the striping of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13234) # zeros from the mantissa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13235) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13236) ap_p_fm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13237) lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13238) clr.l %d3 # init table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13239) fmov.s &0x3f800000,%fp1 # init fp1 to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13240) mov.l &3,%d2 # init d2 to count bits in counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13241) ap_p_el:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13242) asr.l &1,%d0 # shift lsb into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13243) bcc.b ap_p_en # if 1, mul fp1 by pwrten factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13244) fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13245) ap_p_en:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13246) add.l &12,%d3 # inc d3 to next rtable entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13247) tst.l %d0 # check if d0 is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13248) bne.b ap_p_el # if not, get next bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13249) fmul.x %fp1,%fp0 # mul mantissa by 10**(no_bits_shifted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13250) bra.b pwrten # go calc pwrten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13251) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13252) # This section handles a negative adjusted exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13253) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13254) ap_st_n:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13255) clr.l %d1 # clr counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13256) mov.l &2,%d5 # set up d5 to point to lword 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13257) mov.l (%a0,%d5.L*4),%d4 # get lword 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13258) bne.b ap_n_cl # if not zero, check digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13259) sub.l &1,%d5 # dec d5 to point to lword 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13260) addq.l &8,%d1 # inc counter by 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13261) mov.l (%a0,%d5.L*4),%d4 # get lword 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13262) ap_n_cl:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13263) mov.l &28,%d3 # point to last digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13264) mov.l &7,%d2 # init digit counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13265) ap_n_gd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13266) bfextu %d4{%d3:&4},%d0 # get digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13267) bne.b ap_n_fx # if non-zero, go to exp fix
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13268) subq.l &4,%d3 # point to previous digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13269) addq.l &1,%d1 # inc digit counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13270) dbf.w %d2,ap_n_gd # get next digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13271) ap_n_fx:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13272) mov.l %d1,%d0 # copy counter to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13273) mov.l (%sp),%d1 # get adjusted exp from memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13274) sub.l %d0,%d1 # subtract count from exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13275) bgt.b ap_n_fm # if still pos, go fix mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13276) neg.l %d1 # take abs of exp and clr SE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13277) mov.l (%a0),%d4 # load lword 1 to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13278) and.l &0xbfffffff,%d4 # and clr SE in d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13279) and.l &0xbfffffff,(%a0) # and in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13280) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13281) # Calculate the mantissa multiplier to compensate for the appending of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13282) # zeros to the mantissa.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13283) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13284) ap_n_fm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13285) lea.l PTENRN(%pc),%a1 # get address of power-of-ten table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13286) clr.l %d3 # init table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13287) fmov.s &0x3f800000,%fp1 # init fp1 to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13288) mov.l &3,%d2 # init d2 to count bits in counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13289) ap_n_el:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13290) asr.l &1,%d0 # shift lsb into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13291) bcc.b ap_n_en # if 1, mul fp1 by pwrten factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13292) fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13293) ap_n_en:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13294) add.l &12,%d3 # inc d3 to next rtable entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13295) tst.l %d0 # check if d0 is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13296) bne.b ap_n_el # if not, get next bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13297) fdiv.x %fp1,%fp0 # div mantissa by 10**(no_bits_shifted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13298) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13299) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13300) # Calculate power-of-ten factor from adjusted and shifted exponent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13301) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13302) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13303) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13304) # pwrten:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13305) # (*) d0: temp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13306) # ( ) d1: exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13307) # (*) d2: {FPCR[6:5],SM,SE} as index in RTABLE; temp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13308) # (*) d3: FPCR work copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13309) # ( ) d4: first word of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13310) # (*) a1: RTABLE pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13311) # calc_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13312) # (*) d0: temp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13313) # ( ) d1: exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13314) # (*) d3: PWRTxx table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13315) # ( ) a0: pointer to working copy of bcd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13316) # (*) a1: PWRTxx pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13317) # (*) fp1: power-of-ten accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13318) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13319) # Pwrten calculates the exponent factor in the selected rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13320) # according to the following table:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13321) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13322) # Sign of Mant Sign of Exp Rounding Mode PWRTEN Rounding Mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13323) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13324) # ANY ANY RN RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13325) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13326) # + + RP RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13327) # - + RP RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13328) # + - RP RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13329) # - - RP RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13330) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13331) # + + RM RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13332) # - + RM RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13333) # + - RM RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13334) # - - RM RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13335) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13336) # + + RZ RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13337) # - + RZ RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13338) # + - RZ RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13339) # - - RZ RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13340) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13341) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13342) pwrten:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13343) mov.l USER_FPCR(%a6),%d3 # get user's FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13344) bfextu %d3{&26:&2},%d2 # isolate rounding mode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13345) mov.l (%a0),%d4 # reload 1st bcd word to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13346) asl.l &2,%d2 # format d2 to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13347) bfextu %d4{&0:&2},%d0 # {FPCR[6],FPCR[5],SM,SE}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13348) add.l %d0,%d2 # in d2 as index into RTABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13349) lea.l RTABLE(%pc),%a1 # load rtable base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13350) mov.b (%a1,%d2),%d0 # load new rounding bits from table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13351) clr.l %d3 # clear d3 to force no exc and extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13352) bfins %d0,%d3{&26:&2} # stuff new rounding bits in FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13353) fmov.l %d3,%fpcr # write new FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13354) asr.l &1,%d0 # write correct PTENxx table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13355) bcc.b not_rp # to a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13356) lea.l PTENRP(%pc),%a1 # it is RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13357) bra.b calc_p # go to init section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13358) not_rp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13359) asr.l &1,%d0 # keep checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13360) bcc.b not_rm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13361) lea.l PTENRM(%pc),%a1 # it is RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13362) bra.b calc_p # go to init section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13363) not_rm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13364) lea.l PTENRN(%pc),%a1 # it is RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13365) calc_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13366) mov.l %d1,%d0 # copy exp to d0;use d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13367) bpl.b no_neg # if exp is negative,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13368) neg.l %d0 # invert it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13369) or.l &0x40000000,(%a0) # and set SE bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13370) no_neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13371) clr.l %d3 # table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13372) fmov.s &0x3f800000,%fp1 # init fp1 to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13373) e_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13374) asr.l &1,%d0 # shift next bit into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13375) bcc.b e_next # if zero, skip the mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13376) fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13377) e_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13378) add.l &12,%d3 # inc d3 to next rtable entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13379) tst.l %d0 # check if d0 is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13380) bne.b e_loop # not zero, continue shifting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13381) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13382) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13383) # Check the sign of the adjusted exp and make the value in fp0 the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13384) # same sign. If the exp was pos then multiply fp1*fp0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13385) # else divide fp0/fp1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13386) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13387) # Register Usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13388) # norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13389) # ( ) a0: pointer to working bcd value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13390) # (*) fp0: mantissa accumulator
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13391) # ( ) fp1: scaling factor - 10**(abs(exp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13392) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13393) pnorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13394) btst &30,(%a0) # test the sign of the exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13395) beq.b mul # if clear, go to multiply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13396) div:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13397) fdiv.x %fp1,%fp0 # exp is negative, so divide mant by exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13398) bra.b end_dec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13399) mul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13400) fmul.x %fp1,%fp0 # exp is positive, so multiply by exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13401) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13402) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13403) # Clean up and return with result in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13404) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13405) # If the final mul/div in decbin incurred an inex exception,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13406) # it will be inex2, but will be reported as inex1 by get_op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13407) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13408) end_dec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13409) fmov.l %fpsr,%d0 # get status register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13410) bclr &inex2_bit+8,%d0 # test for inex2 and clear it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13411) beq.b no_exc # skip this if no exc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13412) ori.w &inx1a_mask,2+USER_FPSR(%a6) # set INEX1/AINEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13413) no_exc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13414) add.l &0x4,%sp # clear 1 lw param
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13415) fmovm.x (%sp)+,&0x40 # restore fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13416) movm.l (%sp)+,&0x3c # restore d2-d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13417) fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13418) fmov.l &0x0,%fpsr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13419) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13421) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13422) # bindec(): Converts an input in extended precision format to bcd format#
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13423) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13424) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13425) # a0 = pointer to the input extended precision value in memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13426) # the input may be either normalized, unnormalized, or #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13427) # denormalized. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13428) # d0 = contains the k-factor sign-extended to 32-bits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13429) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13430) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13431) # FP_SCR0(a6) = bcd format result on the stack. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13432) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13433) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13434) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13435) # A1. Set RM and size ext; Set SIGMA = sign of input. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13436) # The k-factor is saved for use in d7. Clear the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13437) # BINDEC_FLG for separating normalized/denormalized #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13438) # input. If input is unnormalized or denormalized, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13439) # normalize it. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13440) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13441) # A2. Set X = abs(input). #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13442) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13443) # A3. Compute ILOG. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13444) # ILOG is the log base 10 of the input value. It is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13445) # approximated by adding e + 0.f when the original #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13446) # value is viewed as 2^^e * 1.f in extended precision. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13447) # This value is stored in d6. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13448) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13449) # A4. Clr INEX bit. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13450) # The operation in A3 above may have set INEX2. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13451) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13452) # A5. Set ICTR = 0; #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13453) # ICTR is a flag used in A13. It must be set before the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13454) # loop entry A6. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13455) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13456) # A6. Calculate LEN. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13457) # LEN is the number of digits to be displayed. The #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13458) # k-factor can dictate either the total number of digits, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13459) # if it is a positive number, or the number of digits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13460) # after the decimal point which are to be included as #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13461) # significant. See the 68882 manual for examples. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13462) # If LEN is computed to be greater than 17, set OPERR in #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13463) # USER_FPSR. LEN is stored in d4. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13464) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13465) # A7. Calculate SCALE. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13466) # SCALE is equal to 10^ISCALE, where ISCALE is the number #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13467) # of decimal places needed to insure LEN integer digits #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13468) # in the output before conversion to bcd. LAMBDA is the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13469) # sign of ISCALE, used in A9. Fp1 contains #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13470) # 10^^(abs(ISCALE)) using a rounding mode which is a #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13471) # function of the original rounding mode and the signs #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13472) # of ISCALE and X. A table is given in the code. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13473) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13474) # A8. Clr INEX; Force RZ. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13475) # The operation in A3 above may have set INEX2. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13476) # RZ mode is forced for the scaling operation to insure #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13477) # only one rounding error. The grs bits are collected in #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13478) # the INEX flag for use in A10. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13479) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13480) # A9. Scale X -> Y. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13481) # The mantissa is scaled to the desired number of #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13482) # significant digits. The excess digits are collected #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13483) # in INEX2. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13484) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13485) # A10. Or in INEX. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13486) # If INEX is set, round error occurred. This is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13487) # compensated for by 'or-ing' in the INEX2 flag to #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13488) # the lsb of Y. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13489) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13490) # A11. Restore original FPCR; set size ext. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13491) # Perform FINT operation in the user's rounding mode. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13492) # Keep the size to extended. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13493) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13494) # A12. Calculate YINT = FINT(Y) according to user's rounding #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13495) # mode. The FPSP routine sintd0 is used. The output #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13496) # is in fp0. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13497) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13498) # A13. Check for LEN digits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13499) # If the int operation results in more than LEN digits, #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13500) # or less than LEN -1 digits, adjust ILOG and repeat from #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13501) # A6. This test occurs only on the first pass. If the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13502) # result is exactly 10^LEN, decrement ILOG and divide #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13503) # the mantissa by 10. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13504) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13505) # A14. Convert the mantissa to bcd. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13506) # The binstr routine is used to convert the LEN digit #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13507) # mantissa to bcd in memory. The input to binstr is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13508) # to be a fraction; i.e. (mantissa)/10^LEN and adjusted #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13509) # such that the decimal point is to the left of bit 63. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13510) # The bcd digits are stored in the correct position in #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13511) # the final string area in memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13512) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13513) # A15. Convert the exponent to bcd. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13514) # As in A14 above, the exp is converted to bcd and the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13515) # digits are stored in the final string. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13516) # Test the length of the final exponent string. If the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13517) # length is 4, set operr. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13518) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13519) # A16. Write sign bits to final string. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13520) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13521) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13523) set BINDEC_FLG, EXC_TEMP # DENORM flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13525) # Constants in extended precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13526) PLOG2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13527) long 0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13528) PLOG2UP1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13529) long 0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13531) # Constants in single precision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13532) FONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13533) long 0x3F800000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13534) FTWO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13535) long 0x40000000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13536) FTEN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13537) long 0x41200000,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13538) F4933:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13539) long 0x459A2800,0x00000000,0x00000000,0x00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13541) RBDTBL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13542) byte 0,0,0,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13543) byte 3,3,2,2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13544) byte 3,2,2,3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13545) byte 2,3,3,2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13547) # Implementation Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13548) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13549) # The registers are used as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13550) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13551) # d0: scratch; LEN input to binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13552) # d1: scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13553) # d2: upper 32-bits of mantissa for binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13554) # d3: scratch;lower 32-bits of mantissa for binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13555) # d4: LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13556) # d5: LAMBDA/ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13557) # d6: ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13558) # d7: k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13559) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13560) # a1: scratch pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13561) # a2: pointer to FP_X; abs(original value) in ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13562) # fp0: scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13563) # fp1: scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13564) # fp2: scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13565) # F_SCR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13566) # F_SCR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13567) # L_SCR1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13568) # L_SCR2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13570) global bindec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13571) bindec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13572) movm.l &0x3f20,-(%sp) # {%d2-%d7/%a2}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13573) fmovm.x &0x7,-(%sp) # {%fp0-%fp2}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13575) # A1. Set RM and size ext. Set SIGMA = sign input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13576) # The k-factor is saved for use in d7. Clear BINDEC_FLG for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13577) # separating normalized/denormalized input. If the input
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13578) # is a denormalized number, set the BINDEC_FLG memory word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13579) # to signal denorm. If the input is unnormalized, normalize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13580) # the input and test for denormalized result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13581) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13582) fmov.l &rm_mode*0x10,%fpcr # set RM and ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13583) mov.l (%a0),L_SCR2(%a6) # save exponent for sign check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13584) mov.l %d0,%d7 # move k-factor to d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13586) clr.b BINDEC_FLG(%a6) # clr norm/denorm flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13587) cmpi.b STAG(%a6),&DENORM # is input a DENORM?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13588) bne.w A2_str # no; input is a NORM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13590) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13591) # Normalize the denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13592) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13593) un_de_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13594) mov.w (%a0),%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13595) and.w &0x7fff,%d0 # strip sign of normalized exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13596) mov.l 4(%a0),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13597) mov.l 8(%a0),%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13598) norm_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13599) sub.w &1,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13600) lsl.l &1,%d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13601) roxl.l &1,%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13602) tst.l %d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13603) bge.b norm_loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13604) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13605) # Test if the normalized input is denormalized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13606) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13607) tst.w %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13608) bgt.b pos_exp # if greater than zero, it is a norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13609) st BINDEC_FLG(%a6) # set flag for denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13610) pos_exp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13611) and.w &0x7fff,%d0 # strip sign of normalized exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13612) mov.w %d0,(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13613) mov.l %d1,4(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13614) mov.l %d2,8(%a0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13616) # A2. Set X = abs(input).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13617) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13618) A2_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13619) mov.l (%a0),FP_SCR1(%a6) # move input to work space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13620) mov.l 4(%a0),FP_SCR1+4(%a6) # move input to work space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13621) mov.l 8(%a0),FP_SCR1+8(%a6) # move input to work space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13622) and.l &0x7fffffff,FP_SCR1(%a6) # create abs(X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13624) # A3. Compute ILOG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13625) # ILOG is the log base 10 of the input value. It is approx-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13626) # imated by adding e + 0.f when the original value is viewed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13627) # as 2^^e * 1.f in extended precision. This value is stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13628) # in d6.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13629) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13630) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13631) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13632) # d0: k-factor/exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13633) # d2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13634) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13635) # d4: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13636) # d5: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13637) # d6: x/ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13638) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13639) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13640) # a1: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13641) # a2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13642) # fp0: x/float(ILOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13643) # fp1: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13644) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13645) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13646) # F_SCR2:Abs(X)/Abs(X) with $3fff exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13647) # L_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13648) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13650) tst.b BINDEC_FLG(%a6) # check for denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13651) beq.b A3_cont # if clr, continue with norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13652) mov.l &-4933,%d6 # force ILOG = -4933
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13653) bra.b A4_str
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13654) A3_cont:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13655) mov.w FP_SCR1(%a6),%d0 # move exp to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13656) mov.w &0x3fff,FP_SCR1(%a6) # replace exponent with 0x3fff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13657) fmov.x FP_SCR1(%a6),%fp0 # now fp0 has 1.f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13658) sub.w &0x3fff,%d0 # strip off bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13659) fadd.w %d0,%fp0 # add in exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13660) fsub.s FONE(%pc),%fp0 # subtract off 1.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13661) fbge.w pos_res # if pos, branch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13662) fmul.x PLOG2UP1(%pc),%fp0 # if neg, mul by LOG2UP1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13663) fmov.l %fp0,%d6 # put ILOG in d6 as a lword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13664) bra.b A4_str # go move out ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13665) pos_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13666) fmul.x PLOG2(%pc),%fp0 # if pos, mul by LOG2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13667) fmov.l %fp0,%d6 # put ILOG in d6 as a lword
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13670) # A4. Clr INEX bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13671) # The operation in A3 above may have set INEX2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13673) A4_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13674) fmov.l &0,%fpsr # zero all of fpsr - nothing needed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13677) # A5. Set ICTR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13678) # ICTR is a flag used in A13. It must be set before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13679) # loop entry A6. The lower word of d5 is used for ICTR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13681) clr.w %d5 # clear ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13683) # A6. Calculate LEN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13684) # LEN is the number of digits to be displayed. The k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13685) # can dictate either the total number of digits, if it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13686) # a positive number, or the number of digits after the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13687) # original decimal point which are to be included as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13688) # significant. See the 68882 manual for examples.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13689) # If LEN is computed to be greater than 17, set OPERR in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13690) # USER_FPSR. LEN is stored in d4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13691) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13692) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13693) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13694) # d0: exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13695) # d2: x/x/scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13696) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13697) # d4: exc picture/LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13698) # d5: ICTR/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13699) # d6: ILOG/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13700) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13701) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13702) # a1: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13703) # a2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13704) # fp0: float(ILOG)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13705) # fp1: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13706) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13707) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13708) # F_SCR2:Abs(X) with $3fff exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13709) # L_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13710) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13712) A6_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13713) tst.l %d7 # branch on sign of k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13714) ble.b k_neg # if k <= 0, LEN = ILOG + 1 - k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13715) mov.l %d7,%d4 # if k > 0, LEN = k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13716) bra.b len_ck # skip to LEN check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13717) k_neg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13718) mov.l %d6,%d4 # first load ILOG to d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13719) sub.l %d7,%d4 # subtract off k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13720) addq.l &1,%d4 # add in the 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13721) len_ck:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13722) tst.l %d4 # LEN check: branch on sign of LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13723) ble.b LEN_ng # if neg, set LEN = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13724) cmp.l %d4,&17 # test if LEN > 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13725) ble.b A7_str # if not, forget it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13726) mov.l &17,%d4 # set max LEN = 17
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13727) tst.l %d7 # if negative, never set OPERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13728) ble.b A7_str # if positive, continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13729) or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13730) bra.b A7_str # finished here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13731) LEN_ng:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13732) mov.l &1,%d4 # min LEN is 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13735) # A7. Calculate SCALE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13736) # SCALE is equal to 10^ISCALE, where ISCALE is the number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13737) # of decimal places needed to insure LEN integer digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13738) # in the output before conversion to bcd. LAMBDA is the sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13739) # of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13740) # the rounding mode as given in the following table (see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13741) # Coonen, p. 7.23 as ref.; however, the SCALE variable is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13742) # of opposite sign in bindec.sa from Coonen).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13743) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13744) # Initial USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13745) # FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13746) # ----------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13747) # RN 00 0 0 00/0 RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13748) # RN 00 0 1 00/0 RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13749) # RN 00 1 0 00/0 RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13750) # RN 00 1 1 00/0 RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13751) # RZ 01 0 0 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13752) # RZ 01 0 1 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13753) # RZ 01 1 0 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13754) # RZ 01 1 1 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13755) # RM 10 0 0 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13756) # RM 10 0 1 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13757) # RM 10 1 0 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13758) # RM 10 1 1 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13759) # RP 11 0 0 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13760) # RP 11 0 1 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13761) # RP 11 1 0 11/3 RP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13762) # RP 11 1 1 10/2 RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13763) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13764) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13765) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13766) # d0: exponent/scratch - final is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13767) # d2: x/0 or 24 for A9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13768) # d3: x/scratch - offset ptr into PTENRM array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13769) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13770) # d5: 0/ICTR:LAMBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13771) # d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13772) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13773) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13774) # a1: x/ptr to PTENRM array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13775) # a2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13776) # fp0: float(ILOG)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13777) # fp1: x/10^ISCALE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13778) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13779) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13780) # F_SCR2:Abs(X) with $3fff exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13781) # L_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13782) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13784) A7_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13785) tst.l %d7 # test sign of k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13786) bgt.b k_pos # if pos and > 0, skip this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13787) cmp.l %d7,%d6 # test k - ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13788) blt.b k_pos # if ILOG >= k, skip this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13789) mov.l %d7,%d6 # if ((k<0) & (ILOG < k)) ILOG = k
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13790) k_pos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13791) mov.l %d6,%d0 # calc ILOG + 1 - LEN in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13792) addq.l &1,%d0 # add the 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13793) sub.l %d4,%d0 # sub off LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13794) swap %d5 # use upper word of d5 for LAMBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13795) clr.w %d5 # set it zero initially
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13796) clr.w %d2 # set up d2 for very small case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13797) tst.l %d0 # test sign of ISCALE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13798) bge.b iscale # if pos, skip next inst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13799) addq.w &1,%d5 # if neg, set LAMBDA true
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13800) cmp.l %d0,&0xffffecd4 # test iscale <= -4908
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13801) bgt.b no_inf # if false, skip rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13802) add.l &24,%d0 # add in 24 to iscale
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13803) mov.l &24,%d2 # put 24 in d2 for A9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13804) no_inf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13805) neg.l %d0 # and take abs of ISCALE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13806) iscale:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13807) fmov.s FONE(%pc),%fp1 # init fp1 to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13808) bfextu USER_FPCR(%a6){&26:&2},%d1 # get initial rmode bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13809) lsl.w &1,%d1 # put them in bits 2:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13810) add.w %d5,%d1 # add in LAMBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13811) lsl.w &1,%d1 # put them in bits 3:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13812) tst.l L_SCR2(%a6) # test sign of original x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13813) bge.b x_pos # if pos, don't set bit 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13814) addq.l &1,%d1 # if neg, set bit 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13815) x_pos:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13816) lea.l RBDTBL(%pc),%a2 # load rbdtbl base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13817) mov.b (%a2,%d1),%d3 # load d3 with new rmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13818) lsl.l &4,%d3 # put bits in proper position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13819) fmov.l %d3,%fpcr # load bits into fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13820) lsr.l &4,%d3 # put bits in proper position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13821) tst.b %d3 # decode new rmode for pten table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13822) bne.b not_rn # if zero, it is RN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13823) lea.l PTENRN(%pc),%a1 # load a1 with RN table base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13824) bra.b rmode # exit decode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13825) not_rn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13826) lsr.b &1,%d3 # get lsb in carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13827) bcc.b not_rp2 # if carry clear, it is RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13828) lea.l PTENRP(%pc),%a1 # load a1 with RP table base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13829) bra.b rmode # exit decode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13830) not_rp2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13831) lea.l PTENRM(%pc),%a1 # load a1 with RM table base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13832) rmode:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13833) clr.l %d3 # clr table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13834) e_loop2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13835) lsr.l &1,%d0 # shift next bit into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13836) bcc.b e_next2 # if zero, skip the mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13837) fmul.x (%a1,%d3),%fp1 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13838) e_next2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13839) add.l &12,%d3 # inc d3 to next pwrten table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13840) tst.l %d0 # test if ISCALE is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13841) bne.b e_loop2 # if not, loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13843) # A8. Clr INEX; Force RZ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13844) # The operation in A3 above may have set INEX2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13845) # RZ mode is forced for the scaling operation to insure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13846) # only one rounding error. The grs bits are collected in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13847) # the INEX flag for use in A10.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13848) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13849) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13850) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13852) fmov.l &0,%fpsr # clr INEX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13853) fmov.l &rz_mode*0x10,%fpcr # set RZ rounding mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13855) # A9. Scale X -> Y.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13856) # The mantissa is scaled to the desired number of significant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13857) # digits. The excess digits are collected in INEX2. If mul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13858) # Check d2 for excess 10 exponential value. If not zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13859) # the iscale value would have caused the pwrten calculation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13860) # to overflow. Only a negative iscale can cause this, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13861) # multiply by 10^(d2), which is now only allowed to be 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13862) # with a multiply by 10^8 and 10^16, which is exact since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13863) # 10^24 is exact. If the input was denormalized, we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13864) # create a busy stack frame with the mul command and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13865) # two operands, and allow the fpu to complete the multiply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13866) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13867) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13868) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13869) # d0: FPCR with RZ mode/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13870) # d2: 0 or 24/unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13871) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13872) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13873) # d5: ICTR:LAMBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13874) # d6: ILOG/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13875) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13876) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13877) # a1: ptr to PTENRM array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13878) # a2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13879) # fp0: float(ILOG)/X adjusted for SCALE (Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13880) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13881) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13882) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13883) # F_SCR2:Abs(X) with $3fff exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13884) # L_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13885) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13887) A9_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13888) fmov.x (%a0),%fp0 # load X from memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13889) fabs.x %fp0 # use abs(X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13890) tst.w %d5 # LAMBDA is in lower word of d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13891) bne.b sc_mul # if neg (LAMBDA = 1), scale by mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13892) fdiv.x %fp1,%fp0 # calculate X / SCALE -> Y to fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13893) bra.w A10_st # branch to A10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13895) sc_mul:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13896) tst.b BINDEC_FLG(%a6) # check for denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13897) beq.w A9_norm # if norm, continue with mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13899) # for DENORM, we must calculate:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13900) # fp0 = input_op * 10^ISCALE * 10^24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13901) # since the input operand is a DENORM, we can't multiply it directly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13902) # so, we do the multiplication of the exponents and mantissas separately.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13903) # in this way, we avoid underflow on intermediate stages of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13904) # multiplication and guarantee a result without exception.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13905) fmovm.x &0x2,-(%sp) # save 10^ISCALE to stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13907) mov.w (%sp),%d3 # grab exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13908) andi.w &0x7fff,%d3 # clear sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13909) ori.w &0x8000,(%a0) # make DENORM exp negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13910) add.w (%a0),%d3 # add DENORM exp to 10^ISCALE exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13911) subi.w &0x3fff,%d3 # subtract BIAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13912) add.w 36(%a1),%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13913) subi.w &0x3fff,%d3 # subtract BIAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13914) add.w 48(%a1),%d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13915) subi.w &0x3fff,%d3 # subtract BIAS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13917) bmi.w sc_mul_err # is result is DENORM, punt!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13919) andi.w &0x8000,(%sp) # keep sign
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13920) or.w %d3,(%sp) # insert new exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13921) andi.w &0x7fff,(%a0) # clear sign bit on DENORM again
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13922) mov.l 0x8(%a0),-(%sp) # put input op mantissa on stk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13923) mov.l 0x4(%a0),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13924) mov.l &0x3fff0000,-(%sp) # force exp to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13925) fmovm.x (%sp)+,&0x80 # load normalized DENORM into fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13926) fmul.x (%sp)+,%fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13928) # fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13929) # fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13930) mov.l 36+8(%a1),-(%sp) # get 10^8 mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13931) mov.l 36+4(%a1),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13932) mov.l &0x3fff0000,-(%sp) # force exp to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13933) mov.l 48+8(%a1),-(%sp) # get 10^16 mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13934) mov.l 48+4(%a1),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13935) mov.l &0x3fff0000,-(%sp)# force exp to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13936) fmul.x (%sp)+,%fp0 # multiply fp0 by 10^8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13937) fmul.x (%sp)+,%fp0 # multiply fp0 by 10^16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13938) bra.b A10_st
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13940) sc_mul_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13941) bra.b sc_mul_err
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13943) A9_norm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13944) tst.w %d2 # test for small exp case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13945) beq.b A9_con # if zero, continue as normal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13946) fmul.x 36(%a1),%fp0 # multiply fp0 by 10^8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13947) fmul.x 48(%a1),%fp0 # multiply fp0 by 10^16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13948) A9_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13949) fmul.x %fp1,%fp0 # calculate X * SCALE -> Y to fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13951) # A10. Or in INEX.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13952) # If INEX is set, round error occurred. This is compensated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13953) # for by 'or-ing' in the INEX2 flag to the lsb of Y.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13954) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13955) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13956) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13957) # d0: FPCR with RZ mode/FPSR with INEX2 isolated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13958) # d2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13959) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13960) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13961) # d5: ICTR:LAMBDA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13962) # d6: ILOG/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13963) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13964) # a0: ptr for original operand/final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13965) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13966) # a2: x/ptr to FP_SCR1(a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13967) # fp0: Y/Y with lsb adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13968) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13969) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13971) A10_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13972) fmov.l %fpsr,%d0 # get FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13973) fmov.x %fp0,FP_SCR1(%a6) # move Y to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13974) lea.l FP_SCR1(%a6),%a2 # load a2 with ptr to FP_SCR1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13975) btst &9,%d0 # check if INEX2 set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13976) beq.b A11_st # if clear, skip rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13977) or.l &1,8(%a2) # or in 1 to lsb of mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13978) fmov.x FP_SCR1(%a6),%fp0 # write adjusted Y back to fpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13981) # A11. Restore original FPCR; set size ext.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13982) # Perform FINT operation in the user's rounding mode. Keep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13983) # the size to extended. The sintdo entry point in the sint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13984) # routine expects the FPCR value to be in USER_FPCR for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13985) # mode and precision. The original FPCR is saved in L_SCR1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13987) A11_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13988) mov.l USER_FPCR(%a6),L_SCR1(%a6) # save it for later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13989) and.l &0x00000030,USER_FPCR(%a6) # set size to ext,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13990) # ;block exceptions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13993) # A12. Calculate YINT = FINT(Y) according to user's rounding mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13994) # The FPSP routine sintd0 is used. The output is in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13995) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13996) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13997) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13998) # d0: FPSR with AINEX cleared/FPCR with size set to ext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13999) # d2: x/x/scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14000) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14001) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14002) # d5: ICTR:LAMBDA/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14003) # d6: ILOG/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14004) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14005) # a0: ptr for original operand/src ptr for sintdo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14006) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14007) # a2: ptr to FP_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14008) # a6: temp pointer to FP_SCR1(a6) - orig value saved and restored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14009) # fp0: Y/YINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14010) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14011) # fp2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14012) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14013) # F_SCR2:Y adjusted for inex/Y with original exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14014) # L_SCR1:x/original USER_FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14015) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14017) A12_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14018) movm.l &0xc0c0,-(%sp) # save regs used by sintd0 {%d0-%d1/%a0-%a1}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14019) mov.l L_SCR1(%a6),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14020) mov.l L_SCR2(%a6),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14022) lea.l FP_SCR1(%a6),%a0 # a0 is ptr to FP_SCR1(a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14023) fmov.x %fp0,(%a0) # move Y to memory at FP_SCR1(a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14024) tst.l L_SCR2(%a6) # test sign of original operand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14025) bge.b do_fint12 # if pos, use Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14026) or.l &0x80000000,(%a0) # if neg, use -Y
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14027) do_fint12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14028) mov.l USER_FPSR(%a6),-(%sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14029) # bsr sintdo # sint routine returns int in fp0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14031) fmov.l USER_FPCR(%a6),%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14032) fmov.l &0x0,%fpsr # clear the AEXC bits!!!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14033) ## mov.l USER_FPCR(%a6),%d0 # ext prec/keep rnd mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14034) ## andi.l &0x00000030,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14035) ## fmov.l %d0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14036) fint.x FP_SCR1(%a6),%fp0 # do fint()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14037) fmov.l %fpsr,%d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14038) or.w %d0,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14039) ## fmov.l &0x0,%fpcr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14040) ## fmov.l %fpsr,%d0 # don't keep ccodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14041) ## or.w %d0,FPSR_EXCEPT(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14043) mov.b (%sp),USER_FPSR(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14044) add.l &4,%sp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14046) mov.l (%sp)+,L_SCR2(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14047) mov.l (%sp)+,L_SCR1(%a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14048) movm.l (%sp)+,&0x303 # restore regs used by sint {%d0-%d1/%a0-%a1}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14050) mov.l L_SCR2(%a6),FP_SCR1(%a6) # restore original exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14051) mov.l L_SCR1(%a6),USER_FPCR(%a6) # restore user's FPCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14053) # A13. Check for LEN digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14054) # If the int operation results in more than LEN digits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14055) # or less than LEN -1 digits, adjust ILOG and repeat from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14056) # A6. This test occurs only on the first pass. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14057) # result is exactly 10^LEN, decrement ILOG and divide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14058) # the mantissa by 10. The calculation of 10^LEN cannot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14059) # be inexact, since all powers of ten up to 10^27 are exact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14060) # in extended precision, so the use of a previous power-of-ten
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14061) # table will introduce no error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14062) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14063) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14064) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14065) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14066) # d0: FPCR with size set to ext/scratch final = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14067) # d2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14068) # d3: x/scratch final = x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14069) # d4: LEN/LEN adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14070) # d5: ICTR:LAMBDA/LAMBDA:ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14071) # d6: ILOG/ILOG adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14072) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14073) # a0: pointer into memory for packed bcd string formation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14074) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14075) # a2: ptr to FP_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14076) # fp0: int portion of Y/abs(YINT) adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14077) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14078) # fp2: x/10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14079) # F_SCR1:x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14080) # F_SCR2:Y with original exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14081) # L_SCR1:original USER_FPCR/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14082) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14084) A13_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14085) swap %d5 # put ICTR in lower word of d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14086) tst.w %d5 # check if ICTR = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14087) bne not_zr # if non-zero, go to second test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14088) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14089) # Compute 10^(LEN-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14090) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14091) fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14092) mov.l %d4,%d0 # put LEN in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14093) subq.l &1,%d0 # d0 = LEN -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14094) clr.l %d3 # clr table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14095) l_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14096) lsr.l &1,%d0 # shift next bit into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14097) bcc.b l_next # if zero, skip the mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14098) fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14099) l_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14100) add.l &12,%d3 # inc d3 to next pwrten table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14101) tst.l %d0 # test if LEN is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14102) bne.b l_loop # if not, loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14103) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14104) # 10^LEN-1 is computed for this test and A14. If the input was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14105) # denormalized, check only the case in which YINT > 10^LEN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14106) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14107) tst.b BINDEC_FLG(%a6) # check if input was norm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14108) beq.b A13_con # if norm, continue with checking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14109) fabs.x %fp0 # take abs of YINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14110) bra test_2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14111) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14112) # Compare abs(YINT) to 10^(LEN-1) and 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14113) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14114) A13_con:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14115) fabs.x %fp0 # take abs of YINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14116) fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^(LEN-1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14117) fbge.w test_2 # if greater, do next test
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14118) subq.l &1,%d6 # subtract 1 from ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14119) mov.w &1,%d5 # set ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14120) fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14121) fmul.s FTEN(%pc),%fp2 # compute 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14122) bra.w A6_str # return to A6 and recompute YINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14123) test_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14124) fmul.s FTEN(%pc),%fp2 # compute 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14125) fcmp.x %fp0,%fp2 # compare abs(YINT) with 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14126) fblt.w A14_st # if less, all is ok, go to A14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14127) fbgt.w fix_ex # if greater, fix and redo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14128) fdiv.s FTEN(%pc),%fp0 # if equal, divide by 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14129) addq.l &1,%d6 # and inc ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14130) bra.b A14_st # and continue elsewhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14131) fix_ex:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14132) addq.l &1,%d6 # increment ILOG by 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14133) mov.w &1,%d5 # set ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14134) fmov.l &rm_mode*0x10,%fpcr # set rmode to RM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14135) bra.w A6_str # return to A6 and recompute YINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14136) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14137) # Since ICTR <> 0, we have already been through one adjustment,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14138) # and shouldn't have another; this is to check if abs(YINT) = 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14139) # 10^LEN is again computed using whatever table is in a1 since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14140) # value calculated cannot be inexact.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14141) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14142) not_zr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14143) fmov.s FONE(%pc),%fp2 # init fp2 to 1.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14144) mov.l %d4,%d0 # put LEN in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14145) clr.l %d3 # clr table index
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14146) z_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14147) lsr.l &1,%d0 # shift next bit into carry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14148) bcc.b z_next # if zero, skip the mul
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14149) fmul.x (%a1,%d3),%fp2 # mul by 10**(d3_bit_no)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14150) z_next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14151) add.l &12,%d3 # inc d3 to next pwrten table entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14152) tst.l %d0 # test if LEN is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14153) bne.b z_loop # if not, loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14154) fabs.x %fp0 # get abs(YINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14155) fcmp.x %fp0,%fp2 # check if abs(YINT) = 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14156) fbneq.w A14_st # if not, skip this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14157) fdiv.s FTEN(%pc),%fp0 # divide abs(YINT) by 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14158) addq.l &1,%d6 # and inc ILOG by 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14159) addq.l &1,%d4 # and inc LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14160) fmul.s FTEN(%pc),%fp2 # if LEN++, the get 10^^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14162) # A14. Convert the mantissa to bcd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14163) # The binstr routine is used to convert the LEN digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14164) # mantissa to bcd in memory. The input to binstr is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14165) # to be a fraction; i.e. (mantissa)/10^LEN and adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14166) # such that the decimal point is to the left of bit 63.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14167) # The bcd digits are stored in the correct position in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14168) # the final string area in memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14169) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14170) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14171) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14172) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14173) # d0: x/LEN call to binstr - final is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14174) # d1: x/0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14175) # d2: x/ms 32-bits of mant of abs(YINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14176) # d3: x/ls 32-bits of mant of abs(YINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14177) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14178) # d5: ICTR:LAMBDA/LAMBDA:ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14179) # d6: ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14180) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14181) # a0: pointer into memory for packed bcd string formation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14182) # /ptr to first mantissa byte in result string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14183) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14184) # a2: ptr to FP_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14185) # fp0: int portion of Y/abs(YINT) adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14186) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14187) # fp2: 10^LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14188) # F_SCR1:x/Work area for final result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14189) # F_SCR2:Y with original exponent/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14190) # L_SCR1:original USER_FPCR/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14191) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14193) A14_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14194) fmov.l &rz_mode*0x10,%fpcr # force rz for conversion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14195) fdiv.x %fp2,%fp0 # divide abs(YINT) by 10^LEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14196) lea.l FP_SCR0(%a6),%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14197) fmov.x %fp0,(%a0) # move abs(YINT)/10^LEN to memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14198) mov.l 4(%a0),%d2 # move 2nd word of FP_RES to d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14199) mov.l 8(%a0),%d3 # move 3rd word of FP_RES to d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14200) clr.l 4(%a0) # zero word 2 of FP_RES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14201) clr.l 8(%a0) # zero word 3 of FP_RES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14202) mov.l (%a0),%d0 # move exponent to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14203) swap %d0 # put exponent in lower word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14204) beq.b no_sft # if zero, don't shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14205) sub.l &0x3ffd,%d0 # sub bias less 2 to make fract
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14206) tst.l %d0 # check if > 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14207) bgt.b no_sft # if so, don't shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14208) neg.l %d0 # make exp positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14209) m_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14210) lsr.l &1,%d2 # shift d2:d3 right, add 0s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14211) roxr.l &1,%d3 # the number of places
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14212) dbf.w %d0,m_loop # given in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14213) no_sft:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14214) tst.l %d2 # check for mantissa of zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14215) bne.b no_zr # if not, go on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14216) tst.l %d3 # continue zero check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14217) beq.b zer_m # if zero, go directly to binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14218) no_zr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14219) clr.l %d1 # put zero in d1 for addx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14220) add.l &0x00000080,%d3 # inc at bit 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14221) addx.l %d1,%d2 # continue inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14222) and.l &0xffffff80,%d3 # strip off lsb not used by 882
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14223) zer_m:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14224) mov.l %d4,%d0 # put LEN in d0 for binstr call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14225) addq.l &3,%a0 # a0 points to M16 byte in result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14226) bsr binstr # call binstr to convert mant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14229) # A15. Convert the exponent to bcd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14230) # As in A14 above, the exp is converted to bcd and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14231) # digits are stored in the final string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14232) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14233) # Digits are stored in L_SCR1(a6) on return from BINDEC as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14234) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14235) # 32 16 15 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14236) # -----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14237) # | 0 | e3 | e2 | e1 | e4 | X | X | X |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14238) # -----------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14239) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14240) # And are moved into their proper places in FP_SCR0. If digit e4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14241) # is non-zero, OPERR is signaled. In all cases, all 4 digits are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14242) # written as specified in the 881/882 manual for packed decimal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14243) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14244) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14245) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14246) # d0: x/LEN call to binstr - final is 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14247) # d1: x/scratch (0);shift count for final exponent packing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14248) # d2: x/ms 32-bits of exp fraction/scratch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14249) # d3: x/ls 32-bits of exp fraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14250) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14251) # d5: ICTR:LAMBDA/LAMBDA:ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14252) # d6: ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14253) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14254) # a0: ptr to result string/ptr to L_SCR1(a6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14255) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14256) # a2: ptr to FP_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14257) # fp0: abs(YINT) adjusted/float(ILOG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14258) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14259) # fp2: 10^LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14260) # F_SCR1:Work area for final result/BCD result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14261) # F_SCR2:Y with original exponent/ILOG/10^4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14262) # L_SCR1:original USER_FPCR/Exponent digits on return from binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14263) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14265) A15_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14266) tst.b BINDEC_FLG(%a6) # check for denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14267) beq.b not_denorm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14268) ftest.x %fp0 # test for zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14269) fbeq.w den_zero # if zero, use k-factor or 4933
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14270) fmov.l %d6,%fp0 # float ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14271) fabs.x %fp0 # get abs of ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14272) bra.b convrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14273) den_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14274) tst.l %d7 # check sign of the k-factor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14275) blt.b use_ilog # if negative, use ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14276) fmov.s F4933(%pc),%fp0 # force exponent to 4933
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14277) bra.b convrt # do it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14278) use_ilog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14279) fmov.l %d6,%fp0 # float ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14280) fabs.x %fp0 # get abs of ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14281) bra.b convrt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14282) not_denorm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14283) ftest.x %fp0 # test for zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14284) fbneq.w not_zero # if zero, force exponent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14285) fmov.s FONE(%pc),%fp0 # force exponent to 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14286) bra.b convrt # do it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14287) not_zero:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14288) fmov.l %d6,%fp0 # float ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14289) fabs.x %fp0 # get abs of ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14290) convrt:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14291) fdiv.x 24(%a1),%fp0 # compute ILOG/10^4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14292) fmov.x %fp0,FP_SCR1(%a6) # store fp0 in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14293) mov.l 4(%a2),%d2 # move word 2 to d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14294) mov.l 8(%a2),%d3 # move word 3 to d3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14295) mov.w (%a2),%d0 # move exp to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14296) beq.b x_loop_fin # if zero, skip the shift
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14297) sub.w &0x3ffd,%d0 # subtract off bias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14298) neg.w %d0 # make exp positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14299) x_loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14300) lsr.l &1,%d2 # shift d2:d3 right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14301) roxr.l &1,%d3 # the number of places
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14302) dbf.w %d0,x_loop # given in d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14303) x_loop_fin:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14304) clr.l %d1 # put zero in d1 for addx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14305) add.l &0x00000080,%d3 # inc at bit 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14306) addx.l %d1,%d2 # continue inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14307) and.l &0xffffff80,%d3 # strip off lsb not used by 882
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14308) mov.l &4,%d0 # put 4 in d0 for binstr call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14309) lea.l L_SCR1(%a6),%a0 # a0 is ptr to L_SCR1 for exp digits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14310) bsr binstr # call binstr to convert exp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14311) mov.l L_SCR1(%a6),%d0 # load L_SCR1 lword to d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14312) mov.l &12,%d1 # use d1 for shift count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14313) lsr.l %d1,%d0 # shift d0 right by 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14314) bfins %d0,FP_SCR0(%a6){&4:&12} # put e3:e2:e1 in FP_SCR0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14315) lsr.l %d1,%d0 # shift d0 right by 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14316) bfins %d0,FP_SCR0(%a6){&16:&4} # put e4 in FP_SCR0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14317) tst.b %d0 # check if e4 is zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14318) beq.b A16_st # if zero, skip rest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14319) or.l &opaop_mask,USER_FPSR(%a6) # set OPERR & AIOP in USER_FPSR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14322) # A16. Write sign bits to final string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14323) # Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14324) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14325) # Register usage:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14326) # Input/Output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14327) # d0: x/scratch - final is x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14328) # d2: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14329) # d3: x/x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14330) # d4: LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14331) # d5: ICTR:LAMBDA/LAMBDA:ICTR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14332) # d6: ILOG/ILOG adjusted
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14333) # d7: k-factor/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14334) # a0: ptr to L_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14335) # a1: ptr to PTENxx array/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14336) # a2: ptr to FP_SCR1(a6)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14337) # fp0: float(ILOG)/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14338) # fp1: 10^ISCALE/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14339) # fp2: 10^LEN/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14340) # F_SCR1:BCD result with correct signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14341) # F_SCR2:ILOG/10^4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14342) # L_SCR1:Exponent digits on return from binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14343) # L_SCR2:first word of X packed/Unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14345) A16_st:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14346) clr.l %d0 # clr d0 for collection of signs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14347) and.b &0x0f,FP_SCR0(%a6) # clear first nibble of FP_SCR0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14348) tst.l L_SCR2(%a6) # check sign of original mantissa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14349) bge.b mant_p # if pos, don't set SM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14350) mov.l &2,%d0 # move 2 in to d0 for SM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14351) mant_p:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14352) tst.l %d6 # check sign of ILOG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14353) bge.b wr_sgn # if pos, don't set SE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14354) addq.l &1,%d0 # set bit 0 in d0 for SE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14355) wr_sgn:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14356) bfins %d0,FP_SCR0(%a6){&0:&2} # insert SM and SE into FP_SCR0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14358) # Clean up and restore all registers used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14360) fmov.l &0,%fpsr # clear possible inex2/ainex bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14361) fmovm.x (%sp)+,&0xe0 # {%fp0-%fp2}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14362) movm.l (%sp)+,&0x4fc # {%d2-%d7/%a2}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14363) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14365) global PTENRN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14366) PTENRN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14367) long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14368) long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14369) long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14370) long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14371) long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14372) long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14373) long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14374) long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14375) long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14376) long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14377) long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14378) long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14379) long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14381) global PTENRP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14382) PTENRP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14383) long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14384) long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14385) long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14386) long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14387) long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14388) long 0x40690000,0x9DC5ADA8,0x2B70B59E # 10 ^ 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14389) long 0x40D30000,0xC2781F49,0xFFCFA6D6 # 10 ^ 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14390) long 0x41A80000,0x93BA47C9,0x80E98CE0 # 10 ^ 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14391) long 0x43510000,0xAA7EEBFB,0x9DF9DE8E # 10 ^ 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14392) long 0x46A30000,0xE319A0AE,0xA60E91C7 # 10 ^ 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14393) long 0x4D480000,0xC9767586,0x81750C18 # 10 ^ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14394) long 0x5A920000,0x9E8B3B5D,0xC53D5DE5 # 10 ^ 2048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14395) long 0x75250000,0xC4605202,0x8A20979B # 10 ^ 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14397) global PTENRM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14398) PTENRM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14399) long 0x40020000,0xA0000000,0x00000000 # 10 ^ 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14400) long 0x40050000,0xC8000000,0x00000000 # 10 ^ 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14401) long 0x400C0000,0x9C400000,0x00000000 # 10 ^ 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14402) long 0x40190000,0xBEBC2000,0x00000000 # 10 ^ 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14403) long 0x40340000,0x8E1BC9BF,0x04000000 # 10 ^ 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14404) long 0x40690000,0x9DC5ADA8,0x2B70B59D # 10 ^ 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14405) long 0x40D30000,0xC2781F49,0xFFCFA6D5 # 10 ^ 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14406) long 0x41A80000,0x93BA47C9,0x80E98CDF # 10 ^ 128
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14407) long 0x43510000,0xAA7EEBFB,0x9DF9DE8D # 10 ^ 256
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14408) long 0x46A30000,0xE319A0AE,0xA60E91C6 # 10 ^ 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14409) long 0x4D480000,0xC9767586,0x81750C17 # 10 ^ 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14410) long 0x5A920000,0x9E8B3B5D,0xC53D5DE4 # 10 ^ 2048
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14411) long 0x75250000,0xC4605202,0x8A20979A # 10 ^ 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14413) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14414) # binstr(): Converts a 64-bit binary integer to bcd. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14415) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14416) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14417) # d2:d3 = 64-bit binary integer #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14418) # d0 = desired length (LEN) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14419) # a0 = pointer to start in memory for bcd characters #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14420) # (This pointer must point to byte 4 of the first #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14421) # lword of the packed decimal memory string.) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14422) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14423) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14424) # a0 = pointer to LEN bcd digits representing the 64-bit integer. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14425) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14426) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14427) # The 64-bit binary is assumed to have a decimal point before #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14428) # bit 63. The fraction is multiplied by 10 using a mul by 2 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14429) # shift and a mul by 8 shift. The bits shifted out of the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14430) # msb form a decimal digit. This process is iterated until #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14431) # LEN digits are formed. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14432) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14433) # A1. Init d7 to 1. D7 is the byte digit counter, and if 1, the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14434) # digit formed will be assumed the least significant. This is #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14435) # to force the first byte formed to have a 0 in the upper 4 bits. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14436) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14437) # A2. Beginning of the loop: #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14438) # Copy the fraction in d2:d3 to d4:d5. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14439) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14440) # A3. Multiply the fraction in d2:d3 by 8 using bit-field #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14441) # extracts and shifts. The three msbs from d2 will go into d1. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14442) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14443) # A4. Multiply the fraction in d4:d5 by 2 using shifts. The msb #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14444) # will be collected by the carry. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14445) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14446) # A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5 #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14447) # into d2:d3. D1 will contain the bcd digit formed. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14448) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14449) # A6. Test d7. If zero, the digit formed is the ms digit. If non- #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14450) # zero, it is the ls digit. Put the digit in its place in the #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14451) # upper word of d0. If it is the ls digit, write the word #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14452) # from d0 to memory. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14453) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14454) # A7. Decrement d6 (LEN counter) and repeat the loop until zero. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14455) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14456) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14458) # Implementation Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14459) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14460) # The registers are used as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14461) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14462) # d0: LEN counter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14463) # d1: temp used to form the digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14464) # d2: upper 32-bits of fraction for mul by 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14465) # d3: lower 32-bits of fraction for mul by 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14466) # d4: upper 32-bits of fraction for mul by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14467) # d5: lower 32-bits of fraction for mul by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14468) # d6: temp for bit-field extracts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14469) # d7: byte digit formation word;digit count {0,1}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14470) # a0: pointer into memory for packed bcd string formation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14471) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14473) global binstr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14474) binstr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14475) movm.l &0xff00,-(%sp) # {%d0-%d7}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14477) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14478) # A1: Init d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14479) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14480) mov.l &1,%d7 # init d7 for second digit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14481) subq.l &1,%d0 # for dbf d0 would have LEN+1 passes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14482) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14483) # A2. Copy d2:d3 to d4:d5. Start loop.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14484) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14485) loop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14486) mov.l %d2,%d4 # copy the fraction before muls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14487) mov.l %d3,%d5 # to d4:d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14488) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14489) # A3. Multiply d2:d3 by 8; extract msbs into d1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14490) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14491) bfextu %d2{&0:&3},%d1 # copy 3 msbs of d2 into d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14492) asl.l &3,%d2 # shift d2 left by 3 places
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14493) bfextu %d3{&0:&3},%d6 # copy 3 msbs of d3 into d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14494) asl.l &3,%d3 # shift d3 left by 3 places
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14495) or.l %d6,%d2 # or in msbs from d3 into d2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14496) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14497) # A4. Multiply d4:d5 by 2; add carry out to d1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14498) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14499) asl.l &1,%d5 # mul d5 by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14500) roxl.l &1,%d4 # mul d4 by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14501) swap %d6 # put 0 in d6 lower word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14502) addx.w %d6,%d1 # add in extend from mul by 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14503) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14504) # A5. Add mul by 8 to mul by 2. D1 contains the digit formed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14505) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14506) add.l %d5,%d3 # add lower 32 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14507) nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14508) addx.l %d4,%d2 # add with extend upper 32 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14509) nop # ERRATA FIX #13 (Rev. 1.2 6/6/90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14510) addx.w %d6,%d1 # add in extend from add to d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14511) swap %d6 # with d6 = 0; put 0 in upper word
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14512) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14513) # A6. Test d7 and branch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14514) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14515) tst.w %d7 # if zero, store digit & to loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14516) beq.b first_d # if non-zero, form byte & write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14517) sec_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14518) swap %d7 # bring first digit to word d7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14519) asl.w &4,%d7 # first digit in upper 4 bits d7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14520) add.w %d1,%d7 # add in ls digit to d7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14521) mov.b %d7,(%a0)+ # store d7b byte in memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14522) swap %d7 # put LEN counter in word d7a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14523) clr.w %d7 # set d7a to signal no digits done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14524) dbf.w %d0,loop # do loop some more!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14525) bra.b end_bstr # finished, so exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14526) first_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14527) swap %d7 # put digit word in d7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14528) mov.w %d1,%d7 # put new digit in d7b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14529) swap %d7 # put LEN counter in word d7a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14530) addq.w &1,%d7 # set d7a to signal first digit done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14531) dbf.w %d0,loop # do loop some more!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14532) swap %d7 # put last digit in string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14533) lsl.w &4,%d7 # move it to upper 4 bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14534) mov.b %d7,(%a0)+ # store it in memory string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14535) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14536) # Clean up and return with result in fp0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14537) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14538) end_bstr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14539) movm.l (%sp)+,&0xff # {%d0-%d7}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14540) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14542) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14543) # XDEF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14544) # facc_in_b(): dmem_read_byte failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14545) # facc_in_w(): dmem_read_word failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14546) # facc_in_l(): dmem_read_long failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14547) # facc_in_d(): dmem_read of dbl prec failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14548) # facc_in_x(): dmem_read of ext prec failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14549) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14550) # facc_out_b(): dmem_write_byte failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14551) # facc_out_w(): dmem_write_word failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14552) # facc_out_l(): dmem_write_long failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14553) # facc_out_d(): dmem_write of dbl prec failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14554) # facc_out_x(): dmem_write of ext prec failed #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14555) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14556) # XREF **************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14557) # _real_access() - exit through access error handler #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14558) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14559) # INPUT *************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14560) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14561) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14562) # OUTPUT ************************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14563) # None #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14564) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14565) # ALGORITHM *********************************************************** #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14566) # Flow jumps here when an FP data fetch call gets an error #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14567) # result. This means the operating system wants an access error frame #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14568) # made out of the current exception stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14569) # So, we first call restore() which makes sure that any updated #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14570) # -(an)+ register gets returned to its pre-exception value and then #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14571) # we change the stack to an access error stack frame. #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14572) # #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14573) #########################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14575) facc_in_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14576) movq.l &0x1,%d0 # one byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14577) bsr.w restore # fix An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14579) mov.w &0x0121,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14580) bra.w facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14582) facc_in_w:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14583) movq.l &0x2,%d0 # two bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14584) bsr.w restore # fix An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14586) mov.w &0x0141,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14587) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14589) facc_in_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14590) movq.l &0x4,%d0 # four bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14591) bsr.w restore # fix An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14593) mov.w &0x0101,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14594) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14596) facc_in_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14597) movq.l &0x8,%d0 # eight bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14598) bsr.w restore # fix An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14600) mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14601) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14603) facc_in_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14604) movq.l &0xc,%d0 # twelve bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14605) bsr.w restore # fix An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14607) mov.w &0x0161,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14608) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14610) ################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14612) facc_out_b:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14613) movq.l &0x1,%d0 # one byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14614) bsr.w restore # restore An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14616) mov.w &0x00a1,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14617) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14619) facc_out_w:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14620) movq.l &0x2,%d0 # two bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14621) bsr.w restore # restore An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14623) mov.w &0x00c1,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14624) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14626) facc_out_l:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14627) movq.l &0x4,%d0 # four bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14628) bsr.w restore # restore An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14630) mov.w &0x0081,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14631) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14633) facc_out_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14634) movq.l &0x8,%d0 # eight bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14635) bsr.w restore # restore An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14637) mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14638) bra.b facc_finish
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14640) facc_out_x:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14641) mov.l &0xc,%d0 # twelve bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14642) bsr.w restore # restore An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14644) mov.w &0x00e1,EXC_VOFF(%a6) # set FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14646) # here's where we actually create the access error frame from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14647) # current exception stack frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14648) facc_finish:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14649) mov.l USER_FPIAR(%a6),EXC_PC(%a6) # store current PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14651) fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14652) fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14653) movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14655) unlk %a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14657) mov.l (%sp),-(%sp) # store SR, hi(PC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14658) mov.l 0x8(%sp),0x4(%sp) # store lo(PC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14659) mov.l 0xc(%sp),0x8(%sp) # store EA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14660) mov.l &0x00000001,0xc(%sp) # store FSLW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14661) mov.w 0x6(%sp),0xc(%sp) # fix FSLW (size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14662) mov.w &0x4008,0x6(%sp) # store voff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14664) btst &0x5,(%sp) # supervisor or user mode?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14665) beq.b facc_out2 # user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14666) bset &0x2,0xd(%sp) # set supervisor TM bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14668) facc_out2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14669) bra.l _real_access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14671) ##################################################################
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14673) # if the effective addressing mode was predecrement or postincrement,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14674) # the emulation has already changed its value to the correct post-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14675) # instruction value. but since we're exiting to the access error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14676) # handler, then AN must be returned to its pre-instruction value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14677) # we do that here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14678) restore:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14679) mov.b EXC_OPWORD+0x1(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14680) andi.b &0x38,%d1 # extract opmode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14681) cmpi.b %d1,&0x18 # postinc?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14682) beq.w rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14683) cmpi.b %d1,&0x20 # predec?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14684) beq.w rest_dec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14685) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14687) rest_inc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14688) mov.b EXC_OPWORD+0x1(%a6),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14689) andi.w &0x0007,%d1 # fetch An
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14691) mov.w (tbl_rest_inc.b,%pc,%d1.w*2),%d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14692) jmp (tbl_rest_inc.b,%pc,%d1.w*1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14694) tbl_rest_inc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14695) short ri_a0 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14696) short ri_a1 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14697) short ri_a2 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14698) short ri_a3 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14699) short ri_a4 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14700) short ri_a5 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14701) short ri_a6 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14702) short ri_a7 - tbl_rest_inc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14704) ri_a0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14705) sub.l %d0,EXC_DREGS+0x8(%a6) # fix stacked a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14706) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14707) ri_a1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14708) sub.l %d0,EXC_DREGS+0xc(%a6) # fix stacked a1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14709) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14710) ri_a2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14711) sub.l %d0,%a2 # fix a2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14712) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14713) ri_a3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14714) sub.l %d0,%a3 # fix a3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14715) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14716) ri_a4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14717) sub.l %d0,%a4 # fix a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14718) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14719) ri_a5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14720) sub.l %d0,%a5 # fix a5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14721) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14722) ri_a6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14723) sub.l %d0,(%a6) # fix stacked a6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14724) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14725) # if it's a fmove out instruction, we don't have to fix a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14726) # because we hadn't changed it yet. if it's an opclass two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14727) # instruction (data moved in) and the exception was in supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14728) # mode, then also also wasn't updated. if it was user mode, then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14729) # restore the correct a7 which is in the USP currently.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14730) ri_a7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14731) cmpi.b EXC_VOFF(%a6),&0x30 # move in or out?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14732) bne.b ri_a7_done # out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14734) btst &0x5,EXC_SR(%a6) # user or supervisor?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14735) bne.b ri_a7_done # supervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14736) movc %usp,%a0 # restore USP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14737) sub.l %d0,%a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14738) movc %a0,%usp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14739) ri_a7_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14740) rts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14742) # need to invert adjustment value if the <ea> was predec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14743) rest_dec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14744) neg.l %d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14745) bra.b rest_inc