389 lines
7.7 KiB
Plaintext
389 lines
7.7 KiB
Plaintext
* $NetBSD: l_support.sa,v 1.3 1994/10/26 07:49:16 cgd Exp $
|
|
|
|
* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
|
|
* M68000 Hi-Performance Microprocessor Division
|
|
* M68040 Software Package
|
|
*
|
|
* M68040 Software Package Copyright (c) 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.
|
|
|
|
*
|
|
* l_support.sa 1.2 5/1/91
|
|
*
|
|
|
|
L_SUPPORT IDNT 2,1 Motorola 040 Floating Point Software Package
|
|
|
|
section 8
|
|
|
|
mns_one dc.l $bfff0000,$80000000,$00000000
|
|
pls_one dc.l $3fff0000,$80000000,$00000000
|
|
pls_inf dc.l $7fff0000,$00000000,$00000000
|
|
pls_huge dc.l $7ffe0000,$ffffffff,$ffffffff
|
|
mns_huge dc.l $fffe0000,$ffffffff,$ffffffff
|
|
pls_tiny dc.l $00000000,$80000000,$00000000
|
|
mns_tiny dc.l $80000000,$80000000,$00000000
|
|
small dc.l $20000000,$80000000,$00000000
|
|
pls_zero dc.l $00000000,$00000000,$00000000
|
|
|
|
include l_fpsp.h
|
|
|
|
*
|
|
* tag --- determine the type of an extended precision operand
|
|
*
|
|
* The tag values returned match the way the 68040 would have
|
|
* tagged them.
|
|
*
|
|
* Input: a0 points to operand
|
|
*
|
|
* Output d0.b = $00 norm
|
|
* $20 zero
|
|
* $40 inf
|
|
* $60 nan
|
|
* $80 denorm
|
|
* All other registers are unchanged
|
|
*
|
|
xdef tag
|
|
tag:
|
|
move.w LOCAL_EX(a0),d0
|
|
andi.w #$7fff,d0
|
|
beq.b chk_zro
|
|
cmpi.w #$7fff,d0
|
|
beq.b chk_inf
|
|
tag_nrm:
|
|
clr.b d0
|
|
rts
|
|
tag_nan:
|
|
move.b #$60,d0
|
|
rts
|
|
tag_dnrm:
|
|
move.b #$80,d0
|
|
rts
|
|
chk_zro:
|
|
btst.b #7,LOCAL_HI(a0) # check if J-bit is set
|
|
bne.b tag_nrm
|
|
tst.l LOCAL_HI(a0)
|
|
bne.b tag_dnrm
|
|
tst.l LOCAL_LO(a0)
|
|
bne.b tag_dnrm
|
|
tag_zero:
|
|
move.b #$20,d0
|
|
rts
|
|
chk_inf:
|
|
tst.l LOCAL_HI(a0)
|
|
bne.b tag_nan
|
|
tst.l LOCAL_LO(a0)
|
|
bne.b tag_nan
|
|
tag_inf:
|
|
move.b #$40,d0
|
|
rts
|
|
|
|
*
|
|
* t_dz, t_dz2 --- divide by zero exception
|
|
*
|
|
* t_dz2 is used by monadic functions such as flogn (from do_func).
|
|
* t_dz is used by monadic functions such as satanh (from the
|
|
* transcendental function).
|
|
*
|
|
xdef t_dz2
|
|
t_dz2:
|
|
fmovem.x mns_one,fp0
|
|
fmove.l d1,fpcr
|
|
fdiv.x pls_zero,fp0
|
|
rts
|
|
|
|
xdef t_dz
|
|
t_dz:
|
|
btst.b #sign_bit,ETEMP_EX(a6) ;check sign for neg or pos
|
|
beq.b p_inf ;branch if pos sign
|
|
m_inf:
|
|
fmovem.x mns_one,fp0
|
|
fmove.l d1,fpcr
|
|
fdiv.x pls_zero,fp0
|
|
rts
|
|
p_inf:
|
|
fmovem.x pls_one,fp0
|
|
fmove.l d1,fpcr
|
|
fdiv.x pls_zero,fp0
|
|
rts
|
|
*
|
|
* t_operr --- Operand Error exception
|
|
*
|
|
xdef t_operr
|
|
t_operr:
|
|
fmovem.x pls_inf,fp0
|
|
fmove.l d1,fpcr
|
|
fmul.x pls_zero,fp0
|
|
rts
|
|
|
|
*
|
|
* t_unfl --- UNFL exception
|
|
*
|
|
xdef t_unfl
|
|
t_unfl:
|
|
btst.b #sign_bit,ETEMP(a6)
|
|
beq.b unf_pos
|
|
unf_neg:
|
|
fmovem.x mns_tiny,fp0
|
|
fmove.l d1,fpcr
|
|
fmul.x pls_tiny,fp0
|
|
rts
|
|
|
|
unf_pos:
|
|
fmovem.x pls_tiny,fp0
|
|
fmove.l d1,fpcr
|
|
fmul.x fp0,fp0
|
|
rts
|
|
*
|
|
* t_ovfl --- OVFL exception
|
|
*
|
|
* t_ovfl is called as an exit for monadic functions. t_ovfl2
|
|
* is for dyadic exits.
|
|
*
|
|
xdef t_ovfl
|
|
t_ovfl:
|
|
xdef t_ovfl2
|
|
move.l d1,USER_FPCR(a6) user's control register
|
|
move.l #ovfinx_mask,d0
|
|
bra.b t_work
|
|
t_ovfl2:
|
|
move.l #ovfl_inx_mask,d0
|
|
t_work:
|
|
btst.b #sign_bit,ETEMP(a6)
|
|
beq.b ovf_pos
|
|
ovf_neg:
|
|
fmovem.x mns_huge,fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmul.x pls_huge,fp0
|
|
fmove.l fpsr,d1
|
|
or.l d1,d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
ovf_pos:
|
|
fmovem.x pls_huge,fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmul.x pls_huge,fp0
|
|
fmove.l fpsr,d1
|
|
or.l d1,d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
*
|
|
* t_inx2 --- INEX2 exception (correct fpcr is in USER_FPCR(a6))
|
|
*
|
|
xdef t_inx2
|
|
t_inx2:
|
|
fmove.l fpsr,USER_FPSR(a6) capture incoming fpsr
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
*
|
|
* create an inex2 exception by adding two numbers with very different exponents
|
|
* do the add in fp1 so as to not disturb the result sitting in fp0
|
|
*
|
|
fmove.x pls_one,fp1
|
|
fadd.x small,fp1
|
|
*
|
|
or.l #inx2a_mask,USER_FPSR(a6) ;set INEX2, AINEX
|
|
fmove.l USER_FPSR(a6),fpsr
|
|
rts
|
|
*
|
|
* t_frcinx --- Force Inex2 (for monadic functions)
|
|
*
|
|
xdef t_frcinx
|
|
t_frcinx:
|
|
fmove.l fpsr,USER_FPSR(a6) capture incoming fpsr
|
|
fmove.l d1,fpcr
|
|
*
|
|
* create an inex2 exception by adding two numbers with very different exponents
|
|
* do the add in fp1 so as to not disturb the result sitting in fp0
|
|
*
|
|
fmove.x pls_one,fp1
|
|
fadd.x small,fp1
|
|
*
|
|
or.l #inx2a_mask,USER_FPSR(a6) ;set INEX2, AINEX
|
|
btst.b #unfl_bit,FPSR_EXCEPT(a6) ;test for unfl bit set
|
|
beq.b no_uacc1 ;if clear, do not set aunfl
|
|
bset.b #aunfl_bit,FPSR_AEXCEPT(a6)
|
|
no_uacc1:
|
|
fmove.l USER_FPSR(a6),fpsr
|
|
rts
|
|
*
|
|
* dst_nan --- force result when destination is a NaN
|
|
*
|
|
xdef dst_nan
|
|
dst_nan:
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmove.x FPTEMP(a6),fp0
|
|
rts
|
|
|
|
*
|
|
* src_nan --- force result when source is a NaN
|
|
*
|
|
xdef src_nan
|
|
src_nan:
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmove.x ETEMP(a6),fp0
|
|
rts
|
|
*
|
|
* mon_nan --- force result when source is a NaN (monadic version)
|
|
*
|
|
* This is the same as src_nan except that the user's fpcr comes
|
|
* in via d1, not USER_FPCR(a6).
|
|
*
|
|
xdef mon_nan
|
|
mon_nan:
|
|
fmove.l d1,fpcr
|
|
fmove.x ETEMP(a6),fp0
|
|
rts
|
|
*
|
|
* t_extdnrm, t_resdnrm --- generate results for denorm inputs
|
|
*
|
|
* For all functions that have a denormalized input and that f(x)=x,
|
|
* this is the entry point.
|
|
*
|
|
xdef t_extdnrm
|
|
t_extdnrm:
|
|
fmove.l d1,fpcr
|
|
fmove.x LOCAL_EX(a0),fp0
|
|
fmove.l fpsr,d0
|
|
or.l #unfinx_mask,d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
|
|
xdef t_resdnrm
|
|
t_resdnrm:
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmove.x LOCAL_EX(a0),fp0
|
|
fmove.l fpsr,d0
|
|
or.l #unfl_mask,d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
*
|
|
*
|
|
*
|
|
xdef t_avoid_unsupp
|
|
t_avoid_unsupp:
|
|
fmove.x fp0,fp0
|
|
rts
|
|
|
|
xdef sto_cos
|
|
sto_cos:
|
|
fmovem.x LOCAL_EX(a0),fp1
|
|
rts
|
|
*
|
|
* Native instruction support
|
|
*
|
|
* Some systems may need entry points even for 68040 native
|
|
* instructions. These routines are provided for
|
|
* convenience.
|
|
*
|
|
xdef sadd
|
|
sadd:
|
|
fmovem.x FPTEMP(a6),fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fadd.x ETEMP(a6),fp0
|
|
rts
|
|
|
|
xdef ssub
|
|
ssub:
|
|
fmovem.x FPTEMP(a6),fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fsub.x ETEMP(a6),fp0
|
|
rts
|
|
|
|
xdef smul
|
|
smul:
|
|
fmovem.x FPTEMP(a6),fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fmul.x ETEMP(a6),fp0
|
|
rts
|
|
|
|
xdef sdiv
|
|
sdiv:
|
|
fmovem.x FPTEMP(a6),fp0
|
|
fmove.l USER_FPCR(a6),fpcr
|
|
fdiv.x ETEMP(a6),fp0
|
|
rts
|
|
|
|
xdef sabs
|
|
sabs:
|
|
fmovem.x ETEMP(a6),fp0
|
|
fmove.l d1,fpcr
|
|
fabs.x fp0
|
|
rts
|
|
|
|
xdef sneg
|
|
sneg:
|
|
fmovem.x ETEMP(a6),fp0
|
|
fmove.l d1,fpcr
|
|
fneg.x fp0
|
|
rts
|
|
|
|
xdef ssqrt
|
|
ssqrt:
|
|
fmovem.x ETEMP(a6),fp0
|
|
fmove.l d1,fpcr
|
|
fsqrt.x fp0
|
|
rts
|
|
|
|
*
|
|
* l_sint,l_sintrz,l_sintd --- special wrapper for fint and fintrz
|
|
*
|
|
* On entry, move the user's FPCR to USER_FPCR.
|
|
*
|
|
* On return from, we need to pickup the INEX2/AINEX bits
|
|
* that are in USER_FPSR.
|
|
*
|
|
xref sint
|
|
xref sintrz
|
|
xref sintd
|
|
|
|
xdef l_sint
|
|
l_sint:
|
|
move.l d1,USER_FPCR(a6)
|
|
jsr sint
|
|
fmove.l fpsr,d0
|
|
or.l USER_FPSR(a6),d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
|
|
xdef l_sintrz
|
|
l_sintrz:
|
|
move.l d1,USER_FPCR(a6)
|
|
jsr sintrz
|
|
fmove.l fpsr,d0
|
|
or.l USER_FPSR(a6),d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
|
|
xdef l_sintd
|
|
l_sintd:
|
|
move.l d1,USER_FPCR(a6)
|
|
jsr sintd
|
|
fmove.l fpsr,d0
|
|
or.l USER_FPSR(a6),d0
|
|
fmove.l d0,fpsr
|
|
rts
|
|
|
|
end
|