| | |
| | 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 |