File indexing completed on 2025-05-11 08:23:49
0001 #include "fpsp-namespace.h"
0002 //
0003 //
0004 // x_snan.sa 3.3 7/1/91
0005 //
0006 // fpsp_snan --- FPSP handler for signalling NAN exception
0007 //
0008 // SNAN for float -> integer conversions (integer conversion of
0009 // an SNAN) is a non-maskable run-time exception.
0010 //
0011 // For trap disabled the 040 does the following:
0012 // If the dest data format is s, d, or x, then the SNAN bit in the NAN
0013 // is set to one and the resulting non-signaling NAN (truncated if
0014 // necessary) is transferred to the dest. If the dest format is b, w,
0015 // or l, then garbage is written to the dest (actually the upper 32 bits
0016 // of the mantissa are sent to the integer unit).
0017 //
0018 // For trap enabled the 040 does the following:
0019 // If the inst is move_out, then the results are the same as for trap
0020 // disabled with the exception posted. If the instruction is not move_
0021 // out, the dest. is not modified, and the exception is posted.
0022 //
0023
0024 // Copyright (C) Motorola, Inc. 1990
0025 // All Rights Reserved
0026 //
0027 // THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
0028 // The copyright notice above does not evidence any
0029 // actual or intended publication of such source code.
0030
0031 X_SNAN: //idnt 2,1 | Motorola 040 Floating Point Software Package
0032
0033 |section 8
0034
0035 #include "fpsp.defs"
0036
0037 |xref get_fline
0038 |xref mem_write
0039 |xref real_snan
0040 |xref real_inex
0041 |xref fpsp_done
0042 |xref reg_dest
0043
0044 .global fpsp_snan
0045 fpsp_snan:
0046 link %a6,#-LOCAL_SIZE
0047 fsave -(%a7)
0048 moveml %d0-%d1/%a0-%a1,USER_DA(%a6)
0049 fmovemx %fp0-%fp3,USER_FP0(%a6)
0050 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6)
0051
0052 //
0053 // Check if trap enabled
0054 //
0055 btstb #snan_bit,FPCR_ENABLE(%a6)
0056 bnes ena //If enabled, then branch
0057
0058 bsrl move_out //else SNAN disabled
0059 //
0060 // It is possible to have an inex1 exception with the
0061 // snan. If the inex enable bit is set in the FPCR, and either
0062 // inex2 or inex1 occurred, we must clean up and branch to the
0063 // real inex handler.
0064 //
0065 ck_inex:
0066 moveb FPCR_ENABLE(%a6),%d0
0067 andb FPSR_EXCEPT(%a6),%d0
0068 andib #0x3,%d0
0069 beq end_snan
0070 //
0071 // Inexact enabled and reported, and we must take an inexact exception.
0072 //
0073 take_inex:
0074 moveb #INEX_VEC,EXC_VEC+1(%a6)
0075 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
0076 fmovemx USER_FP0(%a6),%fp0-%fp3
0077 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0078 frestore (%a7)+
0079 unlk %a6
0080 bral real_inex
0081 //
0082 // SNAN is enabled. Check if inst is move_out.
0083 // Make any corrections to the 040 output as necessary.
0084 //
0085 ena:
0086 btstb #5,CMDREG1B(%a6) //if set, inst is move out
0087 beq not_out
0088
0089 bsrl move_out
0090
0091 report_snan:
0092 moveb (%a7),VER_TMP(%a6)
0093 cmpib #VER_40,(%a7) //test for orig unimp frame
0094 bnes ck_rev
0095 moveql #13,%d0 //need to zero 14 lwords
0096 bras rep_con
0097 ck_rev:
0098 moveql #11,%d0 //need to zero 12 lwords
0099 rep_con:
0100 clrl (%a7)
0101 loop1:
0102 clrl -(%a7) //clear and dec a7
0103 dbra %d0,loop1
0104 moveb VER_TMP(%a6),(%a7) //format a busy frame
0105 moveb #BUSY_SIZE-4,1(%a7)
0106 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
0107 orl #sx_mask,E_BYTE(%a6)
0108 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
0109 fmovemx USER_FP0(%a6),%fp0-%fp3
0110 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0111 frestore (%a7)+
0112 unlk %a6
0113 bral real_snan
0114 //
0115 // Exit snan handler by expanding the unimp frame into a busy frame
0116 //
0117 end_snan:
0118 bclrb #E1,E_BYTE(%a6)
0119
0120 moveb (%a7),VER_TMP(%a6)
0121 cmpib #VER_40,(%a7) //test for orig unimp frame
0122 bnes ck_rev2
0123 moveql #13,%d0 //need to zero 14 lwords
0124 bras rep_con2
0125 ck_rev2:
0126 moveql #11,%d0 //need to zero 12 lwords
0127 rep_con2:
0128 clrl (%a7)
0129 loop2:
0130 clrl -(%a7) //clear and dec a7
0131 dbra %d0,loop2
0132 moveb VER_TMP(%a6),(%a7) //format a busy frame
0133 moveb #BUSY_SIZE-4,1(%a7) //write busy size
0134 movel USER_FPSR(%a6),FPSR_SHADOW(%a6)
0135 orl #sx_mask,E_BYTE(%a6)
0136 moveml USER_DA(%a6),%d0-%d1/%a0-%a1
0137 fmovemx USER_FP0(%a6),%fp0-%fp3
0138 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar
0139 frestore (%a7)+
0140 unlk %a6
0141 bral fpsp_done
0142
0143 //
0144 // Move_out
0145 //
0146 move_out:
0147 movel EXC_EA(%a6),%a0 //get <ea> from exc frame
0148
0149 bfextu CMDREG1B(%a6){#3:#3},%d0 //move rx field to d0{2:0}
0150 cmpil #0,%d0 //check for long
0151 beqs sto_long //branch if move_out long
0152
0153 cmpil #4,%d0 //check for word
0154 beqs sto_word //branch if move_out word
0155
0156 cmpil #6,%d0 //check for byte
0157 beqs sto_byte //branch if move_out byte
0158
0159 //
0160 // Not byte, word or long
0161 //
0162 rts
0163 //
0164 // Get the 32 most significant bits of etemp mantissa
0165 //
0166 sto_long:
0167 movel ETEMP_HI(%a6),%d1
0168 movel #4,%d0 //load byte count
0169 //
0170 // Set signalling nan bit
0171 //
0172 bsetl #30,%d1
0173 //
0174 // Store to the users destination address
0175 //
0176 tstl %a0 //check if <ea> is 0
0177 beqs wrt_dn //destination is a data register
0178
0179 movel %d1,-(%a7) //move the snan onto the stack
0180 movel %a0,%a1 //load dest addr into a1
0181 movel %a7,%a0 //load src addr of snan into a0
0182 bsrl mem_write //write snan to user memory
0183 movel (%a7)+,%d1 //clear off stack
0184 rts
0185 //
0186 // Get the 16 most significant bits of etemp mantissa
0187 //
0188 sto_word:
0189 movel ETEMP_HI(%a6),%d1
0190 movel #2,%d0 //load byte count
0191 //
0192 // Set signalling nan bit
0193 //
0194 bsetl #30,%d1
0195 //
0196 // Store to the users destination address
0197 //
0198 tstl %a0 //check if <ea> is 0
0199 beqs wrt_dn //destination is a data register
0200
0201 movel %d1,-(%a7) //move the snan onto the stack
0202 movel %a0,%a1 //load dest addr into a1
0203 movel %a7,%a0 //point to low word
0204 bsrl mem_write //write snan to user memory
0205 movel (%a7)+,%d1 //clear off stack
0206 rts
0207 //
0208 // Get the 8 most significant bits of etemp mantissa
0209 //
0210 sto_byte:
0211 movel ETEMP_HI(%a6),%d1
0212 movel #1,%d0 //load byte count
0213 //
0214 // Set signalling nan bit
0215 //
0216 bsetl #30,%d1
0217 //
0218 // Store to the users destination address
0219 //
0220 tstl %a0 //check if <ea> is 0
0221 beqs wrt_dn //destination is a data register
0222 movel %d1,-(%a7) //move the snan onto the stack
0223 movel %a0,%a1 //load dest addr into a1
0224 movel %a7,%a0 //point to source byte
0225 bsrl mem_write //write snan to user memory
0226 movel (%a7)+,%d1 //clear off stack
0227 rts
0228
0229 //
0230 // wrt_dn --- write to a data register
0231 //
0232 // We get here with D1 containing the data to write and D0 the
0233 // number of bytes to write: 1=byte,2=word,4=long.
0234 //
0235 wrt_dn:
0236 movel %d1,L_SCR1(%a6) //data
0237 movel %d0,-(%a7) //size
0238 bsrl get_fline //returns fline word in d0
0239 movel %d0,%d1
0240 andil #0x7,%d1 //d1 now holds register number
0241 movel (%sp)+,%d0 //get original size
0242 cmpil #4,%d0
0243 beqs wrt_long
0244 cmpil #2,%d0
0245 bnes wrt_byte
0246 wrt_word:
0247 orl #0x8,%d1
0248 bral reg_dest
0249 wrt_long:
0250 orl #0x10,%d1
0251 bral reg_dest
0252 wrt_byte:
0253 bral reg_dest
0254 //
0255 // Check if it is a src nan or dst nan
0256 //
0257 not_out:
0258 movel DTAG(%a6),%d0
0259 bfextu %d0{#0:#3},%d0 //isolate dtag in lsbs
0260
0261 cmpib #3,%d0 //check for nan in destination
0262 bnes issrc //destination nan has priority
0263 dst_nan:
0264 btstb #6,FPTEMP_HI(%a6) //check if dest nan is an snan
0265 bnes issrc //no, so check source for snan
0266 movew FPTEMP_EX(%a6),%d0
0267 bras cont
0268 issrc:
0269 movew ETEMP_EX(%a6),%d0
0270 cont:
0271 btstl #15,%d0 //test for sign of snan
0272 beqs clr_neg
0273 bsetb #neg_bit,FPSR_CC(%a6)
0274 bra report_snan
0275 clr_neg:
0276 bclrb #neg_bit,FPSR_CC(%a6)
0277 bra report_snan
0278
0279 |end