18c2ecf20Sopenharmony_ci| 28c2ecf20Sopenharmony_ci| kernel_ex.sa 3.3 12/19/90 38c2ecf20Sopenharmony_ci| 48c2ecf20Sopenharmony_ci| This file contains routines to force exception status in the 58c2ecf20Sopenharmony_ci| fpu for exceptional cases detected or reported within the 68c2ecf20Sopenharmony_ci| transcendental functions. Typically, the t_xx routine will 78c2ecf20Sopenharmony_ci| set the appropriate bits in the USER_FPSR word on the stack. 88c2ecf20Sopenharmony_ci| The bits are tested in gen_except.sa to determine if an exceptional 98c2ecf20Sopenharmony_ci| situation needs to be created on return from the FPSP. 108c2ecf20Sopenharmony_ci| 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 138c2ecf20Sopenharmony_ci| All Rights Reserved 148c2ecf20Sopenharmony_ci| 158c2ecf20Sopenharmony_ci| For details on the license for this file, please see the 168c2ecf20Sopenharmony_ci| file, README, in this same directory. 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ciKERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci |section 8 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "fpsp.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cimns_inf: .long 0xffff0000,0x00000000,0x00000000 258c2ecf20Sopenharmony_cipls_inf: .long 0x7fff0000,0x00000000,0x00000000 268c2ecf20Sopenharmony_cinan: .long 0x7fff0000,0xffffffff,0xffffffff 278c2ecf20Sopenharmony_cihuge: .long 0x7ffe0000,0xffffffff,0xffffffff 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci |xref ovf_r_k 308c2ecf20Sopenharmony_ci |xref unf_sub 318c2ecf20Sopenharmony_ci |xref nrm_set 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci .global t_dz 348c2ecf20Sopenharmony_ci .global t_dz2 358c2ecf20Sopenharmony_ci .global t_operr 368c2ecf20Sopenharmony_ci .global t_unfl 378c2ecf20Sopenharmony_ci .global t_ovfl 388c2ecf20Sopenharmony_ci .global t_ovfl2 398c2ecf20Sopenharmony_ci .global t_inx2 408c2ecf20Sopenharmony_ci .global t_frcinx 418c2ecf20Sopenharmony_ci .global t_extdnrm 428c2ecf20Sopenharmony_ci .global t_resdnrm 438c2ecf20Sopenharmony_ci .global dst_nan 448c2ecf20Sopenharmony_ci .global src_nan 458c2ecf20Sopenharmony_ci| 468c2ecf20Sopenharmony_ci| DZ exception 478c2ecf20Sopenharmony_ci| 488c2ecf20Sopenharmony_ci| 498c2ecf20Sopenharmony_ci| if dz trap disabled 508c2ecf20Sopenharmony_ci| store properly signed inf (use sign of etemp) into fp0 518c2ecf20Sopenharmony_ci| set FPSR exception status dz bit, condition code 528c2ecf20Sopenharmony_ci| inf bit, and accrued dz bit 538c2ecf20Sopenharmony_ci| return 548c2ecf20Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 558c2ecf20Sopenharmony_ci| 568c2ecf20Sopenharmony_ci| else dz trap enabled 578c2ecf20Sopenharmony_ci| set exception status bit & accrued bits in FPSR 588c2ecf20Sopenharmony_ci| set flag to disable sto_res from corrupting fp register 598c2ecf20Sopenharmony_ci| return 608c2ecf20Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 618c2ecf20Sopenharmony_ci| 628c2ecf20Sopenharmony_ci| t_dz2 is used by monadic functions such as flogn (from do_func). 638c2ecf20Sopenharmony_ci| t_dz is used by monadic functions such as satanh (from the 648c2ecf20Sopenharmony_ci| transcendental function). 658c2ecf20Sopenharmony_ci| 668c2ecf20Sopenharmony_cit_dz2: 678c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 688c2ecf20Sopenharmony_ci fmovel #0,%FPSR |clr status bits (Z set) 698c2ecf20Sopenharmony_ci btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 708c2ecf20Sopenharmony_ci bnes dz_ena_end 718c2ecf20Sopenharmony_ci bras m_inf |flogx always returns -inf 728c2ecf20Sopenharmony_cit_dz: 738c2ecf20Sopenharmony_ci fmovel #0,%FPSR |clr status bits (Z set) 748c2ecf20Sopenharmony_ci btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 758c2ecf20Sopenharmony_ci bnes dz_ena 768c2ecf20Sopenharmony_ci| 778c2ecf20Sopenharmony_ci| dz disabled 788c2ecf20Sopenharmony_ci| 798c2ecf20Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 808c2ecf20Sopenharmony_ci beqs p_inf |branch if pos sign 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cim_inf: 838c2ecf20Sopenharmony_ci fmovemx mns_inf,%fp0-%fp0 |load -inf 848c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 858c2ecf20Sopenharmony_ci bras set_fpsr 868c2ecf20Sopenharmony_cip_inf: 878c2ecf20Sopenharmony_ci fmovemx pls_inf,%fp0-%fp0 |load +inf 888c2ecf20Sopenharmony_ciset_fpsr: 898c2ecf20Sopenharmony_ci orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 908c2ecf20Sopenharmony_ci rts 918c2ecf20Sopenharmony_ci| 928c2ecf20Sopenharmony_ci| dz enabled 938c2ecf20Sopenharmony_ci| 948c2ecf20Sopenharmony_cidz_ena: 958c2ecf20Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 968c2ecf20Sopenharmony_ci beqs dz_ena_end 978c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 988c2ecf20Sopenharmony_cidz_ena_end: 998c2ecf20Sopenharmony_ci orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 1008c2ecf20Sopenharmony_ci st STORE_FLG(%a6) 1018c2ecf20Sopenharmony_ci rts 1028c2ecf20Sopenharmony_ci| 1038c2ecf20Sopenharmony_ci| OPERR exception 1048c2ecf20Sopenharmony_ci| 1058c2ecf20Sopenharmony_ci| if (operr trap disabled) 1068c2ecf20Sopenharmony_ci| set FPSR exception status operr bit, condition code 1078c2ecf20Sopenharmony_ci| nan bit; Store default NAN into fp0 1088c2ecf20Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 1098c2ecf20Sopenharmony_ci| 1108c2ecf20Sopenharmony_ci| else (operr trap enabled) 1118c2ecf20Sopenharmony_ci| set FPSR exception status operr bit, accrued operr bit 1128c2ecf20Sopenharmony_ci| set flag to disable sto_res from corrupting fp register 1138c2ecf20Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 1148c2ecf20Sopenharmony_ci| 1158c2ecf20Sopenharmony_cit_operr: 1168c2ecf20Sopenharmony_ci orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled 1198c2ecf20Sopenharmony_ci bnes op_ena 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci fmovemx nan,%fp0-%fp0 |load default nan 1228c2ecf20Sopenharmony_ci rts 1238c2ecf20Sopenharmony_ciop_ena: 1248c2ecf20Sopenharmony_ci st STORE_FLG(%a6) |do not corrupt destination 1258c2ecf20Sopenharmony_ci rts 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci| 1288c2ecf20Sopenharmony_ci| t_unfl --- UNFL exception 1298c2ecf20Sopenharmony_ci| 1308c2ecf20Sopenharmony_ci| This entry point is used by all routines requiring unfl, inex2, 1318c2ecf20Sopenharmony_ci| aunfl, and ainex to be set on exit. 1328c2ecf20Sopenharmony_ci| 1338c2ecf20Sopenharmony_ci| On entry, a0 points to the exceptional operand. The final exceptional 1348c2ecf20Sopenharmony_ci| operand is built in FP_SCR1 and only the sign from the original operand 1358c2ecf20Sopenharmony_ci| is used. 1368c2ecf20Sopenharmony_ci| 1378c2ecf20Sopenharmony_cit_unfl: 1388c2ecf20Sopenharmony_ci clrl FP_SCR1(%a6) |set exceptional operand to zero 1398c2ecf20Sopenharmony_ci clrl FP_SCR1+4(%a6) 1408c2ecf20Sopenharmony_ci clrl FP_SCR1+8(%a6) 1418c2ecf20Sopenharmony_ci tstb (%a0) |extract sign from caller's exop 1428c2ecf20Sopenharmony_ci bpls unfl_signok 1438c2ecf20Sopenharmony_ci bset #sign_bit,FP_SCR1(%a6) 1448c2ecf20Sopenharmony_ciunfl_signok: 1458c2ecf20Sopenharmony_ci leal FP_SCR1(%a6),%a0 1468c2ecf20Sopenharmony_ci orl #unfinx_mask,USER_FPSR(%a6) 1478c2ecf20Sopenharmony_ci| ;set UNFL, INEX2, AUNFL, AINEX 1488c2ecf20Sopenharmony_ciunfl_con: 1498c2ecf20Sopenharmony_ci btstb #unfl_bit,FPCR_ENABLE(%a6) 1508c2ecf20Sopenharmony_ci beqs unfl_dis 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciunfl_ena: 1538c2ecf20Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 1548c2ecf20Sopenharmony_ci bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 1558c2ecf20Sopenharmony_ci bsetb #sticky_bit,STICKY(%a6) |set sticky bit 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciunfl_dis: 1608c2ecf20Sopenharmony_ci bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 1638c2ecf20Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci bsr unf_sub |returns IEEE result at a0 1668c2ecf20Sopenharmony_ci| ;and sets FPSR_CC accordingly 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 1698c2ecf20Sopenharmony_ci beqs unfl_fin 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 1728c2ecf20Sopenharmony_ci bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciunfl_fin: 1758c2ecf20Sopenharmony_ci fmovemx (%a0),%fp0-%fp0 |store result in fp0 1768c2ecf20Sopenharmony_ci rts 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci| 1808c2ecf20Sopenharmony_ci| t_ovfl2 --- OVFL exception (without inex2 returned) 1818c2ecf20Sopenharmony_ci| 1828c2ecf20Sopenharmony_ci| This entry is used by scale to force catastrophic overflow. The 1838c2ecf20Sopenharmony_ci| ovfl, aovfl, and ainex bits are set, but not the inex2 bit. 1848c2ecf20Sopenharmony_ci| 1858c2ecf20Sopenharmony_cit_ovfl2: 1868c2ecf20Sopenharmony_ci orl #ovfl_inx_mask,USER_FPSR(%a6) 1878c2ecf20Sopenharmony_ci movel ETEMP(%a6),FP_SCR1(%a6) 1888c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),FP_SCR1+4(%a6) 1898c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),FP_SCR1+8(%a6) 1908c2ecf20Sopenharmony_ci| 1918c2ecf20Sopenharmony_ci| Check for single or double round precision. If single, check if 1928c2ecf20Sopenharmony_ci| the lower 40 bits of ETEMP are zero; if not, set inex2. If double, 1938c2ecf20Sopenharmony_ci| check if the lower 21 bits are zero; if not, set inex2. 1948c2ecf20Sopenharmony_ci| 1958c2ecf20Sopenharmony_ci moveb FPCR_MODE(%a6),%d0 1968c2ecf20Sopenharmony_ci andib #0xc0,%d0 1978c2ecf20Sopenharmony_ci beq t_work |if extended, finish ovfl processing 1988c2ecf20Sopenharmony_ci cmpib #0x40,%d0 |test for single 1998c2ecf20Sopenharmony_ci bnes t_dbl 2008c2ecf20Sopenharmony_cit_sgl: 2018c2ecf20Sopenharmony_ci tstb ETEMP_LO(%a6) 2028c2ecf20Sopenharmony_ci bnes t_setinx2 2038c2ecf20Sopenharmony_ci movel ETEMP_HI(%a6),%d0 2048c2ecf20Sopenharmony_ci andil #0xff,%d0 |look at only lower 8 bits 2058c2ecf20Sopenharmony_ci bnes t_setinx2 2068c2ecf20Sopenharmony_ci bra t_work 2078c2ecf20Sopenharmony_cit_dbl: 2088c2ecf20Sopenharmony_ci movel ETEMP_LO(%a6),%d0 2098c2ecf20Sopenharmony_ci andil #0x7ff,%d0 |look at only lower 11 bits 2108c2ecf20Sopenharmony_ci beq t_work 2118c2ecf20Sopenharmony_cit_setinx2: 2128c2ecf20Sopenharmony_ci orl #inex2_mask,USER_FPSR(%a6) 2138c2ecf20Sopenharmony_ci bras t_work 2148c2ecf20Sopenharmony_ci| 2158c2ecf20Sopenharmony_ci| t_ovfl --- OVFL exception 2168c2ecf20Sopenharmony_ci| 2178c2ecf20Sopenharmony_ci|** Note: the exc operand is returned in ETEMP. 2188c2ecf20Sopenharmony_ci| 2198c2ecf20Sopenharmony_cit_ovfl: 2208c2ecf20Sopenharmony_ci orl #ovfinx_mask,USER_FPSR(%a6) 2218c2ecf20Sopenharmony_cit_work: 2228c2ecf20Sopenharmony_ci btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled 2238c2ecf20Sopenharmony_ci beqs ovf_dis 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ciovf_ena: 2268c2ecf20Sopenharmony_ci clrl FP_SCR1(%a6) |set exceptional operand 2278c2ecf20Sopenharmony_ci clrl FP_SCR1+4(%a6) 2288c2ecf20Sopenharmony_ci clrl FP_SCR1+8(%a6) 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 2318c2ecf20Sopenharmony_ci bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15 2328c2ecf20Sopenharmony_ci bsetb #sticky_bit,STICKY(%a6) |set sticky bit 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 2358c2ecf20Sopenharmony_ci| ;fall through to disabled case 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci| For disabled overflow call 'ovf_r_k'. This routine loads the 2388c2ecf20Sopenharmony_ci| correct result based on the rounding precision, destination 2398c2ecf20Sopenharmony_ci| format, rounding mode and sign. 2408c2ecf20Sopenharmony_ci| 2418c2ecf20Sopenharmony_ciovf_dis: 2428c2ecf20Sopenharmony_ci bsr ovf_r_k |returns unsigned ETEMP_EX 2438c2ecf20Sopenharmony_ci| ;and sets FPSR_CC accordingly. 2448c2ecf20Sopenharmony_ci bfclr ETEMP_SGN(%a6){#0:#8} |fix sign 2458c2ecf20Sopenharmony_ci beqs ovf_pos 2468c2ecf20Sopenharmony_ci bsetb #sign_bit,ETEMP_EX(%a6) 2478c2ecf20Sopenharmony_ci bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign 2488c2ecf20Sopenharmony_ciovf_pos: 2498c2ecf20Sopenharmony_ci fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0 2508c2ecf20Sopenharmony_ci rts 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci| 2548c2ecf20Sopenharmony_ci| INEX2 exception 2558c2ecf20Sopenharmony_ci| 2568c2ecf20Sopenharmony_ci| The inex2 and ainex bits are set. 2578c2ecf20Sopenharmony_ci| 2588c2ecf20Sopenharmony_cit_inx2: 2598c2ecf20Sopenharmony_ci orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 2608c2ecf20Sopenharmony_ci rts 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci| 2638c2ecf20Sopenharmony_ci| Force Inex2 2648c2ecf20Sopenharmony_ci| 2658c2ecf20Sopenharmony_ci| This routine is called by the transcendental routines to force 2668c2ecf20Sopenharmony_ci| the inex2 exception bits set in the FPSR. If the underflow bit 2678c2ecf20Sopenharmony_ci| is set, but the underflow trap was not taken, the aunfl bit in 2688c2ecf20Sopenharmony_ci| the FPSR must be set. 2698c2ecf20Sopenharmony_ci| 2708c2ecf20Sopenharmony_cit_frcinx: 2718c2ecf20Sopenharmony_ci orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 2728c2ecf20Sopenharmony_ci btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set 2738c2ecf20Sopenharmony_ci beqs no_uacc1 |if clear, do not set aunfl 2748c2ecf20Sopenharmony_ci bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 2758c2ecf20Sopenharmony_cino_uacc1: 2768c2ecf20Sopenharmony_ci rts 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci| 2798c2ecf20Sopenharmony_ci| DST_NAN 2808c2ecf20Sopenharmony_ci| 2818c2ecf20Sopenharmony_ci| Determine if the destination nan is signalling or non-signalling, 2828c2ecf20Sopenharmony_ci| and set the FPSR bits accordingly. See the MC68040 User's Manual 2838c2ecf20Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS. 2848c2ecf20Sopenharmony_ci| 2858c2ecf20Sopenharmony_cidst_nan: 2868c2ecf20Sopenharmony_ci btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan 2878c2ecf20Sopenharmony_ci beqs dst_pos |if clr, it was positive 2888c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit 2898c2ecf20Sopenharmony_cidst_pos: 2908c2ecf20Sopenharmony_ci btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling 2918c2ecf20Sopenharmony_ci beqs dst_snan |branch if signalling 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 2948c2ecf20Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan 2958c2ecf20Sopenharmony_ci| 2968c2ecf20Sopenharmony_ci| Check the source nan. If it is signalling, snan will be reported. 2978c2ecf20Sopenharmony_ci| 2988c2ecf20Sopenharmony_ci moveb STAG(%a6),%d0 2998c2ecf20Sopenharmony_ci andib #0xe0,%d0 3008c2ecf20Sopenharmony_ci cmpib #0x60,%d0 3018c2ecf20Sopenharmony_ci bnes no_snan 3028c2ecf20Sopenharmony_ci btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 3038c2ecf20Sopenharmony_ci bnes no_snan 3048c2ecf20Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3058c2ecf20Sopenharmony_cino_snan: 3068c2ecf20Sopenharmony_ci rts 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cidst_snan: 3098c2ecf20Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 3108c2ecf20Sopenharmony_ci beqs dst_dis |branch if disabled 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci orb #nan_tag,DTAG(%a6) |set up dtag for nan 3138c2ecf20Sopenharmony_ci st STORE_FLG(%a6) |do not store a result 3148c2ecf20Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3158c2ecf20Sopenharmony_ci rts 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cidst_dis: 3188c2ecf20Sopenharmony_ci bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop 3198c2ecf20Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 3208c2ecf20Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |load non-sign. nan 3218c2ecf20Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3228c2ecf20Sopenharmony_ci rts 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci| 3258c2ecf20Sopenharmony_ci| SRC_NAN 3268c2ecf20Sopenharmony_ci| 3278c2ecf20Sopenharmony_ci| Determine if the source nan is signalling or non-signalling, 3288c2ecf20Sopenharmony_ci| and set the FPSR bits accordingly. See the MC68040 User's Manual 3298c2ecf20Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS. 3308c2ecf20Sopenharmony_ci| 3318c2ecf20Sopenharmony_cisrc_nan: 3328c2ecf20Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan 3338c2ecf20Sopenharmony_ci beqs src_pos |if clr, it was positive 3348c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit 3358c2ecf20Sopenharmony_cisrc_pos: 3368c2ecf20Sopenharmony_ci btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 3378c2ecf20Sopenharmony_ci beqs src_snan |branch if signalling 3388c2ecf20Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 3398c2ecf20Sopenharmony_ci fmovex ETEMP(%a6),%fp0 |return the non-signalling nan 3408c2ecf20Sopenharmony_ci rts 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cisrc_snan: 3438c2ecf20Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 3448c2ecf20Sopenharmony_ci beqs src_dis |branch if disabled 3458c2ecf20Sopenharmony_ci bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 3468c2ecf20Sopenharmony_ci orb #norm_tag,DTAG(%a6) |set up dtag for norm 3478c2ecf20Sopenharmony_ci orb #nan_tag,STAG(%a6) |set up stag for nan 3488c2ecf20Sopenharmony_ci st STORE_FLG(%a6) |do not store a result 3498c2ecf20Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3508c2ecf20Sopenharmony_ci rts 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cisrc_dis: 3538c2ecf20Sopenharmony_ci bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 3548c2ecf20Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 3558c2ecf20Sopenharmony_ci fmovex ETEMP(%a6),%fp0 |load non-sign. nan 3568c2ecf20Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3578c2ecf20Sopenharmony_ci rts 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci| 3608c2ecf20Sopenharmony_ci| For all functions that have a denormalized input and that f(x)=x, 3618c2ecf20Sopenharmony_ci| this is the entry point 3628c2ecf20Sopenharmony_ci| 3638c2ecf20Sopenharmony_cit_extdnrm: 3648c2ecf20Sopenharmony_ci orl #unfinx_mask,USER_FPSR(%a6) 3658c2ecf20Sopenharmony_ci| ;set UNFL, INEX2, AUNFL, AINEX 3668c2ecf20Sopenharmony_ci bras xdnrm_con 3678c2ecf20Sopenharmony_ci| 3688c2ecf20Sopenharmony_ci| Entry point for scale with extended denorm. The function does 3698c2ecf20Sopenharmony_ci| not set inex2, aunfl, or ainex. 3708c2ecf20Sopenharmony_ci| 3718c2ecf20Sopenharmony_cit_resdnrm: 3728c2ecf20Sopenharmony_ci orl #unfl_mask,USER_FPSR(%a6) 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cixdnrm_con: 3758c2ecf20Sopenharmony_ci btstb #unfl_bit,FPCR_ENABLE(%a6) 3768c2ecf20Sopenharmony_ci beqs xdnrm_dis 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci| 3798c2ecf20Sopenharmony_ci| If exceptions are enabled, the additional task of setting up WBTEMP 3808c2ecf20Sopenharmony_ci| is needed so that when the underflow exception handler is entered, 3818c2ecf20Sopenharmony_ci| the user perceives no difference between what the 040 provides vs. 3828c2ecf20Sopenharmony_ci| what the FPSP provides. 3838c2ecf20Sopenharmony_ci| 3848c2ecf20Sopenharmony_cixdnrm_ena: 3858c2ecf20Sopenharmony_ci movel %a0,-(%a7) 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci movel LOCAL_EX(%a0),FP_SCR1(%a6) 3888c2ecf20Sopenharmony_ci movel LOCAL_HI(%a0),FP_SCR1+4(%a6) 3898c2ecf20Sopenharmony_ci movel LOCAL_LO(%a0),FP_SCR1+8(%a6) 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci lea FP_SCR1(%a6),%a0 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 3948c2ecf20Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 3958c2ecf20Sopenharmony_ci tstw LOCAL_EX(%a0) |check if input is denorm 3968c2ecf20Sopenharmony_ci beqs xdnrm_dn |if so, skip nrm_set 3978c2ecf20Sopenharmony_ci bsr nrm_set |normalize the result (exponent 3988c2ecf20Sopenharmony_ci| ;will be negative 3998c2ecf20Sopenharmony_cixdnrm_dn: 4008c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign 4018c2ecf20Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 4028c2ecf20Sopenharmony_ci beqs xdep 4038c2ecf20Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 4048c2ecf20Sopenharmony_cixdep: 4058c2ecf20Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 4068c2ecf20Sopenharmony_ci bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 4078c2ecf20Sopenharmony_ci bclrb #sticky_bit,STICKY(%a6) |clear sticky bit 4088c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 4098c2ecf20Sopenharmony_ci movel (%a7)+,%a0 4108c2ecf20Sopenharmony_cixdnrm_dis: 4118c2ecf20Sopenharmony_ci bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 4128c2ecf20Sopenharmony_ci bnes not_ext |if not round extended, store 4138c2ecf20Sopenharmony_ci| ;IEEE defaults 4148c2ecf20Sopenharmony_ciis_ext: 4158c2ecf20Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 4168c2ecf20Sopenharmony_ci beqs xdnrm_store 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci bras xdnrm_store 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cinot_ext: 4238c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 4248c2ecf20Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 4258c2ecf20Sopenharmony_ci bsr unf_sub |returns IEEE result pointed by 4268c2ecf20Sopenharmony_ci| ;a0; sets FPSR_CC accordingly 4278c2ecf20Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4288c2ecf20Sopenharmony_ci beqs xdnrm_store 4298c2ecf20Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 4308c2ecf20Sopenharmony_cixdnrm_store: 4318c2ecf20Sopenharmony_ci fmovemx (%a0),%fp0-%fp0 |store result in fp0 4328c2ecf20Sopenharmony_ci rts 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci| 4358c2ecf20Sopenharmony_ci| This subroutine is used for dyadic operations that use an extended 4368c2ecf20Sopenharmony_ci| denorm within the kernel. The approach used is to capture the frame, 4378c2ecf20Sopenharmony_ci| fix/restore. 4388c2ecf20Sopenharmony_ci| 4398c2ecf20Sopenharmony_ci .global t_avoid_unsupp 4408c2ecf20Sopenharmony_cit_avoid_unsupp: 4418c2ecf20Sopenharmony_ci link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative 4428c2ecf20Sopenharmony_ci| ;offsets may be used 4438c2ecf20Sopenharmony_ci fsave -(%a7) 4448c2ecf20Sopenharmony_ci tstb 1(%a7) |check if idle, exit if so 4458c2ecf20Sopenharmony_ci beq idle_end 4468c2ecf20Sopenharmony_ci btstb #E1,E_BYTE(%a2) |check for an E1 exception if 4478c2ecf20Sopenharmony_ci| ;enabled, there is an unsupp 4488c2ecf20Sopenharmony_ci beq end_avun |else, exit 4498c2ecf20Sopenharmony_ci btstb #7,DTAG(%a2) |check for denorm destination 4508c2ecf20Sopenharmony_ci beqs src_den |else, must be a source denorm 4518c2ecf20Sopenharmony_ci| 4528c2ecf20Sopenharmony_ci| handle destination denorm 4538c2ecf20Sopenharmony_ci| 4548c2ecf20Sopenharmony_ci lea FPTEMP(%a2),%a0 4558c2ecf20Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 4568c2ecf20Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 4578c2ecf20Sopenharmony_ci bclrb #7,DTAG(%a2) |set DTAG to norm 4588c2ecf20Sopenharmony_ci bsr nrm_set |normalize result, exponent 4598c2ecf20Sopenharmony_ci| ;will become negative 4608c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 4618c2ecf20Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4628c2ecf20Sopenharmony_ci beqs ck_src_den |check if source is also denorm 4638c2ecf20Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 4648c2ecf20Sopenharmony_cick_src_den: 4658c2ecf20Sopenharmony_ci btstb #7,STAG(%a2) 4668c2ecf20Sopenharmony_ci beqs end_avun 4678c2ecf20Sopenharmony_cisrc_den: 4688c2ecf20Sopenharmony_ci lea ETEMP(%a2),%a0 4698c2ecf20Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 4708c2ecf20Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 4718c2ecf20Sopenharmony_ci bclrb #7,STAG(%a2) |set STAG to norm 4728c2ecf20Sopenharmony_ci bsr nrm_set |normalize result, exponent 4738c2ecf20Sopenharmony_ci| ;will become negative 4748c2ecf20Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 4758c2ecf20Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4768c2ecf20Sopenharmony_ci beqs den_com 4778c2ecf20Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 4788c2ecf20Sopenharmony_ciden_com: 4798c2ecf20Sopenharmony_ci moveb #0xfe,CU_SAVEPC(%a2) |set continue frame 4808c2ecf20Sopenharmony_ci clrw NMNEXC(%a2) |clear NMNEXC 4818c2ecf20Sopenharmony_ci bclrb #E1,E_BYTE(%a2) 4828c2ecf20Sopenharmony_ci| fmove.l %FPSR,FPSR_SHADOW(%a2) 4838c2ecf20Sopenharmony_ci| bset.b #SFLAG,E_BYTE(%a2) 4848c2ecf20Sopenharmony_ci| bset.b #XFLAG,T_BYTE(%a2) 4858c2ecf20Sopenharmony_ciend_avun: 4868c2ecf20Sopenharmony_ci frestore (%a7)+ 4878c2ecf20Sopenharmony_ci unlk %a2 4888c2ecf20Sopenharmony_ci rts 4898c2ecf20Sopenharmony_ciidle_end: 4908c2ecf20Sopenharmony_ci addl #4,%a7 4918c2ecf20Sopenharmony_ci unlk %a2 4928c2ecf20Sopenharmony_ci rts 4938c2ecf20Sopenharmony_ci |end 494