summaryrefslogtreecommitdiff
path: root/sys/arch/m68k/fpsp/do_func.sa
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/m68k/fpsp/do_func.sa
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/m68k/fpsp/do_func.sa')
-rw-r--r--sys/arch/m68k/fpsp/do_func.sa584
1 files changed, 584 insertions, 0 deletions
diff --git a/sys/arch/m68k/fpsp/do_func.sa b/sys/arch/m68k/fpsp/do_func.sa
new file mode 100644
index 00000000000..92e3fde0b49
--- /dev/null
+++ b/sys/arch/m68k/fpsp/do_func.sa
@@ -0,0 +1,584 @@
+* $NetBSD: do_func.sa,v 1.2 1994/10/26 07:49:02 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.
+
+*
+* do_func.sa 3.4 2/18/91
+*
+* Do_func performs the unimplemented operation. The operation
+* to be performed is determined from the lower 7 bits of the
+* extension word (except in the case of fmovecr and fsincos).
+* The opcode and tag bits form an index into a jump table in
+* tbldo.sa. Cases of zero, infinity and NaN are handled in
+* do_func by forcing the default result. Normalized and
+* denormalized (there are no unnormalized numbers at this
+* point) are passed onto the emulation code.
+*
+* CMDREG1B and STAG are extracted from the fsave frame
+* and combined to form the table index. The function called
+* will start with a0 pointing to the ETEMP operand. Dyadic
+* functions can find FPTEMP at -12(a0).
+*
+* Called functions return their result in fp0. Sincos returns
+* sin(x) in fp0 and cos(x) in fp1.
+*
+
+DO_FUNC IDNT 2,1 Motorola 040 Floating Point Software Package
+
+ section 8
+
+ include fpsp.h
+
+ xref t_dz2
+ xref t_operr
+ xref t_inx2
+ xref t_resdnrm
+ xref dst_nan
+ xref src_nan
+ xref nrm_set
+ xref sto_cos
+
+ xref tblpre
+ xref slognp1,slogn,slog10,slog2
+ xref slognd,slog10d,slog2d
+ xref smod,srem
+ xref sscale
+ xref smovcr
+
+PONE dc.l $3fff0000,$80000000,$00000000 ;+1
+MONE dc.l $bfff0000,$80000000,$00000000 ;-1
+PZERO dc.l $00000000,$00000000,$00000000 ;+0
+MZERO dc.l $80000000,$00000000,$00000000 ;-0
+PINF dc.l $7fff0000,$00000000,$00000000 ;+inf
+MINF dc.l $ffff0000,$00000000,$00000000 ;-inf
+QNAN dc.l $7fff0000,$ffffffff,$ffffffff ;non-signaling nan
+PPIBY2 dc.l $3FFF0000,$C90FDAA2,$2168C235 ;+PI/2
+MPIBY2 dc.l $bFFF0000,$C90FDAA2,$2168C235 ;-PI/2
+
+ xdef do_func
+do_func:
+ clr.b CU_ONLY(a6)
+*
+* Check for fmovecr. It does not follow the format of fp gen
+* unimplemented instructions. The test is on the upper 6 bits;
+* if they are $17, the inst is fmovecr. Call entry smovcr
+* directly.
+*
+ bfextu CMDREG1B(a6){0:6},d0 ;get opclass and src fields
+ cmpi.l #$17,d0 ;if op class and size fields are $17,
+* ;it is FMOVECR; if not, continue
+ bne.b not_fmovecr
+ jmp smovcr ;fmovecr; jmp directly to emulation
+
+not_fmovecr:
+ move.w CMDREG1B(a6),d0
+ and.l #$7F,d0
+ cmpi.l #$38,d0 ;if the extension is >= $38,
+ bge.b serror ;it is illegal
+ bfextu STAG(a6){0:3},d1
+ lsl.l #3,d0 ;make room for STAG
+ add.l d1,d0 ;combine for final index into table
+ lea.l tblpre,a1 ;start of monster jump table
+ move.l (a1,d0.w*4),a1 ;real target address
+ lea.l ETEMP(a6),a0 ;a0 is pointer to src op
+ move.l USER_FPCR(a6),d1
+ and.l #$FF,d1 ; discard all but rounding mode/prec
+ fmove.l #0,fpcr
+ jmp (a1)
+*
+* ERROR
+*
+ xdef serror
+serror:
+ st.b STORE_FLG(a6)
+ rts
+*
+* These routines load forced values into fp0. They are called
+* by index into tbldo.
+*
+* Load a signed zero to fp0 and set inex2/ainex
+*
+ xdef snzrinx
+snzrinx:
+ btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand
+ bne.b ld_mzinx ;if negative, branch
+ bsr ld_pzero ;bsr so we can return and set inx
+ bra t_inx2 ;now, set the inx for the next inst
+ld_mzinx:
+ bsr ld_mzero ;if neg, load neg zero, return here
+ bra t_inx2 ;now, set the inx for the next inst
+*
+* Load a signed zero to fp0; do not set inex2/ainex
+*
+ xdef szero
+szero:
+ btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand
+ bne ld_mzero ;if neg, load neg zero
+ bra ld_pzero ;load positive zero
+*
+* Load a signed infinity to fp0; do not set inex2/ainex
+*
+ xdef sinf
+sinf:
+ btst.b #sign_bit,LOCAL_EX(a0) ;get sign of source operand
+ bne ld_minf ;if negative branch
+ bra ld_pinf
+*
+* Load a signed one to fp0; do not set inex2/ainex
+*
+ xdef sone
+sone:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source
+ bne ld_mone
+ bra ld_pone
+*
+* Load a signed pi/2 to fp0; do not set inex2/ainex
+*
+ xdef spi_2
+spi_2:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source
+ bne ld_mpi2
+ bra ld_ppi2
+*
+* Load either a +0 or +inf for plus/minus operand
+*
+ xdef szr_inf
+szr_inf:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source
+ bne ld_pzero
+ bra ld_pinf
+*
+* Result is either an operr or +inf for plus/minus operand
+* [Used by slogn, slognp1, slog10, and slog2]
+*
+ xdef sopr_inf
+sopr_inf:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source
+ bne t_operr
+ bra ld_pinf
+*
+* FLOGNP1
+*
+ xdef sslognp1
+sslognp1:
+ fmovem.x (a0),fp0
+ fcmp.b #-1,fp0
+ fbgt slognp1
+ fbeq t_dz2 ;if = -1, divide by zero exception
+ fmove.l #0,FPSR ;clr N flag
+ bra t_operr ;take care of operands < -1
+*
+* FETOXM1
+*
+ xdef setoxm1i
+setoxm1i:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check sign of source
+ bne ld_mone
+ bra ld_pinf
+*
+* FLOGN
+*
+* Test for 1.0 as an input argument, returning +zero. Also check
+* the sign and return operr if negative.
+*
+ xdef sslogn
+sslogn:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ bne t_operr ;take care of operands < 0
+ cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input
+ bne slogn
+ cmpi.l #$80000000,LOCAL_HI(a0)
+ bne slogn
+ tst.l LOCAL_LO(a0)
+ bne slogn
+ fmove.x PZERO,fp0
+ rts
+
+ xdef sslognd
+sslognd:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ beq slognd
+ bra t_operr ;take care of operands < 0
+
+*
+* FLOG10
+*
+ xdef sslog10
+sslog10:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ bne t_operr ;take care of operands < 0
+ cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input
+ bne slog10
+ cmpi.l #$80000000,LOCAL_HI(a0)
+ bne slog10
+ tst.l LOCAL_LO(a0)
+ bne slog10
+ fmove.x PZERO,fp0
+ rts
+
+ xdef sslog10d
+sslog10d:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ beq slog10d
+ bra t_operr ;take care of operands < 0
+
+*
+* FLOG2
+*
+ xdef sslog2
+sslog2:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ bne t_operr ;take care of operands < 0
+ cmpi.w #$3fff,LOCAL_EX(a0) ;test for 1.0 input
+ bne slog2
+ cmpi.l #$80000000,LOCAL_HI(a0)
+ bne slog2
+ tst.l LOCAL_LO(a0)
+ bne slog2
+ fmove.x PZERO,fp0
+ rts
+
+ xdef sslog2d
+sslog2d:
+ btst.b #sign_bit,LOCAL_EX(a0)
+ beq slog2d
+ bra t_operr ;take care of operands < 0
+
+*
+* FMOD
+*
+pmodt:
+* ;$21 fmod
+* ;dtag,stag
+ dc.l smod ; 00,00 norm,norm = normal
+ dc.l smod_oper ; 00,01 norm,zero = nan with operr
+ dc.l smod_fpn ; 00,10 norm,inf = fpn
+ dc.l smod_snan ; 00,11 norm,nan = nan
+ dc.l smod_zro ; 01,00 zero,norm = +-zero
+ dc.l smod_oper ; 01,01 zero,zero = nan with operr
+ dc.l smod_zro ; 01,10 zero,inf = +-zero
+ dc.l smod_snan ; 01,11 zero,nan = nan
+ dc.l smod_oper ; 10,00 inf,norm = nan with operr
+ dc.l smod_oper ; 10,01 inf,zero = nan with operr
+ dc.l smod_oper ; 10,10 inf,inf = nan with operr
+ dc.l smod_snan ; 10,11 inf,nan = nan
+ dc.l smod_dnan ; 11,00 nan,norm = nan
+ dc.l smod_dnan ; 11,01 nan,zero = nan
+ dc.l smod_dnan ; 11,10 nan,inf = nan
+ dc.l smod_dnan ; 11,11 nan,nan = nan
+
+ xdef pmod
+pmod:
+ clr.b FPSR_QBYTE(a6) ; clear quotient field
+ bfextu STAG(a6){0:3},d0 ;stag = d0
+ bfextu DTAG(a6){0:3},d1 ;dtag = d1
+
+*
+* Alias extended denorms to norms for the jump table.
+*
+ bclr.l #2,d0
+ bclr.l #2,d1
+
+ lsl.b #2,d1
+ or.b d0,d1 ;d1{3:2} = dtag, d1{1:0} = stag
+* ;Tag values:
+* ;00 = norm or denorm
+* ;01 = zero
+* ;10 = inf
+* ;11 = nan
+ lea pmodt,a1
+ move.l (a1,d1.w*4),a1
+ jmp (a1)
+
+smod_snan:
+ bra src_nan
+smod_dnan:
+ bra dst_nan
+smod_oper:
+ bra t_operr
+smod_zro:
+ move.b ETEMP(a6),d1 ;get sign of src op
+ move.b FPTEMP(a6),d0 ;get sign of dst op
+ eor.b d0,d1 ;get exor of sign bits
+ btst.l #7,d1 ;test for sign
+ beq.b smod_zsn ;if clr, do not set sign big
+ bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit
+smod_zsn:
+ btst.l #7,d0 ;test if + or -
+ beq ld_pzero ;if pos then load +0
+ bra ld_mzero ;else neg load -0
+
+smod_fpn:
+ move.b ETEMP(a6),d1 ;get sign of src op
+ move.b FPTEMP(a6),d0 ;get sign of dst op
+ eor.b d0,d1 ;get exor of sign bits
+ btst.l #7,d1 ;test for sign
+ beq.b smod_fsn ;if clr, do not set sign big
+ bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit
+smod_fsn:
+ tst.b DTAG(a6) ;filter out denormal destination case
+ bpl.b smod_nrm ;
+ lea.l FPTEMP(a6),a0 ;a0<- addr(FPTEMP)
+ bra t_resdnrm ;force UNFL(but exact) result
+smod_nrm:
+ fmove.l USER_FPCR(a6),fpcr ;use user's rmode and precision
+ fmove.x FPTEMP(a6),fp0 ;return dest to fp0
+ rts
+
+*
+* FREM
+*
+premt:
+* ;$25 frem
+* ;dtag,stag
+ dc.l srem ; 00,00 norm,norm = normal
+ dc.l srem_oper ; 00,01 norm,zero = nan with operr
+ dc.l srem_fpn ; 00,10 norm,inf = fpn
+ dc.l srem_snan ; 00,11 norm,nan = nan
+ dc.l srem_zro ; 01,00 zero,norm = +-zero
+ dc.l srem_oper ; 01,01 zero,zero = nan with operr
+ dc.l srem_zro ; 01,10 zero,inf = +-zero
+ dc.l srem_snan ; 01,11 zero,nan = nan
+ dc.l srem_oper ; 10,00 inf,norm = nan with operr
+ dc.l srem_oper ; 10,01 inf,zero = nan with operr
+ dc.l srem_oper ; 10,10 inf,inf = nan with operr
+ dc.l srem_snan ; 10,11 inf,nan = nan
+ dc.l srem_dnan ; 11,00 nan,norm = nan
+ dc.l srem_dnan ; 11,01 nan,zero = nan
+ dc.l srem_dnan ; 11,10 nan,inf = nan
+ dc.l srem_dnan ; 11,11 nan,nan = nan
+
+ xdef prem
+prem:
+ clr.b FPSR_QBYTE(a6) ;clear quotient field
+ bfextu STAG(a6){0:3},d0 ;stag = d0
+ bfextu DTAG(a6){0:3},d1 ;dtag = d1
+*
+* Alias extended denorms to norms for the jump table.
+*
+ bclr #2,d0
+ bclr #2,d1
+
+ lsl.b #2,d1
+ or.b d0,d1 ;d1{3:2} = dtag, d1{1:0} = stag
+* ;Tag values:
+* ;00 = norm or denorm
+* ;01 = zero
+* ;10 = inf
+* ;11 = nan
+ lea premt,a1
+ move.l (a1,d1.w*4),a1
+ jmp (a1)
+
+srem_snan:
+ bra src_nan
+srem_dnan:
+ bra dst_nan
+srem_oper:
+ bra t_operr
+srem_zro:
+ move.b ETEMP(a6),d1 ;get sign of src op
+ move.b FPTEMP(a6),d0 ;get sign of dst op
+ eor.b d0,d1 ;get exor of sign bits
+ btst.l #7,d1 ;test for sign
+ beq.b srem_zsn ;if clr, do not set sign big
+ bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit
+srem_zsn:
+ btst.l #7,d0 ;test if + or -
+ beq ld_pzero ;if pos then load +0
+ bra ld_mzero ;else neg load -0
+
+srem_fpn:
+ move.b ETEMP(a6),d1 ;get sign of src op
+ move.b FPTEMP(a6),d0 ;get sign of dst op
+ eor.b d0,d1 ;get exor of sign bits
+ btst.l #7,d1 ;test for sign
+ beq.b srem_fsn ;if clr, do not set sign big
+ bset.b #q_sn_bit,FPSR_QBYTE(a6) ;set q-byte sign bit
+srem_fsn:
+ tst.b DTAG(a6) ;filter out denormal destination case
+ bpl.b srem_nrm ;
+ lea.l FPTEMP(a6),a0 ;a0<- addr(FPTEMP)
+ bra t_resdnrm ;force UNFL(but exact) result
+srem_nrm:
+ fmove.l USER_FPCR(a6),fpcr ;use user's rmode and precision
+ fmove.x FPTEMP(a6),fp0 ;return dest to fp0
+ rts
+*
+* FSCALE
+*
+pscalet:
+* ;$26 fscale
+* ;dtag,stag
+ dc.l sscale ; 00,00 norm,norm = result
+ dc.l sscale ; 00,01 norm,zero = fpn
+ dc.l scl_opr ; 00,10 norm,inf = nan with operr
+ dc.l scl_snan ; 00,11 norm,nan = nan
+ dc.l scl_zro ; 01,00 zero,norm = +-zero
+ dc.l scl_zro ; 01,01 zero,zero = +-zero
+ dc.l scl_opr ; 01,10 zero,inf = nan with operr
+ dc.l scl_snan ; 01,11 zero,nan = nan
+ dc.l scl_inf ; 10,00 inf,norm = +-inf
+ dc.l scl_inf ; 10,01 inf,zero = +-inf
+ dc.l scl_opr ; 10,10 inf,inf = nan with operr
+ dc.l scl_snan ; 10,11 inf,nan = nan
+ dc.l scl_dnan ; 11,00 nan,norm = nan
+ dc.l scl_dnan ; 11,01 nan,zero = nan
+ dc.l scl_dnan ; 11,10 nan,inf = nan
+ dc.l scl_dnan ; 11,11 nan,nan = nan
+
+ xdef pscale
+pscale:
+ bfextu STAG(a6){0:3},d0 ;stag in d0
+ bfextu DTAG(a6){0:3},d1 ;dtag in d1
+ bclr.l #2,d0 ;alias denorm into norm
+ bclr.l #2,d1 ;alias denorm into norm
+ lsl.b #2,d1
+ or.b d0,d1 ;d1{4:2} = dtag, d1{1:0} = stag
+* ;dtag values stag values:
+* ;000 = norm 00 = norm
+* ;001 = zero 01 = zero
+* ;010 = inf 10 = inf
+* ;011 = nan 11 = nan
+* ;100 = dnrm
+*
+*
+ lea.l pscalet,a1 ;load start of jump table
+ move.l (a1,d1.w*4),a1 ;load a1 with label depending on tag
+ jmp (a1) ;go to the routine
+
+scl_opr:
+ bra t_operr
+
+scl_dnan:
+ bra dst_nan
+
+scl_zro:
+ btst.b #sign_bit,FPTEMP_EX(a6) ;test if + or -
+ beq ld_pzero ;if pos then load +0
+ bra ld_mzero ;if neg then load -0
+scl_inf:
+ btst.b #sign_bit,FPTEMP_EX(a6) ;test if + or -
+ beq ld_pinf ;if pos then load +inf
+ bra ld_minf ;else neg load -inf
+scl_snan:
+ bra src_nan
+*
+* FSINCOS
+*
+ xdef ssincosz
+ssincosz:
+ btst.b #sign_bit,ETEMP(a6) ;get sign
+ beq.b sincosp
+ fmove.x MZERO,fp0
+ bra.b sincoscom
+sincosp:
+ fmove.x PZERO,fp0
+sincoscom:
+ fmovem.x PONE,fp1 ;do not allow FPSR to be affected
+ bra sto_cos ;store cosine result
+
+ xdef ssincosi
+ssincosi:
+ fmove.x QNAN,fp1 ;load NAN
+ bsr sto_cos ;store cosine result
+ fmove.x QNAN,fp0 ;load NAN
+ bra t_operr
+
+ xdef ssincosnan
+ssincosnan:
+ move.l ETEMP_EX(a6),FP_SCR1(a6)
+ move.l ETEMP_HI(a6),FP_SCR1+4(a6)
+ move.l ETEMP_LO(a6),FP_SCR1+8(a6)
+ bset.b #signan_bit,FP_SCR1+4(a6)
+ fmovem.x FP_SCR1(a6),fp1
+ bsr sto_cos
+ bra src_nan
+*
+* This code forces default values for the zero, inf, and nan cases
+* in the transcendentals code. The CC bits must be set in the
+* stacked FPSR to be correctly reported.
+*
+***Returns +PI/2
+ xdef ld_ppi2
+ld_ppi2:
+ fmove.x PPIBY2,fp0 ;load +pi/2
+ bra t_inx2 ;set inex2 exc
+
+***Returns -PI/2
+ xdef ld_mpi2
+ld_mpi2:
+ fmove.x MPIBY2,fp0 ;load -pi/2
+ or.l #neg_mask,USER_FPSR(a6) ;set N bit
+ bra t_inx2 ;set inex2 exc
+
+***Returns +inf
+ xdef ld_pinf
+ld_pinf:
+ fmove.x PINF,fp0 ;load +inf
+ or.l #inf_mask,USER_FPSR(a6) ;set I bit
+ rts
+
+***Returns -inf
+ xdef ld_minf
+ld_minf:
+ fmove.x MINF,fp0 ;load -inf
+ or.l #neg_mask+inf_mask,USER_FPSR(a6) ;set N and I bits
+ rts
+
+***Returns +1
+ xdef ld_pone
+ld_pone:
+ fmove.x PONE,fp0 ;load +1
+ rts
+
+***Returns -1
+ xdef ld_mone
+ld_mone:
+ fmove.x MONE,fp0 ;load -1
+ or.l #neg_mask,USER_FPSR(a6) ;set N bit
+ rts
+
+***Returns +0
+ xdef ld_pzero
+ld_pzero:
+ fmove.x PZERO,fp0 ;load +0
+ or.l #z_mask,USER_FPSR(a6) ;set Z bit
+ rts
+
+***Returns -0
+ xdef ld_mzero
+ld_mzero:
+ fmove.x MZERO,fp0 ;load -0
+ or.l #neg_mask+z_mask,USER_FPSR(a6) ;set N and Z bits
+ rts
+
+ end