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