Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / m68k / fpsp040 / x_snan.S
diff --git a/kernel/arch/m68k/fpsp040/x_snan.S b/kernel/arch/m68k/fpsp040/x_snan.S
new file mode 100644 (file)
index 0000000..4ed7664
--- /dev/null
@@ -0,0 +1,276 @@
+|
+|      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.
+|
+
+|              Copyright (C) Motorola, Inc. 1990
+|                      All Rights Reserved
+|
+|       For details on the license for this file, please see the
+|       file, README, in this same directory.
+
+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
+
+       .global fpsp_snan
+fpsp_snan:
+       link            %a6,#-LOCAL_SIZE
+       fsave           -(%a7)
+       moveml          %d0-%d1/%a0-%a1,USER_DA(%a6)
+       fmovemx %fp0-%fp3,USER_FP0(%a6)
+       fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
+
+|
+| Check if trap enabled
+|
+       btstb           #snan_bit,FPCR_ENABLE(%a6)
+       bnes            ena             |If enabled, then branch
+
+       bsrl            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:
+       moveb   FPCR_ENABLE(%a6),%d0
+       andb    FPSR_EXCEPT(%a6),%d0
+       andib   #0x3,%d0
+       beq     end_snan
+|
+| Inexact enabled and reported, and we must take an inexact exception.
+|
+take_inex:
+       moveb           #INEX_VEC,EXC_VEC+1(%a6)
+       moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
+       fmovemx USER_FP0(%a6),%fp0-%fp3
+       fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+       frestore        (%a7)+
+       unlk            %a6
+       bral            real_inex
+|
+| SNAN is enabled.  Check if inst is move_out.
+| Make any corrections to the 040 output as necessary.
+|
+ena:
+       btstb           #5,CMDREG1B(%a6) |if set, inst is move out
+       beq             not_out
+
+       bsrl            move_out
+
+report_snan:
+       moveb           (%a7),VER_TMP(%a6)
+       cmpib           #VER_40,(%a7)   |test for orig unimp frame
+       bnes            ck_rev
+       moveql          #13,%d0         |need to zero 14 lwords
+       bras            rep_con
+ck_rev:
+       moveql          #11,%d0         |need to zero 12 lwords
+rep_con:
+       clrl            (%a7)
+loop1:
+       clrl            -(%a7)          |clear and dec a7
+       dbra            %d0,loop1
+       moveb           VER_TMP(%a6),(%a7) |format a busy frame
+       moveb           #BUSY_SIZE-4,1(%a7)
+       movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
+       orl             #sx_mask,E_BYTE(%a6)
+       moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
+       fmovemx USER_FP0(%a6),%fp0-%fp3
+       fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+       frestore        (%a7)+
+       unlk            %a6
+       bral            real_snan
+|
+| Exit snan handler by expanding the unimp frame into a busy frame
+|
+end_snan:
+       bclrb           #E1,E_BYTE(%a6)
+
+       moveb           (%a7),VER_TMP(%a6)
+       cmpib           #VER_40,(%a7)   |test for orig unimp frame
+       bnes            ck_rev2
+       moveql          #13,%d0         |need to zero 14 lwords
+       bras            rep_con2
+ck_rev2:
+       moveql          #11,%d0         |need to zero 12 lwords
+rep_con2:
+       clrl            (%a7)
+loop2:
+       clrl            -(%a7)          |clear and dec a7
+       dbra            %d0,loop2
+       moveb           VER_TMP(%a6),(%a7) |format a busy frame
+       moveb           #BUSY_SIZE-4,1(%a7) |write busy size
+       movel           USER_FPSR(%a6),FPSR_SHADOW(%a6)
+       orl             #sx_mask,E_BYTE(%a6)
+       moveml          USER_DA(%a6),%d0-%d1/%a0-%a1
+       fmovemx USER_FP0(%a6),%fp0-%fp3
+       fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
+       frestore        (%a7)+
+       unlk            %a6
+       bral            fpsp_done
+
+|
+| Move_out
+|
+move_out:
+       movel           EXC_EA(%a6),%a0 |get <ea> from exc frame
+
+       bfextu          CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0}
+       cmpil           #0,%d0          |check for long
+       beqs            sto_long        |branch if move_out long
+
+       cmpil           #4,%d0          |check for word
+       beqs            sto_word        |branch if move_out word
+
+       cmpil           #6,%d0          |check for byte
+       beqs            sto_byte        |branch if move_out byte
+
+|
+| Not byte, word or long
+|
+       rts
+|
+| Get the 32 most significant bits of etemp mantissa
+|
+sto_long:
+       movel           ETEMP_HI(%a6),%d1
+       movel           #4,%d0          |load byte count
+|
+| Set signalling nan bit
+|
+       bsetl           #30,%d1
+|
+| Store to the users destination address
+|
+       tstl            %a0             |check if <ea> is 0
+       beqs            wrt_dn          |destination is a data register
+
+       movel           %d1,-(%a7)      |move the snan onto the stack
+       movel           %a0,%a1         |load dest addr into a1
+       movel           %a7,%a0         |load src addr of snan into a0
+       bsrl            mem_write       |write snan to user memory
+       movel           (%a7)+,%d1      |clear off stack
+       rts
+|
+| Get the 16 most significant bits of etemp mantissa
+|
+sto_word:
+       movel           ETEMP_HI(%a6),%d1
+       movel           #2,%d0          |load byte count
+|
+| Set signalling nan bit
+|
+       bsetl           #30,%d1
+|
+| Store to the users destination address
+|
+       tstl            %a0             |check if <ea> is 0
+       beqs            wrt_dn          |destination is a data register
+
+       movel           %d1,-(%a7)      |move the snan onto the stack
+       movel           %a0,%a1         |load dest addr into a1
+       movel           %a7,%a0         |point to low word
+       bsrl            mem_write       |write snan to user memory
+       movel           (%a7)+,%d1      |clear off stack
+       rts
+|
+| Get the 8 most significant bits of etemp mantissa
+|
+sto_byte:
+       movel           ETEMP_HI(%a6),%d1
+       movel           #1,%d0          |load byte count
+|
+| Set signalling nan bit
+|
+       bsetl           #30,%d1
+|
+| Store to the users destination address
+|
+       tstl            %a0             |check if <ea> is 0
+       beqs            wrt_dn          |destination is a data register
+       movel           %d1,-(%a7)      |move the snan onto the stack
+       movel           %a0,%a1         |load dest addr into a1
+       movel           %a7,%a0         |point to source byte
+       bsrl            mem_write       |write snan to user memory
+       movel           (%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:
+       movel           %d1,L_SCR1(%a6) |data
+       movel           %d0,-(%a7)      |size
+       bsrl            get_fline       |returns fline word in d0
+       movel           %d0,%d1
+       andil           #0x7,%d1                |d1 now holds register number
+       movel           (%sp)+,%d0      |get original size
+       cmpil           #4,%d0
+       beqs            wrt_long
+       cmpil           #2,%d0
+       bnes            wrt_byte
+wrt_word:
+       orl             #0x8,%d1
+       bral            reg_dest
+wrt_long:
+       orl             #0x10,%d1
+       bral            reg_dest
+wrt_byte:
+       bral            reg_dest
+|
+| Check if it is a src nan or dst nan
+|
+not_out:
+       movel           DTAG(%a6),%d0
+       bfextu          %d0{#0:#3},%d0  |isolate dtag in lsbs
+
+       cmpib           #3,%d0          |check for nan in destination
+       bnes            issrc           |destination nan has priority
+dst_nan:
+       btstb           #6,FPTEMP_HI(%a6) |check if dest nan is an snan
+       bnes            issrc           |no, so check source for snan
+       movew           FPTEMP_EX(%a6),%d0
+       bras            cont
+issrc:
+       movew           ETEMP_EX(%a6),%d0
+cont:
+       btstl           #15,%d0         |test for sign of snan
+       beqs            clr_neg
+       bsetb           #neg_bit,FPSR_CC(%a6)
+       bra             report_snan
+clr_neg:
+       bclrb           #neg_bit,FPSR_CC(%a6)
+       bra             report_snan
+
+       |end