summaryrefslogtreecommitdiffstats
path: root/arch/m68k/ifpsp060/src/pfpsp.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/ifpsp060/src/pfpsp.S')
-rw-r--r--arch/m68k/ifpsp060/src/pfpsp.S14745
1 files changed, 14745 insertions, 0 deletions
diff --git a/arch/m68k/ifpsp060/src/pfpsp.S b/arch/m68k/ifpsp060/src/pfpsp.S
new file mode 100644
index 000000000000..0c997c436beb
--- /dev/null
+++ b/arch/m68k/ifpsp060/src/pfpsp.S
@@ -0,0 +1,14745 @@
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
+M68000 Hi-Performance Microprocessor Division
+M68060 Software Package
+Production Release P1.00 -- October 10, 1994
+
+M68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved.
+
+THE SOFTWARE is provided on an "AS IS" basis and without warranty.
+To the maximum extent permitted by applicable law,
+MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
+INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+and any warranty against infringement with regard to the SOFTWARE
+(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials.
+
+To the maximum extent permitted by applicable law,
+IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
+BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
+ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
+Motorola assumes no responsibility for the maintenance and support of the SOFTWARE.
+
+You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE
+so long as this entire notice is retained without alteration in any modified and/or
+redistributed versions, and that such modified versions are clearly identified as such.
+No licenses are granted by implication, estoppel or otherwise under any patents
+or trademarks of Motorola, Inc.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# freal.s:
+# This file is appended to the top of the 060FPSP package
+# and contains the entry points into the package. The user, in
+# effect, branches to one of the branch table entries located
+# after _060FPSP_TABLE.
+# Also, subroutine stubs exist in this file (_fpsp_done for
+# example) that are referenced by the FPSP package itself in order
+# to call a given routine. The stub routine actually performs the
+# callout. The FPSP code does a "bsr" to the stub routine. This
+# extra layer of hierarchy adds a slight performance penalty but
+# it makes the FPSP code easier to read and more mainatinable.
+#
+
+set _off_bsun, 0x00
+set _off_snan, 0x04
+set _off_operr, 0x08
+set _off_ovfl, 0x0c
+set _off_unfl, 0x10
+set _off_dz, 0x14
+set _off_inex, 0x18
+set _off_fline, 0x1c
+set _off_fpu_dis, 0x20
+set _off_trap, 0x24
+set _off_trace, 0x28
+set _off_access, 0x2c
+set _off_done, 0x30
+
+set _off_imr, 0x40
+set _off_dmr, 0x44
+set _off_dmw, 0x48
+set _off_irw, 0x4c
+set _off_irl, 0x50
+set _off_drb, 0x54
+set _off_drw, 0x58
+set _off_drl, 0x5c
+set _off_dwb, 0x60
+set _off_dww, 0x64
+set _off_dwl, 0x68
+
+_060FPSP_TABLE:
+
+###############################################################
+
+# Here's the table of ENTRY POINTS for those linking the package.
+ bra.l _fpsp_snan
+ short 0x0000
+ bra.l _fpsp_operr
+ short 0x0000
+ bra.l _fpsp_ovfl
+ short 0x0000
+ bra.l _fpsp_unfl
+ short 0x0000
+ bra.l _fpsp_dz
+ short 0x0000
+ bra.l _fpsp_inex
+ short 0x0000
+ bra.l _fpsp_fline
+ short 0x0000
+ bra.l _fpsp_unsupp
+ short 0x0000
+ bra.l _fpsp_effadd
+ short 0x0000
+
+ space 56
+
+###############################################################
+ global _fpsp_done
+_fpsp_done:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_done,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_ovfl
+_real_ovfl:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_ovfl,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_unfl
+_real_unfl:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_unfl,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_inex
+_real_inex:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_inex,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_bsun
+_real_bsun:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_bsun,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_operr
+_real_operr:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_operr,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_snan
+_real_snan:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_snan,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_dz
+_real_dz:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dz,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_fline
+_real_fline:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_fline,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_fpu_disabled
+_real_fpu_disabled:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_fpu_dis,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_trap
+_real_trap:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_trap,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_trace
+_real_trace:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_trace,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _real_access
+_real_access:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_access,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+#######################################
+
+ global _imem_read
+_imem_read:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_imr,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_read
+_dmem_read:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dmr,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_write
+_dmem_write:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dmw,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _imem_read_word
+_imem_read_word:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_irw,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _imem_read_long
+_imem_read_long:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_irl,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_read_byte
+_dmem_read_byte:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_drb,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_read_word
+_dmem_read_word:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_drw,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_read_long
+_dmem_read_long:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_drl,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_write_byte
+_dmem_write_byte:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dwb,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_write_word
+_dmem_write_word:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dww,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+ global _dmem_write_long
+_dmem_write_long:
+ mov.l %d0,-(%sp)
+ mov.l (_060FPSP_TABLE-0x80+_off_dwl,%pc),%d0
+ pea.l (_060FPSP_TABLE-0x80,%pc,%d0)
+ mov.l 0x4(%sp),%d0
+ rtd &0x4
+
+#
+# This file contains a set of define statements for constants
+# in order to promote readability within the corecode itself.
+#
+
+set LOCAL_SIZE, 192 # stack frame size(bytes)
+set LV, -LOCAL_SIZE # stack offset
+
+set EXC_SR, 0x4 # stack status register
+set EXC_PC, 0x6 # stack pc
+set EXC_VOFF, 0xa # stacked vector offset
+set EXC_EA, 0xc # stacked <ea>
+
+set EXC_FP, 0x0 # frame pointer
+
+set EXC_AREGS, -68 # offset of all address regs
+set EXC_DREGS, -100 # offset of all data regs
+set EXC_FPREGS, -36 # offset of all fp regs
+
+set EXC_A7, EXC_AREGS+(7*4) # offset of saved a7
+set OLD_A7, EXC_AREGS+(6*4) # extra copy of saved a7
+set EXC_A6, EXC_AREGS+(6*4) # offset of saved a6
+set EXC_A5, EXC_AREGS+(5*4)
+set EXC_A4, EXC_AREGS+(4*4)
+set EXC_A3, EXC_AREGS+(3*4)
+set EXC_A2, EXC_AREGS+(2*4)
+set EXC_A1, EXC_AREGS+(1*4)
+set EXC_A0, EXC_AREGS+(0*4)
+set EXC_D7, EXC_DREGS+(7*4)
+set EXC_D6, EXC_DREGS+(6*4)
+set EXC_D5, EXC_DREGS+(5*4)
+set EXC_D4, EXC_DREGS+(4*4)
+set EXC_D3, EXC_DREGS+(3*4)
+set EXC_D2, EXC_DREGS+(2*4)
+set EXC_D1, EXC_DREGS+(1*4)
+set EXC_D0, EXC_DREGS+(0*4)
+
+set EXC_FP0, EXC_FPREGS+(0*12) # offset of saved fp0
+set EXC_FP1, EXC_FPREGS+(1*12) # offset of saved fp1
+set EXC_FP2, EXC_FPREGS+(2*12) # offset of saved fp2 (not used)
+
+set FP_SCR1, LV+80 # fp scratch 1
+set FP_SCR1_EX, FP_SCR1+0
+set FP_SCR1_SGN, FP_SCR1+2
+set FP_SCR1_HI, FP_SCR1+4
+set FP_SCR1_LO, FP_SCR1+8
+
+set FP_SCR0, LV+68 # fp scratch 0
+set FP_SCR0_EX, FP_SCR0+0
+set FP_SCR0_SGN, FP_SCR0+2
+set FP_SCR0_HI, FP_SCR0+4
+set FP_SCR0_LO, FP_SCR0+8
+
+set FP_DST, LV+56 # fp destination operand
+set FP_DST_EX, FP_DST+0
+set FP_DST_SGN, FP_DST+2
+set FP_DST_HI, FP_DST+4
+set FP_DST_LO, FP_DST+8
+
+set FP_SRC, LV+44 # fp source operand
+set FP_SRC_EX, FP_SRC+0
+set FP_SRC_SGN, FP_SRC+2
+set FP_SRC_HI, FP_SRC+4
+set FP_SRC_LO, FP_SRC+8
+
+set USER_FPIAR, LV+40 # FP instr address register
+
+set USER_FPSR, LV+36 # FP status register
+set FPSR_CC, USER_FPSR+0 # FPSR condition codes
+set FPSR_QBYTE, USER_FPSR+1 # FPSR qoutient byte
+set FPSR_EXCEPT, USER_FPSR+2 # FPSR exception status byte
+set FPSR_AEXCEPT, USER_FPSR+3 # FPSR accrued exception byte
+
+set USER_FPCR, LV+32 # FP control register
+set FPCR_ENABLE, USER_FPCR+2 # FPCR exception enable
+set FPCR_MODE, USER_FPCR+3 # FPCR rounding mode control
+
+set L_SCR3, LV+28 # integer scratch 3
+set L_SCR2, LV+24 # integer scratch 2
+set L_SCR1, LV+20 # integer scratch 1
+
+set STORE_FLG, LV+19 # flag: operand store (ie. not fcmp/ftst)
+
+set EXC_TEMP2, LV+24 # temporary space
+set EXC_TEMP, LV+16 # temporary space
+
+set DTAG, LV+15 # destination operand type
+set STAG, LV+14 # source operand type
+
+set SPCOND_FLG, LV+10 # flag: special case (see below)
+
+set EXC_CC, LV+8 # saved condition codes
+set EXC_EXTWPTR, LV+4 # saved current PC (active)
+set EXC_EXTWORD, LV+2 # saved extension word
+set EXC_CMDREG, LV+2 # saved extension word
+set EXC_OPWORD, LV+0 # saved operation word
+
+################################
+
+# Helpful macros
+
+set FTEMP, 0 # offsets within an
+set FTEMP_EX, 0 # extended precision
+set FTEMP_SGN, 2 # value saved in memory.
+set FTEMP_HI, 4
+set FTEMP_LO, 8
+set FTEMP_GRS, 12
+
+set LOCAL, 0 # offsets within an
+set LOCAL_EX, 0 # extended precision
+set LOCAL_SGN, 2 # value saved in memory.
+set LOCAL_HI, 4
+set LOCAL_LO, 8
+set LOCAL_GRS, 12
+
+set DST, 0 # offsets within an
+set DST_EX, 0 # extended precision
+set DST_HI, 4 # value saved in memory.
+set DST_LO, 8
+
+set SRC, 0 # offsets within an
+set SRC_EX, 0 # extended precision
+set SRC_HI, 4 # value saved in memory.
+set SRC_LO, 8
+
+set SGL_LO, 0x3f81 # min sgl prec exponent
+set SGL_HI, 0x407e # max sgl prec exponent
+set DBL_LO, 0x3c01 # min dbl prec exponent
+set DBL_HI, 0x43fe # max dbl prec exponent
+set EXT_LO, 0x0 # min ext prec exponent
+set EXT_HI, 0x7ffe # max ext prec exponent
+
+set EXT_BIAS, 0x3fff # extended precision bias
+set SGL_BIAS, 0x007f # single precision bias
+set DBL_BIAS, 0x03ff # double precision bias
+
+set NORM, 0x00 # operand type for STAG/DTAG
+set ZERO, 0x01 # operand type for STAG/DTAG
+set INF, 0x02 # operand type for STAG/DTAG
+set QNAN, 0x03 # operand type for STAG/DTAG
+set DENORM, 0x04 # operand type for STAG/DTAG
+set SNAN, 0x05 # operand type for STAG/DTAG
+set UNNORM, 0x06 # operand type for STAG/DTAG
+
+##################
+# FPSR/FPCR bits #
+##################
+set neg_bit, 0x3 # negative result
+set z_bit, 0x2 # zero result
+set inf_bit, 0x1 # infinite result
+set nan_bit, 0x0 # NAN result
+
+set q_sn_bit, 0x7 # sign bit of quotient byte
+
+set bsun_bit, 7 # branch on unordered
+set snan_bit, 6 # signalling NAN
+set operr_bit, 5 # operand error
+set ovfl_bit, 4 # overflow
+set unfl_bit, 3 # underflow
+set dz_bit, 2 # divide by zero
+set inex2_bit, 1 # inexact result 2
+set inex1_bit, 0 # inexact result 1
+
+set aiop_bit, 7 # accrued inexact operation bit
+set aovfl_bit, 6 # accrued overflow bit
+set aunfl_bit, 5 # accrued underflow bit
+set adz_bit, 4 # accrued dz bit
+set ainex_bit, 3 # accrued inexact bit
+
+#############################
+# FPSR individual bit masks #
+#############################
+set neg_mask, 0x08000000 # negative bit mask (lw)
+set inf_mask, 0x02000000 # infinity bit mask (lw)
+set z_mask, 0x04000000 # zero bit mask (lw)
+set nan_mask, 0x01000000 # nan bit mask (lw)
+
+set neg_bmask, 0x08 # negative bit mask (byte)
+set inf_bmask, 0x02 # infinity bit mask (byte)
+set z_bmask, 0x04 # zero bit mask (byte)
+set nan_bmask, 0x01 # nan bit mask (byte)
+
+set bsun_mask, 0x00008000 # bsun exception mask
+set snan_mask, 0x00004000 # snan exception mask
+set operr_mask, 0x00002000 # operr exception mask
+set ovfl_mask, 0x00001000 # overflow exception mask
+set unfl_mask, 0x00000800 # underflow exception mask
+set dz_mask, 0x00000400 # dz exception mask
+set inex2_mask, 0x00000200 # inex2 exception mask
+set inex1_mask, 0x00000100 # inex1 exception mask
+
+set aiop_mask, 0x00000080 # accrued illegal operation
+set aovfl_mask, 0x00000040 # accrued overflow
+set aunfl_mask, 0x00000020 # accrued underflow
+set adz_mask, 0x00000010 # accrued divide by zero
+set ainex_mask, 0x00000008 # accrued inexact
+
+######################################
+# FPSR combinations used in the FPSP #
+######################################
+set dzinf_mask, inf_mask+dz_mask+adz_mask
+set opnan_mask, nan_mask+operr_mask+aiop_mask
+set nzi_mask, 0x01ffffff #clears N, Z, and I
+set unfinx_mask, unfl_mask+inex2_mask+aunfl_mask+ainex_mask
+set unf2inx_mask, unfl_mask+inex2_mask+ainex_mask
+set ovfinx_mask, ovfl_mask+inex2_mask+aovfl_mask+ainex_mask
+set inx1a_mask, inex1_mask+ainex_mask
+set inx2a_mask, inex2_mask+ainex_mask
+set snaniop_mask, nan_mask+snan_mask+aiop_mask
+set snaniop2_mask, snan_mask+aiop_mask
+set naniop_mask, nan_mask+aiop_mask
+set neginf_mask, neg_mask+inf_mask
+set infaiop_mask, inf_mask+aiop_mask
+set negz_mask, neg_mask+z_mask
+set opaop_mask, operr_mask+aiop_mask
+set unfl_inx_mask, unfl_mask+aunfl_mask+ainex_mask
+set ovfl_inx_mask, ovfl_mask+aovfl_mask+ainex_mask
+
+#########
+# misc. #
+#########
+set rnd_stky_bit, 29 # stky bit pos in longword
+
+set sign_bit, 0x7 # sign bit
+set signan_bit, 0x6 # signalling nan bit
+
+set sgl_thresh, 0x3f81 # minimum sgl exponent
+set dbl_thresh, 0x3c01 # minimum dbl exponent
+
+set x_mode, 0x0 # extended precision
+set s_mode, 0x4 # single precision
+set d_mode, 0x8 # double precision
+
+set rn_mode, 0x0 # round-to-nearest
+set rz_mode, 0x1 # round-to-zero
+set rm_mode, 0x2 # round-tp-minus-infinity
+set rp_mode, 0x3 # round-to-plus-infinity
+
+set mantissalen, 64 # length of mantissa in bits
+
+set BYTE, 1 # len(byte) == 1 byte
+set WORD, 2 # len(word) == 2 bytes
+set LONG, 4 # len(longword) == 2 bytes
+
+set BSUN_VEC, 0xc0 # bsun vector offset
+set INEX_VEC, 0xc4 # inexact vector offset
+set DZ_VEC, 0xc8 # dz vector offset
+set UNFL_VEC, 0xcc # unfl vector offset
+set OPERR_VEC, 0xd0 # operr vector offset
+set OVFL_VEC, 0xd4 # ovfl vector offset
+set SNAN_VEC, 0xd8 # snan vector offset
+
+###########################
+# SPecial CONDition FLaGs #
+###########################
+set ftrapcc_flg, 0x01 # flag bit: ftrapcc exception
+set fbsun_flg, 0x02 # flag bit: bsun exception
+set mia7_flg, 0x04 # flag bit: (a7)+ <ea>
+set mda7_flg, 0x08 # flag bit: -(a7) <ea>
+set fmovm_flg, 0x40 # flag bit: fmovm instruction
+set immed_flg, 0x80 # flag bit: &<data> <ea>
+
+set ftrapcc_bit, 0x0
+set fbsun_bit, 0x1
+set mia7_bit, 0x2
+set mda7_bit, 0x3
+set immed_bit, 0x7
+
+##################################
+# TRANSCENDENTAL "LAST-OP" FLAGS #
+##################################
+set FMUL_OP, 0x0 # fmul instr performed last
+set FDIV_OP, 0x1 # fdiv performed last
+set FADD_OP, 0x2 # fadd performed last
+set FMOV_OP, 0x3 # fmov performed last
+
+#############
+# CONSTANTS #
+#############
+T1: long 0x40C62D38,0xD3D64634 # 16381 LOG2 LEAD
+T2: long 0x3D6F90AE,0xB1E75CC7 # 16381 LOG2 TRAIL
+
+PI: long 0x40000000,0xC90FDAA2,0x2168C235,0x00000000
+PIBY2: long 0x3FFF0000,0xC90FDAA2,0x2168C235,0x00000000
+
+TWOBYPI:
+ long 0x3FE45F30,0x6DC9C883
+
+#########################################################################
+# XDEF **************************************************************** #
+# _fpsp_ovfl(): 060FPSP entry point for FP Overflow exception. #
+# #
+# This handler should be the first code executed upon taking the #
+# FP Overflow exception in an operating system. #
+# #
+# XREF **************************************************************** #
+# _imem_read_long() - read instruction longword #
+# fix_skewed_ops() - adjust src operand in fsave frame #
+# set_tag_x() - determine optype of src/dst operands #
+# store_fpreg() - store opclass 0 or 2 result to FP regfile #
+# unnorm_fix() - change UNNORM operands to NORM or ZERO #
+# load_fpn2() - load dst operand from FP regfile #
+# fout() - emulate an opclass 3 instruction #
+# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
+# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
+# _real_ovfl() - "callout" for Overflow exception enabled code #
+# _real_inex() - "callout" for Inexact exception enabled code #
+# _real_trace() - "callout" for Trace exception code #
+# #
+# INPUT *************************************************************** #
+# - The system stack contains the FP Ovfl exception stack frame #
+# - The fsave frame contains the source operand #
+# #
+# OUTPUT ************************************************************** #
+# Overflow Exception enabled: #
+# - The system stack is unchanged #
+# - The fsave frame contains the adjusted src op for opclass 0,2 #
+# Overflow Exception disabled: #
+# - The system stack is unchanged #
+# - The "exception present" flag in the fsave frame is cleared #
+# #
+# ALGORITHM *********************************************************** #
+# On the 060, if an FP overflow is present as the result of any #
+# instruction, the 060 will take an overflow exception whether the #
+# exception is enabled or disabled in the FPCR. For the disabled case, #
+# This handler emulates the instruction to determine what the correct #
+# default result should be for the operation. This default result is #
+# then stored in either the FP regfile, data regfile, or memory. #
+# Finally, the handler exits through the "callout" _fpsp_done() #
+# denoting that no exceptional conditions exist within the machine. #
+# If the exception is enabled, then this handler must create the #
+# exceptional operand and plave it in the fsave state frame, and store #
+# the default result (only if the instruction is opclass 3). For #
+# exceptions enabled, this handler must exit through the "callout" #
+# _real_ovfl() so that the operating system enabled overflow handler #
+# can handle this case. #
+# Two other conditions exist. First, if overflow was disabled #
+# but the inexact exception was enabled, this handler must exit #
+# through the "callout" _real_inex() regardless of whether the result #
+# was inexact. #
+# Also, in the case of an opclass three instruction where #
+# overflow was disabled and the trace exception was enabled, this #
+# handler must exit through the "callout" _real_trace(). #
+# #
+#########################################################################
+
+ global _fpsp_ovfl
+_fpsp_ovfl:
+
+#$# sub.l &24,%sp # make room for src/dst
+
+ link.w %a6,&-LOCAL_SIZE # init stack frame
+
+ fsave FP_SRC(%a6) # grab the "busy" frame
+
+ movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
+ fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
+ fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
+
+# the FPIAR holds the "current PC" of the faulting instruction
+ mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
+ mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
+ addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
+ bsr.l _imem_read_long # fetch the instruction words
+ mov.l %d0,EXC_OPWORD(%a6)
+
+##############################################################################
+
+ btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
+ bne.w fovfl_out
+
+
+ lea FP_SRC(%a6),%a0 # pass: ptr to src op
+ bsr.l fix_skewed_ops # fix src op
+
+# since, I believe, only NORMs and DENORMs can come through here,
+# maybe we can avoid the subroutine call.
+ lea FP_SRC(%a6),%a0 # pass: ptr to src op
+ bsr.l set_tag_x # tag the operand type
+ mov.b %d0,STAG(%a6) # maybe NORM,DENORM
+
+# bit five of the fp extension word separates the monadic and dyadic operations
+# that can pass through fpsp_ovfl(). remember that fcmp, ftst, and fsincos
+# will never take this exception.
+ btst &0x5,1+EXC_CMDREG(%a6) # is operation monadic or dyadic?
+ beq.b fovfl_extract # monadic
+
+ bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
+ bsr.l load_fpn2 # load dst into FP_DST
+
+ lea FP_DST(%a6),%a0 # pass: ptr to dst op
+ bsr.l set_tag_x # tag the operand type
+ cmpi.b %d0,&UNNORM # is operand an UNNORM?
+ bne.b fovfl_op2_done # no
+ bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
+fovfl_op2_done:
+ mov.b %d0,DTAG(%a6) # save dst optype tag
+
+fovfl_extract:
+
+#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
+#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
+#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
+#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
+#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
+#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
+
+ clr.l %d0
+ mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
+
+ mov.b 1+EXC_CMDREG(%a6),%d1
+ andi.w &0x007f,%d1 # extract extension
+
+ andi.l &0x00ff01ff,USER_FPSR(%a6) # zero all but accured field
+
+ fmov.l &0x0,%fpcr # zero current control regs
+ fmov.l &0x0,%fpsr
+
+ lea FP_SRC(%a6),%a0
+ lea FP_DST(%a6),%a1
+
+# maybe we can make these entry points ONLY the OVFL entry points of each routine.
+ mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
+ jsr (tbl_unsupp.l,%pc,%d1.l*1)
+
+# the operation has been emulated. the result is in fp0.
+# the EXOP, if an exception occurred, is in fp1.
+# we must save the default result regardless of whether
+# traps are enabled or disabled.
+ bfextu EXC_CMDREG(%a6){&6:&3},%d0
+ bsr.l store_fpreg
+
+# the exceptional possibilities we have left ourselves with are ONLY overflow
+# and inexact. and, the inexact is such that overflow occurred and was disabled
+# but inexact was enabled.
+ btst &ovfl_bit,FPCR_ENABLE(%a6)
+ bne.b fovfl_ovfl_on
+
+ btst &inex2_bit,FPCR_ENABLE(%a6)
+ bne.b fovfl_inex_on
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ unlk %a6
+#$# add.l &24,%sp
+ bra.l _fpsp_done
+
+# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
+# in fp1. now, simply jump to _real_ovfl()!
+fovfl_ovfl_on:
+ fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
+
+ mov.w &0xe005,2+FP_SRC(%a6) # save exc status
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
+
+ unlk %a6
+
+ bra.l _real_ovfl
+
+# overflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
+# we must jump to real_inex().
+fovfl_inex_on:
+
+ fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
+
+ mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
+ mov.w &0xe001,2+FP_SRC(%a6) # save exc status
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
+
+ unlk %a6
+
+ bra.l _real_inex
+
+########################################################################
+fovfl_out:
+
+
+#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
+#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
+#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
+
+# the src operand is definitely a NORM(!), so tag it as such
+ mov.b &NORM,STAG(%a6) # set src optype tag
+
+ clr.l %d0
+ mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
+
+ and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
+
+ fmov.l &0x0,%fpcr # zero current control regs
+ fmov.l &0x0,%fpsr
+
+ lea FP_SRC(%a6),%a0 # pass ptr to src operand
+
+ bsr.l fout
+
+ btst &ovfl_bit,FPCR_ENABLE(%a6)
+ bne.w fovfl_ovfl_on
+
+ btst &inex2_bit,FPCR_ENABLE(%a6)
+ bne.w fovfl_inex_on
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ unlk %a6
+#$# add.l &24,%sp
+
+ btst &0x7,(%sp) # is trace on?
+ beq.l _fpsp_done # no
+
+ fmov.l %fpiar,0x8(%sp) # "Current PC" is in FPIAR
+ mov.w &0x2024,0x6(%sp) # stk fmt = 0x2; voff = 0x024
+ bra.l _real_trace
+
+#########################################################################
+# XDEF **************************************************************** #
+# _fpsp_unfl(): 060FPSP entry point for FP Underflow exception. #
+# #
+# This handler should be the first code executed upon taking the #
+# FP Underflow exception in an operating system. #
+# #
+# XREF **************************************************************** #
+# _imem_read_long() - read instruction longword #
+# fix_skewed_ops() - adjust src operand in fsave frame #
+# set_tag_x() - determine optype of src/dst operands #
+# store_fpreg() - store opclass 0 or 2 result to FP regfile #
+# unnorm_fix() - change UNNORM operands to NORM or ZERO #
+# load_fpn2() - load dst operand from FP regfile #
+# fout() - emulate an opclass 3 instruction #
+# tbl_unsupp - add of table of emulation routines for opclass 0,2 #
+# _fpsp_done() - "callout" for 060FPSP exit (all work done!) #
+# _real_ovfl() - "callout" for Overflow exception enabled code #
+# _real_inex() - "callout" for Inexact exception enabled code #
+# _real_trace() - "callout" for Trace exception code #
+# #
+# INPUT *************************************************************** #
+# - The system stack contains the FP Unfl exception stack frame #
+# - The fsave frame contains the source operand #
+# #
+# OUTPUT ************************************************************** #
+# Underflow Exception enabled: #
+# - The system stack is unchanged #
+# - The fsave frame contains the adjusted src op for opclass 0,2 #
+# Underflow Exception disabled: #
+# - The system stack is unchanged #
+# - The "exception present" flag in the fsave frame is cleared #
+# #
+# ALGORITHM *********************************************************** #
+# On the 060, if an FP underflow is present as the result of any #
+# instruction, the 060 will take an underflow exception whether the #
+# exception is enabled or disabled in the FPCR. For the disabled case, #
+# This handler emulates the instruction to determine what the correct #
+# default result should be for the operation. This default result is #
+# then stored in either the FP regfile, data regfile, or memory. #
+# Finally, the handler exits through the "callout" _fpsp_done() #
+# denoting that no exceptional conditions exist within the machine. #
+# If the exception is enabled, then this handler must create the #
+# exceptional operand and plave it in the fsave state frame, and store #
+# the default result (only if the instruction is opclass 3). For #
+# exceptions enabled, this handler must exit through the "callout" #
+# _real_unfl() so that the operating system enabled overflow handler #
+# can handle this case. #
+# Two other conditions exist. First, if underflow was disabled #
+# but the inexact exception was enabled and the result was inexact, #
+# this handler must exit through the "callout" _real_inex(). #
+# was inexact. #
+# Also, in the case of an opclass three instruction where #
+# underflow was disabled and the trace exception was enabled, this #
+# handler must exit through the "callout" _real_trace(). #
+# #
+#########################################################################
+
+ global _fpsp_unfl
+_fpsp_unfl:
+
+#$# sub.l &24,%sp # make room for src/dst
+
+ link.w %a6,&-LOCAL_SIZE # init stack frame
+
+ fsave FP_SRC(%a6) # grab the "busy" frame
+
+ movm.l &0x0303,EXC_DREGS(%a6) # save d0-d1/a0-a1
+ fmovm.l %fpcr,%fpsr,%fpiar,USER_FPCR(%a6) # save ctrl regs
+ fmovm.x &0xc0,EXC_FPREGS(%a6) # save fp0-fp1 on stack
+
+# the FPIAR holds the "current PC" of the faulting instruction
+ mov.l USER_FPIAR(%a6),EXC_EXTWPTR(%a6)
+ mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr
+ addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr
+ bsr.l _imem_read_long # fetch the instruction words
+ mov.l %d0,EXC_OPWORD(%a6)
+
+##############################################################################
+
+ btst &0x5,EXC_CMDREG(%a6) # is instr an fmove out?
+ bne.w funfl_out
+
+
+ lea FP_SRC(%a6),%a0 # pass: ptr to src op
+ bsr.l fix_skewed_ops # fix src op
+
+ lea FP_SRC(%a6),%a0 # pass: ptr to src op
+ bsr.l set_tag_x # tag the operand type
+ mov.b %d0,STAG(%a6) # maybe NORM,DENORM
+
+# bit five of the fp ext word separates the monadic and dyadic operations
+# that can pass through fpsp_unfl(). remember that fcmp, and ftst
+# will never take this exception.
+ btst &0x5,1+EXC_CMDREG(%a6) # is op monadic or dyadic?
+ beq.b funfl_extract # monadic
+
+# now, what's left that's not dyadic is fsincos. we can distinguish it
+# from all dyadics by the '0110xxx pattern
+ btst &0x4,1+EXC_CMDREG(%a6) # is op an fsincos?
+ bne.b funfl_extract # yes
+
+ bfextu EXC_CMDREG(%a6){&6:&3},%d0 # dyadic; load dst reg
+ bsr.l load_fpn2 # load dst into FP_DST
+
+ lea FP_DST(%a6),%a0 # pass: ptr to dst op
+ bsr.l set_tag_x # tag the operand type
+ cmpi.b %d0,&UNNORM # is operand an UNNORM?
+ bne.b funfl_op2_done # no
+ bsr.l unnorm_fix # yes; convert to NORM,DENORM,or ZERO
+funfl_op2_done:
+ mov.b %d0,DTAG(%a6) # save dst optype tag
+
+funfl_extract:
+
+#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
+#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
+#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
+#$# mov.l FP_DST_EX(%a6),TRAP_DSTOP_EX(%a6)
+#$# mov.l FP_DST_HI(%a6),TRAP_DSTOP_HI(%a6)
+#$# mov.l FP_DST_LO(%a6),TRAP_DSTOP_LO(%a6)
+
+ clr.l %d0
+ mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
+
+ mov.b 1+EXC_CMDREG(%a6),%d1
+ andi.w &0x007f,%d1 # extract extension
+
+ andi.l &0x00ff01ff,USER_FPSR(%a6)
+
+ fmov.l &0x0,%fpcr # zero current control regs
+ fmov.l &0x0,%fpsr
+
+ lea FP_SRC(%a6),%a0
+ lea FP_DST(%a6),%a1
+
+# maybe we can make these entry points ONLY the OVFL entry points of each routine.
+ mov.l (tbl_unsupp.l,%pc,%d1.w*4),%d1 # fetch routine addr
+ jsr (tbl_unsupp.l,%pc,%d1.l*1)
+
+ bfextu EXC_CMDREG(%a6){&6:&3},%d0
+ bsr.l store_fpreg
+
+# The `060 FPU multiplier hardware is such that if the result of a
+# multiply operation is the smallest possible normalized number
+# (0x00000000_80000000_00000000), then the machine will take an
+# underflow exception. Since this is incorrect, we need to check
+# if our emulation, after re-doing the operation, decided that
+# no underflow was called for. We do these checks only in
+# funfl_{unfl,inex}_on() because w/ both exceptions disabled, this
+# special case will simply exit gracefully with the correct result.
+
+# the exceptional possibilities we have left ourselves with are ONLY overflow
+# and inexact. and, the inexact is such that overflow occurred and was disabled
+# but inexact was enabled.
+ btst &unfl_bit,FPCR_ENABLE(%a6)
+ bne.b funfl_unfl_on
+
+funfl_chkinex:
+ btst &inex2_bit,FPCR_ENABLE(%a6)
+ bne.b funfl_inex_on
+
+funfl_exit:
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ unlk %a6
+#$# add.l &24,%sp
+ bra.l _fpsp_done
+
+# overflow is enabled AND overflow, of course, occurred. so, we have the EXOP
+# in fp1 (don't forget to save fp0). what to do now?
+# well, we simply have to get to go to _real_unfl()!
+funfl_unfl_on:
+
+# The `060 FPU multiplier hardware is such that if the result of a
+# multiply operation is the smallest possible normalized number
+# (0x00000000_80000000_00000000), then the machine will take an
+# underflow exception. Since this is incorrect, we check here to see
+# if our emulation, after re-doing the operation, decided that
+# no underflow was called for.
+ btst &unfl_bit,FPSR_EXCEPT(%a6)
+ beq.w funfl_chkinex
+
+funfl_unfl_on2:
+ fmovm.x &0x40,FP_SRC(%a6) # save EXOP (fp1) to stack
+
+ mov.w &0xe003,2+FP_SRC(%a6) # save exc status
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
+
+ unlk %a6
+
+ bra.l _real_unfl
+
+# undeflow occurred but is disabled. meanwhile, inexact is enabled. therefore,
+# we must jump to real_inex().
+funfl_inex_on:
+
+# The `060 FPU multiplier hardware is such that if the result of a
+# multiply operation is the smallest possible normalized number
+# (0x00000000_80000000_00000000), then the machine will take an
+# underflow exception.
+# But, whether bogus or not, if inexact is enabled AND it occurred,
+# then we have to branch to real_inex.
+
+ btst &inex2_bit,FPSR_EXCEPT(%a6)
+ beq.w funfl_exit
+
+funfl_inex_on2:
+
+ fmovm.x &0x40,FP_SRC(%a6) # save EXOP to stack
+
+ mov.b &0xc4,1+EXC_VOFF(%a6) # vector offset = 0xc4
+ mov.w &0xe001,2+FP_SRC(%a6) # save exc status
+
+ fmovm.x EXC_FPREGS(%a6),&0xc0 # restore fp0-fp1
+ fmovm.l USER_FPCR(%a6),%fpcr,%fpsr,%fpiar # restore ctrl regs
+ movm.l EXC_DREGS(%a6),&0x0303 # restore d0-d1/a0-a1
+
+ frestore FP_SRC(%a6) # do this after fmovm,other f<op>s!
+
+ unlk %a6
+
+ bra.l _real_inex
+
+#######################################################################
+funfl_out:
+
+
+#$# mov.l FP_SRC_EX(%a6),TRAP_SRCOP_EX(%a6)
+#$# mov.l FP_SRC_HI(%a6),TRAP_SRCOP_HI(%a6)
+#$# mov.l FP_SRC_LO(%a6),TRAP_SRCOP_LO(%a6)
+
+# the src operand is definitely a NORM(!), so tag it as such
+ mov.b &NORM,STAG(%a6) # set src optype tag
+
+ clr.l %d0
+ mov.b FPCR_MODE(%a6),%d0 # pass rnd prec/mode
+
+ and.l &0xffff00ff,USER_FPSR(%a6) # zero all but accured field
+
+ fmov.l &0x0,%fpcr # zero current control regs
+ fmov.l &0x0,%fpsr
+
+ lea FP_SRC(%a6),%a0 # pass ptr to src operand
+
+ bsr.l fout
+
+ btst &unfl_bit,FPCR_ENABLE(%a6)
+ bne.w funfl_unfl_on2
+
+ btst &inex2_bit,FPCR_ENABLE(%a6)