x_snan.S (6621B)
1| 2| x_snan.sa 3.3 7/1/91 3| 4| fpsp_snan --- FPSP handler for signalling NAN exception 5| 6| SNAN for float -> integer conversions (integer conversion of 7| an SNAN) is a non-maskable run-time exception. 8| 9| For trap disabled the 040 does the following: 10| If the dest data format is s, d, or x, then the SNAN bit in the NAN 11| is set to one and the resulting non-signaling NAN (truncated if 12| necessary) is transferred to the dest. If the dest format is b, w, 13| or l, then garbage is written to the dest (actually the upper 32 bits 14| of the mantissa are sent to the integer unit). 15| 16| For trap enabled the 040 does the following: 17| If the inst is move_out, then the results are the same as for trap 18| disabled with the exception posted. If the instruction is not move_ 19| out, the dest. is not modified, and the exception is posted. 20| 21 22| Copyright (C) Motorola, Inc. 1990 23| All Rights Reserved 24| 25| For details on the license for this file, please see the 26| file, README, in this same directory. 27 28X_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package 29 30 |section 8 31 32#include "fpsp.h" 33 34 |xref get_fline 35 |xref mem_write 36 |xref real_snan 37 |xref real_inex 38 |xref fpsp_done 39 |xref reg_dest 40 41 .global fpsp_snan 42fpsp_snan: 43 link %a6,#-LOCAL_SIZE 44 fsave -(%a7) 45 moveml %d0-%d1/%a0-%a1,USER_DA(%a6) 46 fmovemx %fp0-%fp3,USER_FP0(%a6) 47 fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) 48 49| 50| Check if trap enabled 51| 52 btstb #snan_bit,FPCR_ENABLE(%a6) 53 bnes ena |If enabled, then branch 54 55 bsrl move_out |else SNAN disabled 56| 57| It is possible to have an inex1 exception with the 58| snan. If the inex enable bit is set in the FPCR, and either 59| inex2 or inex1 occurred, we must clean up and branch to the 60| real inex handler. 61| 62ck_inex: 63 moveb FPCR_ENABLE(%a6),%d0 64 andb FPSR_EXCEPT(%a6),%d0 65 andib #0x3,%d0 66 beq end_snan 67| 68| Inexact enabled and reported, and we must take an inexact exception. 69| 70take_inex: 71 moveb #INEX_VEC,EXC_VEC+1(%a6) 72 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 73 fmovemx USER_FP0(%a6),%fp0-%fp3 74 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 75 frestore (%a7)+ 76 unlk %a6 77 bral real_inex 78| 79| SNAN is enabled. Check if inst is move_out. 80| Make any corrections to the 040 output as necessary. 81| 82ena: 83 btstb #5,CMDREG1B(%a6) |if set, inst is move out 84 beq not_out 85 86 bsrl move_out 87 88report_snan: 89 moveb (%a7),VER_TMP(%a6) 90 cmpib #VER_40,(%a7) |test for orig unimp frame 91 bnes ck_rev 92 moveql #13,%d0 |need to zero 14 lwords 93 bras rep_con 94ck_rev: 95 moveql #11,%d0 |need to zero 12 lwords 96rep_con: 97 clrl (%a7) 98loop1: 99 clrl -(%a7) |clear and dec a7 100 dbra %d0,loop1 101 moveb VER_TMP(%a6),(%a7) |format a busy frame 102 moveb #BUSY_SIZE-4,1(%a7) 103 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 104 orl #sx_mask,E_BYTE(%a6) 105 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 106 fmovemx USER_FP0(%a6),%fp0-%fp3 107 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 108 frestore (%a7)+ 109 unlk %a6 110 bral real_snan 111| 112| Exit snan handler by expanding the unimp frame into a busy frame 113| 114end_snan: 115 bclrb #E1,E_BYTE(%a6) 116 117 moveb (%a7),VER_TMP(%a6) 118 cmpib #VER_40,(%a7) |test for orig unimp frame 119 bnes ck_rev2 120 moveql #13,%d0 |need to zero 14 lwords 121 bras rep_con2 122ck_rev2: 123 moveql #11,%d0 |need to zero 12 lwords 124rep_con2: 125 clrl (%a7) 126loop2: 127 clrl -(%a7) |clear and dec a7 128 dbra %d0,loop2 129 moveb VER_TMP(%a6),(%a7) |format a busy frame 130 moveb #BUSY_SIZE-4,1(%a7) |write busy size 131 movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 132 orl #sx_mask,E_BYTE(%a6) 133 moveml USER_DA(%a6),%d0-%d1/%a0-%a1 134 fmovemx USER_FP0(%a6),%fp0-%fp3 135 fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 136 frestore (%a7)+ 137 unlk %a6 138 bral fpsp_done 139 140| 141| Move_out 142| 143move_out: 144 movel EXC_EA(%a6),%a0 |get <ea> from exc frame 145 146 bfextu CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0} 147 cmpil #0,%d0 |check for long 148 beqs sto_long |branch if move_out long 149 150 cmpil #4,%d0 |check for word 151 beqs sto_word |branch if move_out word 152 153 cmpil #6,%d0 |check for byte 154 beqs sto_byte |branch if move_out byte 155 156| 157| Not byte, word or long 158| 159 rts 160| 161| Get the 32 most significant bits of etemp mantissa 162| 163sto_long: 164 movel ETEMP_HI(%a6),%d1 165 movel #4,%d0 |load byte count 166| 167| Set signalling nan bit 168| 169 bsetl #30,%d1 170| 171| Store to the users destination address 172| 173 tstl %a0 |check if <ea> is 0 174 beqs wrt_dn |destination is a data register 175 176 movel %d1,-(%a7) |move the snan onto the stack 177 movel %a0,%a1 |load dest addr into a1 178 movel %a7,%a0 |load src addr of snan into a0 179 bsrl mem_write |write snan to user memory 180 movel (%a7)+,%d1 |clear off stack 181 rts 182| 183| Get the 16 most significant bits of etemp mantissa 184| 185sto_word: 186 movel ETEMP_HI(%a6),%d1 187 movel #2,%d0 |load byte count 188| 189| Set signalling nan bit 190| 191 bsetl #30,%d1 192| 193| Store to the users destination address 194| 195 tstl %a0 |check if <ea> is 0 196 beqs wrt_dn |destination is a data register 197 198 movel %d1,-(%a7) |move the snan onto the stack 199 movel %a0,%a1 |load dest addr into a1 200 movel %a7,%a0 |point to low word 201 bsrl mem_write |write snan to user memory 202 movel (%a7)+,%d1 |clear off stack 203 rts 204| 205| Get the 8 most significant bits of etemp mantissa 206| 207sto_byte: 208 movel ETEMP_HI(%a6),%d1 209 movel #1,%d0 |load byte count 210| 211| Set signalling nan bit 212| 213 bsetl #30,%d1 214| 215| Store to the users destination address 216| 217 tstl %a0 |check if <ea> is 0 218 beqs wrt_dn |destination is a data register 219 movel %d1,-(%a7) |move the snan onto the stack 220 movel %a0,%a1 |load dest addr into a1 221 movel %a7,%a0 |point to source byte 222 bsrl mem_write |write snan to user memory 223 movel (%a7)+,%d1 |clear off stack 224 rts 225 226| 227| wrt_dn --- write to a data register 228| 229| We get here with D1 containing the data to write and D0 the 230| number of bytes to write: 1=byte,2=word,4=long. 231| 232wrt_dn: 233 movel %d1,L_SCR1(%a6) |data 234 movel %d0,-(%a7) |size 235 bsrl get_fline |returns fline word in d0 236 movel %d0,%d1 237 andil #0x7,%d1 |d1 now holds register number 238 movel (%sp)+,%d0 |get original size 239 cmpil #4,%d0 240 beqs wrt_long 241 cmpil #2,%d0 242 bnes wrt_byte 243wrt_word: 244 orl #0x8,%d1 245 bral reg_dest 246wrt_long: 247 orl #0x10,%d1 248 bral reg_dest 249wrt_byte: 250 bral reg_dest 251| 252| Check if it is a src nan or dst nan 253| 254not_out: 255 movel DTAG(%a6),%d0 256 bfextu %d0{#0:#3},%d0 |isolate dtag in lsbs 257 258 cmpib #3,%d0 |check for nan in destination 259 bnes issrc |destination nan has priority 260dst_nan: 261 btstb #6,FPTEMP_HI(%a6) |check if dest nan is an snan 262 bnes issrc |no, so check source for snan 263 movew FPTEMP_EX(%a6),%d0 264 bras cont 265issrc: 266 movew ETEMP_EX(%a6),%d0 267cont: 268 btstl #15,%d0 |test for sign of snan 269 beqs clr_neg 270 bsetb #neg_bit,FPSR_CC(%a6) 271 bra report_snan 272clr_neg: 273 bclrb #neg_bit,FPSR_CC(%a6) 274 bra report_snan 275 276 |end