* $NetBSD: x_snan.sa,v 1.4 2001/09/16 16:34:32 wiz 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_snan.sa 3.3 7/1/91
*
* fpsp_snan --- FPSP handler for signalling NAN exception
*
* SNAN for float -> integer conversions (integer conversion of
* an SNAN) is a non-maskable run-time exception.
*
* For trap disabled the 040 does the following:
* If the dest data format is s, d, or x, then the SNAN bit in the NAN
* is set to one and the resulting non-signaling NAN (truncated if
* necessary) is transferred to the dest. If the dest format is b, w,
* or l, then garbage is written to the dest (actually the upper 32 bits
* of the mantissa are sent to the integer unit).
*
* For trap enabled the 040 does the following:
* If the inst is move_out, then the results are the same as for trap
* disabled with the exception posted. If the instruction is not move_
* out, the dest. is not modified, and the exception is posted.
*
X_SNAN IDNT 2,1 Motorola 040 Floating Point Software Package
section 8
include fpsp.h
xref get_fline
xref mem_write
xref real_snan
xref real_inex
xref fpsp_done
xref reg_dest
xdef fpsp_snan
fpsp_snan:
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)
*
* Check if trap enabled
*
btst.b #snan_bit,FPCR_ENABLE(a6)
bne.b ena ;If enabled, then branch
bsr.l move_out ;else SNAN disabled
*
* It is possible to have an inex1 exception with the
* snan. If the inex enable bit is set in the FPCR, and either
* inex2 or inex1 occurred, 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.w end_snan
*
* Inexact enabled and reported, and we must take an inexact exception.
*
take_inex:
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
*
* SNAN is enabled. Check if inst is move_out.
* Make any corrections to the 040 output as necessary.
*
ena:
btst.b #5,CMDREG1B(a6) ;if set, inst is move out
beq.w not_out
bsr.l move_out
report_snan:
move.b (a7),VER_TMP(a6)
cmpi.b #VER_40,(a7) ;test for orig unimp frame
bne.b ck_rev
moveq.l #13,d0 ;need to zero 14 lwords
bra.b rep_con
ck_rev:
moveq.l #11,d0 ;need to zero 12 lwords
rep_con:
clr.l (a7)
loop1:
clr.l -(a7) ;clear and dec a7
dbra.w d0,loop1
move.b VER_TMP(a6),(a7) ;format a busy frame
move.b #BUSY_SIZE-4,1(a7)
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 real_snan
*
* Exit snan handler by expanding the unimp frame into a busy frame
*
end_snan:
bclr.b #E1,E_BYTE(a6)
move.b (a7),VER_TMP(a6)
cmpi.b #VER_40,(a7) ;test for orig unimp frame
bne.b ck_rev2
moveq.l #13,d0 ;need to zero 14 lwords
bra.b rep_con2
ck_rev2:
moveq.l #11,d0 ;need to zero 12 lwords
rep_con2:
clr.l (a7)
loop2:
clr.l -(a7) ;clear and dec a7
dbra.w d0,loop2
move.b VER_TMP(a6),(a7) ;format a busy frame
move.b #BUSY_SIZE-4,1(a7) ;write busy size
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
*
* Move_out
*
move_out:
move.l EXC_EA(a6),a0 ;get <ea> from exc frame
bfextu CMDREG1B(a6){3:3},d0 ;move rx field to d0{2:0}
tst.l d0 ;check for long
beq.b sto_long ;branch if move_out long
cmpi.l #4,d0 ;check for word
beq.b sto_word ;branch if move_out word
cmpi.l #6,d0 ;check for byte
beq.b sto_byte ;branch if move_out byte
*
* Not byte, word or long
*
rts
*
* Get the 32 most significant bits of etemp mantissa
*
sto_long:
move.l ETEMP_HI(a6),d1
move.l #4,d0 ;load byte count
*
* Set signalling nan bit
*
bset.l #30,d1
*
* Store to the users destination address
*
tst.l a0 ;check if <ea> is 0
beq.b wrt_dn ;destination is a data register
move.l d1,-(a7) ;move the snan onto the stack
move.l a0,a1 ;load dest addr into a1
move.l a7,a0 ;load src addr of snan into a0
bsr.l mem_write ;write snan to user memory
move.l (a7)+,d1 ;clear off stack
rts
*
* Get the 16 most significant bits of etemp mantissa
*
sto_word:
move.l ETEMP_HI(a6),d1
move.l #2,d0 ;load byte count
*
* Set signalling nan bit
*
bset.l #30,d1
*
* Store to the users destination address
*
tst.l a0 ;check if <ea> is 0
beq.b wrt_dn ;destination is a data register
move.l d1,-(a7) ;move the snan onto the stack
move.l a0,a1 ;load dest addr into a1
move.l a7,a0 ;point to low word
bsr.l mem_write ;write snan to user memory
move.l (a7)+,d1 ;clear off stack
rts
*
* Get the 8 most significant bits of etemp mantissa
*
sto_byte:
move.l ETEMP_HI(a6),d1
move.l #1,d0 ;load byte count
*
* Set signalling nan bit
*
bset.l #30,d1
*
* Store to the users destination address
*
tst.l a0 ;check if <ea> is 0
beq.b wrt_dn ;destination is a data register
move.l d1,-(a7) ;move the snan onto the stack
move.l a0,a1 ;load dest addr into a1
move.l a7,a0 ;point to source byte
bsr.l mem_write ;write snan to user memory
move.l (a7)+,d1 ;clear off stack
rts
*
* wrt_dn --- write to a data register
*
* We get here with D1 containing the data to write and D0 the
* number of bytes to write: 1=byte,2=word,4=long.
*
wrt_dn:
move.l d1,L_SCR1(a6) ;data
move.l d0,-(a7) ;size
bsr.l get_fline ;returns fline word in d0
move.l d0,d1
andi.l #$7,d1 ;d1 now holds register number
move.l (sp)+,d0 ;get original size
cmpi.l #4,d0
beq.b wrt_long
cmpi.l #2,d0
bne.b wrt_byte
wrt_word:
or.l #$8,d1
bra.l reg_dest
wrt_long:
or.l #$10,d1
bra.l reg_dest
wrt_byte:
bra.l reg_dest
*
* Check if it is a src nan or dst nan
*
not_out:
move.l DTAG(a6),d0
bfextu d0{0:3},d0 ;isolate dtag in lsbs
cmpi.b #3,d0 ;check for nan in destination
bne.b issrc ;destination nan has priority
dst_nan:
btst.b #6,FPTEMP_HI(a6) ;check if dest nan is an snan
bne.b issrc ;no, so check source for snan
move.w FPTEMP_EX(a6),d0
bra.b cont
issrc:
move.w ETEMP_EX(a6),d0
cont:
btst.l #15,d0 ;test for sign of snan
beq.b clr_neg
bset.b #neg_bit,FPSR_CC(a6)
bra.w report_snan
clr_neg:
bclr.b #neg_bit,FPSR_CC(a6)
bra.w report_snan
end