162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| x_snan.sa 3.3 7/1/91 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| fpsp_snan --- FPSP handler for signalling NAN exception 562306a36Sopenharmony_ci| 662306a36Sopenharmony_ci| SNAN for float -> integer conversions (integer conversion of 762306a36Sopenharmony_ci| an SNAN) is a non-maskable run-time exception. 862306a36Sopenharmony_ci| 962306a36Sopenharmony_ci| For trap disabled the 040 does the following: 1062306a36Sopenharmony_ci| If the dest data format is s, d, or x, then the SNAN bit in the NAN 1162306a36Sopenharmony_ci| is set to one and the resulting non-signaling NAN (truncated if 1262306a36Sopenharmony_ci| necessary) is transferred to the dest. If the dest format is b, w, 1362306a36Sopenharmony_ci| or l, then garbage is written to the dest (actually the upper 32 bits 1462306a36Sopenharmony_ci| of the mantissa are sent to the integer unit). 1562306a36Sopenharmony_ci| 1662306a36Sopenharmony_ci| For trap enabled the 040 does the following: 1762306a36Sopenharmony_ci| If the inst is move_out, then the results are the same as for trap 1862306a36Sopenharmony_ci| disabled with the exception posted. If the instruction is not move_ 1962306a36Sopenharmony_ci| out, the dest. is not modified, and the exception is posted. 2062306a36Sopenharmony_ci| 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 2362306a36Sopenharmony_ci| All Rights Reserved 2462306a36Sopenharmony_ci| 2562306a36Sopenharmony_ci| For details on the license for this file, please see the 2662306a36Sopenharmony_ci| file, README, in this same directory. 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciX_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci |section 8 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#include "fpsp.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci |xref get_fline 3562306a36Sopenharmony_ci |xref mem_write 3662306a36Sopenharmony_ci |xref real_snan 3762306a36Sopenharmony_ci |xref real_inex 3862306a36Sopenharmony_ci |xref fpsp_done 3962306a36Sopenharmony_ci |xref reg_dest 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci .global fpsp_snan 4262306a36Sopenharmony_cifpsp_snan: 4362306a36Sopenharmony_ci link %a6,#-LOCAL_SIZE 4462306a36Sopenharmony_ci fsave -(%a7) 4562306a36Sopenharmony_ci moveml %d0-%d1/%a0-%a1,USER_DA(%a6) 4662306a36Sopenharmony_ci fmovemx %fp0-%fp3,USER_FP0(%a6) 4762306a36Sopenharmony_ci fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci| 5062306a36Sopenharmony_ci| Check if trap enabled 5162306a36Sopenharmony_ci| 5262306a36Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) 5362306a36Sopenharmony_ci bnes ena |If enabled, then branch 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci bsrl move_out |else SNAN disabled 5662306a36Sopenharmony_ci| 5762306a36Sopenharmony_ci| It is possible to have an inex1 exception with the 5862306a36Sopenharmony_ci| snan. If the inex enable bit is set in the FPCR, and either 5962306a36Sopenharmony_ci| inex2 or inex1 occurred, we must clean up and branch to the 6062306a36Sopenharmony_ci| real inex handler. 6162306a36Sopenharmony_ci| 6262306a36Sopenharmony_cick_inex: 6362306a36Sopenharmony_ci moveb FPCR_ENABLE(%a6),%d0 6462306a36Sopenharmony_ci andb FPSR_EXCEPT(%a6),%d0 6562306a36Sopenharmony_ci andib #0x3,%d0 6662306a36Sopenharmony_ci beq end_snan 6762306a36Sopenharmony_ci| 6862306a36Sopenharmony_ci| Inexact enabled and reported, and we must take an inexact exception. 6962306a36Sopenharmony_ci| 7062306a36Sopenharmony_citake_inex: 7162306a36Sopenharmony_ci moveb #INEX_VEC,EXC_VEC+1(%a6) 7262306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 7362306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 7462306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 7562306a36Sopenharmony_ci frestore (%a7)+ 7662306a36Sopenharmony_ci unlk %a6 7762306a36Sopenharmony_ci bral real_inex 7862306a36Sopenharmony_ci| 7962306a36Sopenharmony_ci| SNAN is enabled. Check if inst is move_out. 8062306a36Sopenharmony_ci| Make any corrections to the 040 output as necessary. 8162306a36Sopenharmony_ci| 8262306a36Sopenharmony_ciena: 8362306a36Sopenharmony_ci btstb #5,CMDREG1B(%a6) |if set, inst is move out 8462306a36Sopenharmony_ci beq not_out 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci bsrl move_out 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cireport_snan: 8962306a36Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 9062306a36Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 9162306a36Sopenharmony_ci bnes ck_rev 9262306a36Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 9362306a36Sopenharmony_ci bras rep_con 9462306a36Sopenharmony_cick_rev: 9562306a36Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 9662306a36Sopenharmony_cirep_con: 9762306a36Sopenharmony_ci clrl (%a7) 9862306a36Sopenharmony_ciloop1: 9962306a36Sopenharmony_ci clrl -(%a7) |clear and dec a7 10062306a36Sopenharmony_ci dbra %d0,loop1 10162306a36Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |format a busy frame 10262306a36Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) 10362306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 10462306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 10562306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 10662306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 10762306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 10862306a36Sopenharmony_ci frestore (%a7)+ 10962306a36Sopenharmony_ci unlk %a6 11062306a36Sopenharmony_ci bral real_snan 11162306a36Sopenharmony_ci| 11262306a36Sopenharmony_ci| Exit snan handler by expanding the unimp frame into a busy frame 11362306a36Sopenharmony_ci| 11462306a36Sopenharmony_ciend_snan: 11562306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 11862306a36Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 11962306a36Sopenharmony_ci bnes ck_rev2 12062306a36Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 12162306a36Sopenharmony_ci bras rep_con2 12262306a36Sopenharmony_cick_rev2: 12362306a36Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 12462306a36Sopenharmony_cirep_con2: 12562306a36Sopenharmony_ci clrl (%a7) 12662306a36Sopenharmony_ciloop2: 12762306a36Sopenharmony_ci clrl -(%a7) |clear and dec a7 12862306a36Sopenharmony_ci dbra %d0,loop2 12962306a36Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |format a busy frame 13062306a36Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) |write busy size 13162306a36Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 13262306a36Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 13362306a36Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 13462306a36Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 13562306a36Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 13662306a36Sopenharmony_ci frestore (%a7)+ 13762306a36Sopenharmony_ci unlk %a6 13862306a36Sopenharmony_ci bral fpsp_done 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci| 14162306a36Sopenharmony_ci| Move_out 14262306a36Sopenharmony_ci| 14362306a36Sopenharmony_cimove_out: 14462306a36Sopenharmony_ci movel EXC_EA(%a6),%a0 |get <ea> from exc frame 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0} 14762306a36Sopenharmony_ci cmpil #0,%d0 |check for long 14862306a36Sopenharmony_ci beqs sto_long |branch if move_out long 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci cmpil #4,%d0 |check for word 15162306a36Sopenharmony_ci beqs sto_word |branch if move_out word 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci cmpil #6,%d0 |check for byte 15462306a36Sopenharmony_ci beqs sto_byte |branch if move_out byte 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci| 15762306a36Sopenharmony_ci| Not byte, word or long 15862306a36Sopenharmony_ci| 15962306a36Sopenharmony_ci rts 16062306a36Sopenharmony_ci| 16162306a36Sopenharmony_ci| Get the 32 most significant bits of etemp mantissa 16262306a36Sopenharmony_ci| 16362306a36Sopenharmony_cisto_long: 16462306a36Sopenharmony_ci movel ETEMP_HI(%a6),%d1 16562306a36Sopenharmony_ci movel #4,%d0 |load byte count 16662306a36Sopenharmony_ci| 16762306a36Sopenharmony_ci| Set signalling nan bit 16862306a36Sopenharmony_ci| 16962306a36Sopenharmony_ci bsetl #30,%d1 17062306a36Sopenharmony_ci| 17162306a36Sopenharmony_ci| Store to the users destination address 17262306a36Sopenharmony_ci| 17362306a36Sopenharmony_ci tstl %a0 |check if <ea> is 0 17462306a36Sopenharmony_ci beqs wrt_dn |destination is a data register 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 17762306a36Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 17862306a36Sopenharmony_ci movel %a7,%a0 |load src addr of snan into a0 17962306a36Sopenharmony_ci bsrl mem_write |write snan to user memory 18062306a36Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 18162306a36Sopenharmony_ci rts 18262306a36Sopenharmony_ci| 18362306a36Sopenharmony_ci| Get the 16 most significant bits of etemp mantissa 18462306a36Sopenharmony_ci| 18562306a36Sopenharmony_cisto_word: 18662306a36Sopenharmony_ci movel ETEMP_HI(%a6),%d1 18762306a36Sopenharmony_ci movel #2,%d0 |load byte count 18862306a36Sopenharmony_ci| 18962306a36Sopenharmony_ci| Set signalling nan bit 19062306a36Sopenharmony_ci| 19162306a36Sopenharmony_ci bsetl #30,%d1 19262306a36Sopenharmony_ci| 19362306a36Sopenharmony_ci| Store to the users destination address 19462306a36Sopenharmony_ci| 19562306a36Sopenharmony_ci tstl %a0 |check if <ea> is 0 19662306a36Sopenharmony_ci beqs wrt_dn |destination is a data register 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 19962306a36Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 20062306a36Sopenharmony_ci movel %a7,%a0 |point to low word 20162306a36Sopenharmony_ci bsrl mem_write |write snan to user memory 20262306a36Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 20362306a36Sopenharmony_ci rts 20462306a36Sopenharmony_ci| 20562306a36Sopenharmony_ci| Get the 8 most significant bits of etemp mantissa 20662306a36Sopenharmony_ci| 20762306a36Sopenharmony_cisto_byte: 20862306a36Sopenharmony_ci movel ETEMP_HI(%a6),%d1 20962306a36Sopenharmony_ci movel #1,%d0 |load byte count 21062306a36Sopenharmony_ci| 21162306a36Sopenharmony_ci| Set signalling nan bit 21262306a36Sopenharmony_ci| 21362306a36Sopenharmony_ci bsetl #30,%d1 21462306a36Sopenharmony_ci| 21562306a36Sopenharmony_ci| Store to the users destination address 21662306a36Sopenharmony_ci| 21762306a36Sopenharmony_ci tstl %a0 |check if <ea> is 0 21862306a36Sopenharmony_ci beqs wrt_dn |destination is a data register 21962306a36Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 22062306a36Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 22162306a36Sopenharmony_ci movel %a7,%a0 |point to source byte 22262306a36Sopenharmony_ci bsrl mem_write |write snan to user memory 22362306a36Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 22462306a36Sopenharmony_ci rts 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci| 22762306a36Sopenharmony_ci| wrt_dn --- write to a data register 22862306a36Sopenharmony_ci| 22962306a36Sopenharmony_ci| We get here with D1 containing the data to write and D0 the 23062306a36Sopenharmony_ci| number of bytes to write: 1=byte,2=word,4=long. 23162306a36Sopenharmony_ci| 23262306a36Sopenharmony_ciwrt_dn: 23362306a36Sopenharmony_ci movel %d1,L_SCR1(%a6) |data 23462306a36Sopenharmony_ci movel %d0,-(%a7) |size 23562306a36Sopenharmony_ci bsrl get_fline |returns fline word in d0 23662306a36Sopenharmony_ci movel %d0,%d1 23762306a36Sopenharmony_ci andil #0x7,%d1 |d1 now holds register number 23862306a36Sopenharmony_ci movel (%sp)+,%d0 |get original size 23962306a36Sopenharmony_ci cmpil #4,%d0 24062306a36Sopenharmony_ci beqs wrt_long 24162306a36Sopenharmony_ci cmpil #2,%d0 24262306a36Sopenharmony_ci bnes wrt_byte 24362306a36Sopenharmony_ciwrt_word: 24462306a36Sopenharmony_ci orl #0x8,%d1 24562306a36Sopenharmony_ci bral reg_dest 24662306a36Sopenharmony_ciwrt_long: 24762306a36Sopenharmony_ci orl #0x10,%d1 24862306a36Sopenharmony_ci bral reg_dest 24962306a36Sopenharmony_ciwrt_byte: 25062306a36Sopenharmony_ci bral reg_dest 25162306a36Sopenharmony_ci| 25262306a36Sopenharmony_ci| Check if it is a src nan or dst nan 25362306a36Sopenharmony_ci| 25462306a36Sopenharmony_cinot_out: 25562306a36Sopenharmony_ci movel DTAG(%a6),%d0 25662306a36Sopenharmony_ci bfextu %d0{#0:#3},%d0 |isolate dtag in lsbs 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci cmpib #3,%d0 |check for nan in destination 25962306a36Sopenharmony_ci bnes issrc |destination nan has priority 26062306a36Sopenharmony_cidst_nan: 26162306a36Sopenharmony_ci btstb #6,FPTEMP_HI(%a6) |check if dest nan is an snan 26262306a36Sopenharmony_ci bnes issrc |no, so check source for snan 26362306a36Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 26462306a36Sopenharmony_ci bras cont 26562306a36Sopenharmony_ciissrc: 26662306a36Sopenharmony_ci movew ETEMP_EX(%a6),%d0 26762306a36Sopenharmony_cicont: 26862306a36Sopenharmony_ci btstl #15,%d0 |test for sign of snan 26962306a36Sopenharmony_ci beqs clr_neg 27062306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) 27162306a36Sopenharmony_ci bra report_snan 27262306a36Sopenharmony_ciclr_neg: 27362306a36Sopenharmony_ci bclrb #neg_bit,FPSR_CC(%a6) 27462306a36Sopenharmony_ci bra report_snan 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci |end 277