18c2ecf20Sopenharmony_ci| 28c2ecf20Sopenharmony_ci| x_snan.sa 3.3 7/1/91 38c2ecf20Sopenharmony_ci| 48c2ecf20Sopenharmony_ci| fpsp_snan --- FPSP handler for signalling NAN exception 58c2ecf20Sopenharmony_ci| 68c2ecf20Sopenharmony_ci| SNAN for float -> integer conversions (integer conversion of 78c2ecf20Sopenharmony_ci| an SNAN) is a non-maskable run-time exception. 88c2ecf20Sopenharmony_ci| 98c2ecf20Sopenharmony_ci| For trap disabled the 040 does the following: 108c2ecf20Sopenharmony_ci| If the dest data format is s, d, or x, then the SNAN bit in the NAN 118c2ecf20Sopenharmony_ci| is set to one and the resulting non-signaling NAN (truncated if 128c2ecf20Sopenharmony_ci| necessary) is transferred to the dest. If the dest format is b, w, 138c2ecf20Sopenharmony_ci| or l, then garbage is written to the dest (actually the upper 32 bits 148c2ecf20Sopenharmony_ci| of the mantissa are sent to the integer unit). 158c2ecf20Sopenharmony_ci| 168c2ecf20Sopenharmony_ci| For trap enabled the 040 does the following: 178c2ecf20Sopenharmony_ci| If the inst is move_out, then the results are the same as for trap 188c2ecf20Sopenharmony_ci| disabled with the exception posted. If the instruction is not move_ 198c2ecf20Sopenharmony_ci| out, the dest. is not modified, and the exception is posted. 208c2ecf20Sopenharmony_ci| 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 238c2ecf20Sopenharmony_ci| All Rights Reserved 248c2ecf20Sopenharmony_ci| 258c2ecf20Sopenharmony_ci| For details on the license for this file, please see the 268c2ecf20Sopenharmony_ci| file, README, in this same directory. 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ciX_SNAN: |idnt 2,1 | Motorola 040 Floating Point Software Package 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci |section 8 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include "fpsp.h" 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci |xref get_fline 358c2ecf20Sopenharmony_ci |xref mem_write 368c2ecf20Sopenharmony_ci |xref real_snan 378c2ecf20Sopenharmony_ci |xref real_inex 388c2ecf20Sopenharmony_ci |xref fpsp_done 398c2ecf20Sopenharmony_ci |xref reg_dest 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci .global fpsp_snan 428c2ecf20Sopenharmony_cifpsp_snan: 438c2ecf20Sopenharmony_ci link %a6,#-LOCAL_SIZE 448c2ecf20Sopenharmony_ci fsave -(%a7) 458c2ecf20Sopenharmony_ci moveml %d0-%d1/%a0-%a1,USER_DA(%a6) 468c2ecf20Sopenharmony_ci fmovemx %fp0-%fp3,USER_FP0(%a6) 478c2ecf20Sopenharmony_ci fmoveml %fpcr/%fpsr/%fpiar,USER_FPCR(%a6) 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci| 508c2ecf20Sopenharmony_ci| Check if trap enabled 518c2ecf20Sopenharmony_ci| 528c2ecf20Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) 538c2ecf20Sopenharmony_ci bnes ena |If enabled, then branch 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci bsrl move_out |else SNAN disabled 568c2ecf20Sopenharmony_ci| 578c2ecf20Sopenharmony_ci| It is possible to have an inex1 exception with the 588c2ecf20Sopenharmony_ci| snan. If the inex enable bit is set in the FPCR, and either 598c2ecf20Sopenharmony_ci| inex2 or inex1 occurred, we must clean up and branch to the 608c2ecf20Sopenharmony_ci| real inex handler. 618c2ecf20Sopenharmony_ci| 628c2ecf20Sopenharmony_cick_inex: 638c2ecf20Sopenharmony_ci moveb FPCR_ENABLE(%a6),%d0 648c2ecf20Sopenharmony_ci andb FPSR_EXCEPT(%a6),%d0 658c2ecf20Sopenharmony_ci andib #0x3,%d0 668c2ecf20Sopenharmony_ci beq end_snan 678c2ecf20Sopenharmony_ci| 688c2ecf20Sopenharmony_ci| Inexact enabled and reported, and we must take an inexact exception. 698c2ecf20Sopenharmony_ci| 708c2ecf20Sopenharmony_citake_inex: 718c2ecf20Sopenharmony_ci moveb #INEX_VEC,EXC_VEC+1(%a6) 728c2ecf20Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 738c2ecf20Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 748c2ecf20Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 758c2ecf20Sopenharmony_ci frestore (%a7)+ 768c2ecf20Sopenharmony_ci unlk %a6 778c2ecf20Sopenharmony_ci bral real_inex 788c2ecf20Sopenharmony_ci| 798c2ecf20Sopenharmony_ci| SNAN is enabled. Check if inst is move_out. 808c2ecf20Sopenharmony_ci| Make any corrections to the 040 output as necessary. 818c2ecf20Sopenharmony_ci| 828c2ecf20Sopenharmony_ciena: 838c2ecf20Sopenharmony_ci btstb #5,CMDREG1B(%a6) |if set, inst is move out 848c2ecf20Sopenharmony_ci beq not_out 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci bsrl move_out 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cireport_snan: 898c2ecf20Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 908c2ecf20Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 918c2ecf20Sopenharmony_ci bnes ck_rev 928c2ecf20Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 938c2ecf20Sopenharmony_ci bras rep_con 948c2ecf20Sopenharmony_cick_rev: 958c2ecf20Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 968c2ecf20Sopenharmony_cirep_con: 978c2ecf20Sopenharmony_ci clrl (%a7) 988c2ecf20Sopenharmony_ciloop1: 998c2ecf20Sopenharmony_ci clrl -(%a7) |clear and dec a7 1008c2ecf20Sopenharmony_ci dbra %d0,loop1 1018c2ecf20Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |format a busy frame 1028c2ecf20Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) 1038c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 1048c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 1058c2ecf20Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 1068c2ecf20Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 1078c2ecf20Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 1088c2ecf20Sopenharmony_ci frestore (%a7)+ 1098c2ecf20Sopenharmony_ci unlk %a6 1108c2ecf20Sopenharmony_ci bral real_snan 1118c2ecf20Sopenharmony_ci| 1128c2ecf20Sopenharmony_ci| Exit snan handler by expanding the unimp frame into a busy frame 1138c2ecf20Sopenharmony_ci| 1148c2ecf20Sopenharmony_ciend_snan: 1158c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci moveb (%a7),VER_TMP(%a6) 1188c2ecf20Sopenharmony_ci cmpib #VER_40,(%a7) |test for orig unimp frame 1198c2ecf20Sopenharmony_ci bnes ck_rev2 1208c2ecf20Sopenharmony_ci moveql #13,%d0 |need to zero 14 lwords 1218c2ecf20Sopenharmony_ci bras rep_con2 1228c2ecf20Sopenharmony_cick_rev2: 1238c2ecf20Sopenharmony_ci moveql #11,%d0 |need to zero 12 lwords 1248c2ecf20Sopenharmony_cirep_con2: 1258c2ecf20Sopenharmony_ci clrl (%a7) 1268c2ecf20Sopenharmony_ciloop2: 1278c2ecf20Sopenharmony_ci clrl -(%a7) |clear and dec a7 1288c2ecf20Sopenharmony_ci dbra %d0,loop2 1298c2ecf20Sopenharmony_ci moveb VER_TMP(%a6),(%a7) |format a busy frame 1308c2ecf20Sopenharmony_ci moveb #BUSY_SIZE-4,1(%a7) |write busy size 1318c2ecf20Sopenharmony_ci movel USER_FPSR(%a6),FPSR_SHADOW(%a6) 1328c2ecf20Sopenharmony_ci orl #sx_mask,E_BYTE(%a6) 1338c2ecf20Sopenharmony_ci moveml USER_DA(%a6),%d0-%d1/%a0-%a1 1348c2ecf20Sopenharmony_ci fmovemx USER_FP0(%a6),%fp0-%fp3 1358c2ecf20Sopenharmony_ci fmoveml USER_FPCR(%a6),%fpcr/%fpsr/%fpiar 1368c2ecf20Sopenharmony_ci frestore (%a7)+ 1378c2ecf20Sopenharmony_ci unlk %a6 1388c2ecf20Sopenharmony_ci bral fpsp_done 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci| 1418c2ecf20Sopenharmony_ci| Move_out 1428c2ecf20Sopenharmony_ci| 1438c2ecf20Sopenharmony_cimove_out: 1448c2ecf20Sopenharmony_ci movel EXC_EA(%a6),%a0 |get <ea> from exc frame 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci bfextu CMDREG1B(%a6){#3:#3},%d0 |move rx field to d0{2:0} 1478c2ecf20Sopenharmony_ci cmpil #0,%d0 |check for long 1488c2ecf20Sopenharmony_ci beqs sto_long |branch if move_out long 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci cmpil #4,%d0 |check for word 1518c2ecf20Sopenharmony_ci beqs sto_word |branch if move_out word 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci cmpil #6,%d0 |check for byte 1548c2ecf20Sopenharmony_ci beqs sto_byte |branch if move_out byte 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci| 1578c2ecf20Sopenharmony_ci| Not byte, word or long 1588c2ecf20Sopenharmony_ci| 1598c2ecf20Sopenharmony_ci rts 1608c2ecf20Sopenharmony_ci| 1618c2ecf20Sopenharmony_ci| Get the 32 most significant bits of etemp mantissa 1628c2ecf20Sopenharmony_ci| 1638c2ecf20Sopenharmony_cisto_long: 1648c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),%d1 1658c2ecf20Sopenharmony_ci movel #4,%d0 |load byte count 1668c2ecf20Sopenharmony_ci| 1678c2ecf20Sopenharmony_ci| Set signalling nan bit 1688c2ecf20Sopenharmony_ci| 1698c2ecf20Sopenharmony_ci bsetl #30,%d1 1708c2ecf20Sopenharmony_ci| 1718c2ecf20Sopenharmony_ci| Store to the users destination address 1728c2ecf20Sopenharmony_ci| 1738c2ecf20Sopenharmony_ci tstl %a0 |check if <ea> is 0 1748c2ecf20Sopenharmony_ci beqs wrt_dn |destination is a data register 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 1778c2ecf20Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 1788c2ecf20Sopenharmony_ci movel %a7,%a0 |load src addr of snan into a0 1798c2ecf20Sopenharmony_ci bsrl mem_write |write snan to user memory 1808c2ecf20Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 1818c2ecf20Sopenharmony_ci rts 1828c2ecf20Sopenharmony_ci| 1838c2ecf20Sopenharmony_ci| Get the 16 most significant bits of etemp mantissa 1848c2ecf20Sopenharmony_ci| 1858c2ecf20Sopenharmony_cisto_word: 1868c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),%d1 1878c2ecf20Sopenharmony_ci movel #2,%d0 |load byte count 1888c2ecf20Sopenharmony_ci| 1898c2ecf20Sopenharmony_ci| Set signalling nan bit 1908c2ecf20Sopenharmony_ci| 1918c2ecf20Sopenharmony_ci bsetl #30,%d1 1928c2ecf20Sopenharmony_ci| 1938c2ecf20Sopenharmony_ci| Store to the users destination address 1948c2ecf20Sopenharmony_ci| 1958c2ecf20Sopenharmony_ci tstl %a0 |check if <ea> is 0 1968c2ecf20Sopenharmony_ci beqs wrt_dn |destination is a data register 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 1998c2ecf20Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 2008c2ecf20Sopenharmony_ci movel %a7,%a0 |point to low word 2018c2ecf20Sopenharmony_ci bsrl mem_write |write snan to user memory 2028c2ecf20Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 2038c2ecf20Sopenharmony_ci rts 2048c2ecf20Sopenharmony_ci| 2058c2ecf20Sopenharmony_ci| Get the 8 most significant bits of etemp mantissa 2068c2ecf20Sopenharmony_ci| 2078c2ecf20Sopenharmony_cisto_byte: 2088c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),%d1 2098c2ecf20Sopenharmony_ci movel #1,%d0 |load byte count 2108c2ecf20Sopenharmony_ci| 2118c2ecf20Sopenharmony_ci| Set signalling nan bit 2128c2ecf20Sopenharmony_ci| 2138c2ecf20Sopenharmony_ci bsetl #30,%d1 2148c2ecf20Sopenharmony_ci| 2158c2ecf20Sopenharmony_ci| Store to the users destination address 2168c2ecf20Sopenharmony_ci| 2178c2ecf20Sopenharmony_ci tstl %a0 |check if <ea> is 0 2188c2ecf20Sopenharmony_ci beqs wrt_dn |destination is a data register 2198c2ecf20Sopenharmony_ci movel %d1,-(%a7) |move the snan onto the stack 2208c2ecf20Sopenharmony_ci movel %a0,%a1 |load dest addr into a1 2218c2ecf20Sopenharmony_ci movel %a7,%a0 |point to source byte 2228c2ecf20Sopenharmony_ci bsrl mem_write |write snan to user memory 2238c2ecf20Sopenharmony_ci movel (%a7)+,%d1 |clear off stack 2248c2ecf20Sopenharmony_ci rts 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci| 2278c2ecf20Sopenharmony_ci| wrt_dn --- write to a data register 2288c2ecf20Sopenharmony_ci| 2298c2ecf20Sopenharmony_ci| We get here with D1 containing the data to write and D0 the 2308c2ecf20Sopenharmony_ci| number of bytes to write: 1=byte,2=word,4=long. 2318c2ecf20Sopenharmony_ci| 2328c2ecf20Sopenharmony_ciwrt_dn: 2338c2ecf20Sopenharmony_ci movel %d1,L_SCR1(%a6) |data 2348c2ecf20Sopenharmony_ci movel %d0,-(%a7) |size 2358c2ecf20Sopenharmony_ci bsrl get_fline |returns fline word in d0 2368c2ecf20Sopenharmony_ci movel %d0,%d1 2378c2ecf20Sopenharmony_ci andil #0x7,%d1 |d1 now holds register number 2388c2ecf20Sopenharmony_ci movel (%sp)+,%d0 |get original size 2398c2ecf20Sopenharmony_ci cmpil #4,%d0 2408c2ecf20Sopenharmony_ci beqs wrt_long 2418c2ecf20Sopenharmony_ci cmpil #2,%d0 2428c2ecf20Sopenharmony_ci bnes wrt_byte 2438c2ecf20Sopenharmony_ciwrt_word: 2448c2ecf20Sopenharmony_ci orl #0x8,%d1 2458c2ecf20Sopenharmony_ci bral reg_dest 2468c2ecf20Sopenharmony_ciwrt_long: 2478c2ecf20Sopenharmony_ci orl #0x10,%d1 2488c2ecf20Sopenharmony_ci bral reg_dest 2498c2ecf20Sopenharmony_ciwrt_byte: 2508c2ecf20Sopenharmony_ci bral reg_dest 2518c2ecf20Sopenharmony_ci| 2528c2ecf20Sopenharmony_ci| Check if it is a src nan or dst nan 2538c2ecf20Sopenharmony_ci| 2548c2ecf20Sopenharmony_cinot_out: 2558c2ecf20Sopenharmony_ci movel DTAG(%a6),%d0 2568c2ecf20Sopenharmony_ci bfextu %d0{#0:#3},%d0 |isolate dtag in lsbs 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci cmpib #3,%d0 |check for nan in destination 2598c2ecf20Sopenharmony_ci bnes issrc |destination nan has priority 2608c2ecf20Sopenharmony_cidst_nan: 2618c2ecf20Sopenharmony_ci btstb #6,FPTEMP_HI(%a6) |check if dest nan is an snan 2628c2ecf20Sopenharmony_ci bnes issrc |no, so check source for snan 2638c2ecf20Sopenharmony_ci movew FPTEMP_EX(%a6),%d0 2648c2ecf20Sopenharmony_ci bras cont 2658c2ecf20Sopenharmony_ciissrc: 2668c2ecf20Sopenharmony_ci movew ETEMP_EX(%a6),%d0 2678c2ecf20Sopenharmony_cicont: 2688c2ecf20Sopenharmony_ci btstl #15,%d0 |test for sign of snan 2698c2ecf20Sopenharmony_ci beqs clr_neg 2708c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) 2718c2ecf20Sopenharmony_ci bra report_snan 2728c2ecf20Sopenharmony_ciclr_neg: 2738c2ecf20Sopenharmony_ci bclrb #neg_bit,FPSR_CC(%a6) 2748c2ecf20Sopenharmony_ci bra report_snan 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci |end 277