summaryrefslogtreecommitdiff
path: root/sys/arch/m68k/fpsp/x_unfl.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/x_unfl.sa
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/m68k/fpsp/x_unfl.sa')
-rw-r--r--sys/arch/m68k/fpsp/x_unfl.sa294
1 files changed, 294 insertions, 0 deletions
diff --git a/sys/arch/m68k/fpsp/x_unfl.sa b/sys/arch/m68k/fpsp/x_unfl.sa
new file mode 100644
index 00000000000..9987455bc88
--- /dev/null
+++ b/sys/arch/m68k/fpsp/x_unfl.sa
@@ -0,0 +1,294 @@
+* $NetBSD: x_unfl.sa,v 1.3 1994/10/26 07:50:30 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.
+
+*
+* x_unfl.sa 3.4 7/1/91
+*
+* fpsp_unfl --- FPSP handler for underflow exception
+*
+* Trap disabled results
+* For 881/2 compatibility, sw must denormalize the intermediate
+* result, then store the result. Denormalization is accomplished
+* by taking the intermediate result (which is always normalized) and
+* shifting the mantissa right while incrementing the exponent until
+* it is equal to the denormalized exponent for the destination
+* format. After denormalizatoin, the result is rounded to the
+* destination format.
+*
+* Trap enabled results
+* All trap disabled code applies. In addition the exceptional
+* operand needs to made available to the user with a bias of $6000
+* added to the exponent.
+*
+
+X_UNFL IDNT 2,1 Motorola 040 Floating Point Software Package
+
+ section 8
+
+ include fpsp.h
+
+ xref denorm
+ xref round
+ xref store
+ xref g_rndpr
+ xref g_opcls
+ xref g_dfmtou
+ xref real_unfl
+ xref real_inex
+ xref fpsp_done
+ xref b1238_fix
+
+ xdef fpsp_unfl
+fpsp_unfl:
+ link a6,#-LOCAL_SIZE
+ fsave -(a7)
+ movem.l d0-d1/a0-a1,USER_DA(a6)
+ fmovem.x fp0-fp3,USER_FP0(a6)
+ fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6)
+
+*
+ bsr.l unf_res ;denormalize, round & store interm op
+*
+* If underflow exceptions are not enabled, check for inexact
+* exception
+*
+ btst.b #unfl_bit,FPCR_ENABLE(a6)
+ beq.b ck_inex
+
+ btst.b #E3,E_BYTE(a6)
+ beq.b no_e3_1
+*
+* Clear dirty bit on dest resister in the frame before branching
+* to b1238_fix.
+*
+ bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no
+ bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit
+ bsr.l b1238_fix ;test for bug1238 case
+ move.l USER_FPSR(a6),FPSR_SHADOW(a6)
+ or.l #sx_mask,E_BYTE(a6)
+no_e3_1:
+ movem.l USER_DA(a6),d0-d1/a0-a1
+ fmovem.x USER_FP0(a6),fp0-fp3
+ fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
+ frestore (a7)+
+ unlk a6
+ bra.l real_unfl
+*
+* It is possible to have either inex2 or inex1 exceptions with the
+* unfl. If the inex enable bit is set in the FPCR, and either
+* inex2 or inex1 occured, we must clean up and branch to the
+* real inex handler.
+*
+ck_inex:
+ move.b FPCR_ENABLE(a6),d0
+ and.b FPSR_EXCEPT(a6),d0
+ andi.b #$3,d0
+ beq.b unfl_done
+
+*
+* Inexact enabled and reported, and we must take an inexact exception
+*
+take_inex:
+ btst.b #E3,E_BYTE(a6)
+ beq.b no_e3_2
+*
+* Clear dirty bit on dest resister in the frame before branching
+* to b1238_fix.
+*
+ bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no
+ bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit
+ bsr.l b1238_fix ;test for bug1238 case
+ move.l USER_FPSR(a6),FPSR_SHADOW(a6)
+ or.l #sx_mask,E_BYTE(a6)
+no_e3_2:
+ move.b #INEX_VEC,EXC_VEC+1(a6)
+ movem.l USER_DA(a6),d0-d1/a0-a1
+ fmovem.x USER_FP0(a6),fp0-fp3
+ fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
+ frestore (a7)+
+ unlk a6
+ bra.l real_inex
+
+unfl_done:
+ bclr.b #E3,E_BYTE(a6)
+ beq.b e1_set ;if set then branch
+*
+* Clear dirty bit on dest resister in the frame before branching
+* to b1238_fix.
+*
+ bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no
+ bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit
+ bsr.l b1238_fix ;test for bug1238 case
+ move.l USER_FPSR(a6),FPSR_SHADOW(a6)
+ or.l #sx_mask,E_BYTE(a6)
+ movem.l USER_DA(a6),d0-d1/a0-a1
+ fmovem.x USER_FP0(a6),fp0-fp3
+ fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
+ frestore (a7)+
+ unlk a6
+ bra.l fpsp_done
+e1_set:
+ movem.l USER_DA(a6),d0-d1/a0-a1
+ fmovem.x USER_FP0(a6),fp0-fp3
+ fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar
+ unlk a6
+ bra.l fpsp_done
+*
+* unf_res --- underflow result calculation
+*
+unf_res:
+ bsr.l g_rndpr ;returns RND_PREC in d0 0=ext,
+* ;1=sgl, 2=dbl
+* ;we need the RND_PREC in the
+* ;upper word for round
+ clr.w -(a7)
+ move.w d0,-(a7) ;copy RND_PREC to stack
+*
+*
+* If the exception bit set is E3, the exceptional operand from the
+* fpu is in WBTEMP; else it is in FPTEMP.
+*
+ btst.b #E3,E_BYTE(a6)
+ beq.b unf_E1
+unf_E3:
+ lea WBTEMP(a6),a0 ;a0 now points to operand
+*
+* Test for fsgldiv and fsglmul. If the inst was one of these, then
+* force the precision to extended for the denorm routine. Use
+* the user's precision for the round routine.
+*
+ move.w CMDREG3B(a6),d1 ;check for fsgldiv or fsglmul
+ andi.w #$7f,d1
+ cmpi.w #$30,d1 ;check for sgldiv
+ beq.b unf_sgl
+ cmpi.w #$33,d1 ;check for sglmul
+ bne.b unf_cont ;if not, use fpcr prec in round
+unf_sgl:
+ clr.l d0
+ move.w #$1,(a7) ;override g_rndpr precision
+* ;force single
+ bra.b unf_cont
+unf_E1:
+ lea FPTEMP(a6),a0 ;a0 now points to operand
+unf_cont:
+ bclr.b #sign_bit,LOCAL_EX(a0) ;clear sign bit
+ sne LOCAL_SGN(a0) ;store sign
+
+ bsr.l denorm ;returns denorm, a0 points to it
+*
+* WARNING:
+* ;d0 has guard,round sticky bit
+* ;make sure that it is not corrupted
+* ;before it reaches the round subroutine
+* ;also ensure that a0 isn't corrupted
+
+*
+* Set up d1 for round subroutine d1 contains the PREC/MODE
+* information respectively on upper/lower register halves.
+*
+ bfextu FPCR_MODE(a6){2:2},d1 ;get mode from FPCR
+* ;mode in lower d1
+ add.l (a7)+,d1 ;merge PREC/MODE
+*
+* WARNING: a0 and d0 are assumed to be intact between the denorm and
+* round subroutines. All code between these two subroutines
+* must not corrupt a0 and d0.
+*
+*
+* Perform Round
+* Input: a0 points to input operand
+* d0{31:29} has guard, round, sticky
+* d1{01:00} has rounding mode
+* d1{17:16} has rounding precision
+* Output: a0 points to rounded operand
+*
+
+ bsr.l round ;returns rounded denorm at (a0)
+*
+* Differentiate between store to memory vs. store to register
+*
+unf_store:
+ bsr.l g_opcls ;returns opclass in d0{2:0}
+ cmpi.b #$3,d0
+ bne.b not_opc011
+*
+* At this point, a store to memory is pending
+*
+opc011:
+ bsr.l g_dfmtou
+ tst.b d0
+ beq.b ext_opc011 ;If extended, do not subtract
+* ;If destination format is sgl/dbl,
+ tst.b LOCAL_HI(a0) ;If rounded result is normal,don't
+* ;subtract
+ bmi.b ext_opc011
+ subq.w #1,LOCAL_EX(a0) ;account for denorm bias vs.
+* ;normalized bias
+* ; normalized denormalized
+* ;single $7f $7e
+* ;double $3ff $3fe
+*
+ext_opc011:
+ bsr.l store ;stores to memory
+ bra.b unf_done ;finish up
+
+*
+* At this point, a store to a float register is pending
+*
+not_opc011:
+ bsr.l store ;stores to float register
+* ;a0 is not corrupted on a store to a
+* ;float register.
+*
+* Set the condition codes according to result
+*
+ tst.l LOCAL_HI(a0) ;check upper mantissa
+ bne.b ck_sgn
+ tst.l LOCAL_LO(a0) ;check lower mantissa
+ bne.b ck_sgn
+ bset.b #z_bit,FPSR_CC(a6) ;set condition codes if zero
+ck_sgn:
+ btst.b #sign_bit,LOCAL_EX(a0) ;check the sign bit
+ beq.b unf_done
+ bset.b #neg_bit,FPSR_CC(a6)
+
+*
+* Finish.
+*
+unf_done:
+ btst.b #inex2_bit,FPSR_EXCEPT(a6)
+ beq.b no_aunfl
+ bset.b #aunfl_bit,FPSR_AEXCEPT(a6)
+no_aunfl:
+ rts
+
+ end