11da177e4SLinus Torvalds| 21da177e4SLinus Torvalds| kernel_ex.sa 3.3 12/19/90 31da177e4SLinus Torvalds| 41da177e4SLinus Torvalds| This file contains routines to force exception status in the 51da177e4SLinus Torvalds| fpu for exceptional cases detected or reported within the 61da177e4SLinus Torvalds| transcendental functions. Typically, the t_xx routine will 71da177e4SLinus Torvalds| set the appropriate bits in the USER_FPSR word on the stack. 81da177e4SLinus Torvalds| The bits are tested in gen_except.sa to determine if an exceptional 91da177e4SLinus Torvalds| situation needs to be created on return from the FPSP. 101da177e4SLinus Torvalds| 111da177e4SLinus Torvalds 121da177e4SLinus Torvalds| Copyright (C) Motorola, Inc. 1990 131da177e4SLinus Torvalds| All Rights Reserved 141da177e4SLinus Torvalds| 15e00d82d0SMatt Waddel| For details on the license for this file, please see the 16e00d82d0SMatt Waddel| file, README, in this same directory. 171da177e4SLinus Torvalds 181da177e4SLinus TorvaldsKERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds |section 8 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds#include "fpsp.h" 231da177e4SLinus Torvalds 241da177e4SLinus Torvaldsmns_inf: .long 0xffff0000,0x00000000,0x00000000 251da177e4SLinus Torvaldspls_inf: .long 0x7fff0000,0x00000000,0x00000000 261da177e4SLinus Torvaldsnan: .long 0x7fff0000,0xffffffff,0xffffffff 271da177e4SLinus Torvaldshuge: .long 0x7ffe0000,0xffffffff,0xffffffff 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds |xref ovf_r_k 301da177e4SLinus Torvalds |xref unf_sub 311da177e4SLinus Torvalds |xref nrm_set 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds .global t_dz 341da177e4SLinus Torvalds .global t_dz2 351da177e4SLinus Torvalds .global t_operr 361da177e4SLinus Torvalds .global t_unfl 371da177e4SLinus Torvalds .global t_ovfl 381da177e4SLinus Torvalds .global t_ovfl2 391da177e4SLinus Torvalds .global t_inx2 401da177e4SLinus Torvalds .global t_frcinx 411da177e4SLinus Torvalds .global t_extdnrm 421da177e4SLinus Torvalds .global t_resdnrm 431da177e4SLinus Torvalds .global dst_nan 441da177e4SLinus Torvalds .global src_nan 451da177e4SLinus Torvalds| 461da177e4SLinus Torvalds| DZ exception 471da177e4SLinus Torvalds| 481da177e4SLinus Torvalds| 491da177e4SLinus Torvalds| if dz trap disabled 501da177e4SLinus Torvalds| store properly signed inf (use sign of etemp) into fp0 511da177e4SLinus Torvalds| set FPSR exception status dz bit, condition code 521da177e4SLinus Torvalds| inf bit, and accrued dz bit 531da177e4SLinus Torvalds| return 541da177e4SLinus Torvalds| frestore the frame into the machine (done by unimp_hd) 551da177e4SLinus Torvalds| 561da177e4SLinus Torvalds| else dz trap enabled 571da177e4SLinus Torvalds| set exception status bit & accrued bits in FPSR 581da177e4SLinus Torvalds| set flag to disable sto_res from corrupting fp register 591da177e4SLinus Torvalds| return 601da177e4SLinus Torvalds| frestore the frame into the machine (done by unimp_hd) 611da177e4SLinus Torvalds| 621da177e4SLinus Torvalds| t_dz2 is used by monadic functions such as flogn (from do_func). 631da177e4SLinus Torvalds| t_dz is used by monadic functions such as satanh (from the 641da177e4SLinus Torvalds| transcendental function). 651da177e4SLinus Torvalds| 661da177e4SLinus Torvaldst_dz2: 671da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 681da177e4SLinus Torvalds fmovel #0,%FPSR |clr status bits (Z set) 691da177e4SLinus Torvalds btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 701da177e4SLinus Torvalds bnes dz_ena_end 711da177e4SLinus Torvalds bras m_inf |flogx always returns -inf 721da177e4SLinus Torvaldst_dz: 731da177e4SLinus Torvalds fmovel #0,%FPSR |clr status bits (Z set) 741da177e4SLinus Torvalds btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 751da177e4SLinus Torvalds bnes dz_ena 761da177e4SLinus Torvalds| 771da177e4SLinus Torvalds| dz disabled 781da177e4SLinus Torvalds| 791da177e4SLinus Torvalds btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 801da177e4SLinus Torvalds beqs p_inf |branch if pos sign 811da177e4SLinus Torvalds 821da177e4SLinus Torvaldsm_inf: 831da177e4SLinus Torvalds fmovemx mns_inf,%fp0-%fp0 |load -inf 841da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 851da177e4SLinus Torvalds bras set_fpsr 861da177e4SLinus Torvaldsp_inf: 871da177e4SLinus Torvalds fmovemx pls_inf,%fp0-%fp0 |load +inf 881da177e4SLinus Torvaldsset_fpsr: 891da177e4SLinus Torvalds orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 901da177e4SLinus Torvalds rts 911da177e4SLinus Torvalds| 921da177e4SLinus Torvalds| dz enabled 931da177e4SLinus Torvalds| 941da177e4SLinus Torvaldsdz_ena: 951da177e4SLinus Torvalds btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 961da177e4SLinus Torvalds beqs dz_ena_end 971da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 981da177e4SLinus Torvaldsdz_ena_end: 991da177e4SLinus Torvalds orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 1001da177e4SLinus Torvalds st STORE_FLG(%a6) 1011da177e4SLinus Torvalds rts 1021da177e4SLinus Torvalds| 1031da177e4SLinus Torvalds| OPERR exception 1041da177e4SLinus Torvalds| 1051da177e4SLinus Torvalds| if (operr trap disabled) 1061da177e4SLinus Torvalds| set FPSR exception status operr bit, condition code 1071da177e4SLinus Torvalds| nan bit; Store default NAN into fp0 1081da177e4SLinus Torvalds| frestore the frame into the machine (done by unimp_hd) 1091da177e4SLinus Torvalds| 1101da177e4SLinus Torvalds| else (operr trap enabled) 1111da177e4SLinus Torvalds| set FPSR exception status operr bit, accrued operr bit 1121da177e4SLinus Torvalds| set flag to disable sto_res from corrupting fp register 1131da177e4SLinus Torvalds| frestore the frame into the machine (done by unimp_hd) 1141da177e4SLinus Torvalds| 1151da177e4SLinus Torvaldst_operr: 1161da177e4SLinus Torvalds orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled 1191da177e4SLinus Torvalds bnes op_ena 1201da177e4SLinus Torvalds 1211da177e4SLinus Torvalds fmovemx nan,%fp0-%fp0 |load default nan 1221da177e4SLinus Torvalds rts 1231da177e4SLinus Torvaldsop_ena: 1241da177e4SLinus Torvalds st STORE_FLG(%a6) |do not corrupt destination 1251da177e4SLinus Torvalds rts 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds| 1281da177e4SLinus Torvalds| t_unfl --- UNFL exception 1291da177e4SLinus Torvalds| 1301da177e4SLinus Torvalds| This entry point is used by all routines requiring unfl, inex2, 1311da177e4SLinus Torvalds| aunfl, and ainex to be set on exit. 1321da177e4SLinus Torvalds| 1331da177e4SLinus Torvalds| On entry, a0 points to the exceptional operand. The final exceptional 1341da177e4SLinus Torvalds| operand is built in FP_SCR1 and only the sign from the original operand 1351da177e4SLinus Torvalds| is used. 1361da177e4SLinus Torvalds| 1371da177e4SLinus Torvaldst_unfl: 1381da177e4SLinus Torvalds clrl FP_SCR1(%a6) |set exceptional operand to zero 1391da177e4SLinus Torvalds clrl FP_SCR1+4(%a6) 1401da177e4SLinus Torvalds clrl FP_SCR1+8(%a6) 1411da177e4SLinus Torvalds tstb (%a0) |extract sign from caller's exop 1421da177e4SLinus Torvalds bpls unfl_signok 1431da177e4SLinus Torvalds bset #sign_bit,FP_SCR1(%a6) 1441da177e4SLinus Torvaldsunfl_signok: 1451da177e4SLinus Torvalds leal FP_SCR1(%a6),%a0 1461da177e4SLinus Torvalds orl #unfinx_mask,USER_FPSR(%a6) 1471da177e4SLinus Torvalds| ;set UNFL, INEX2, AUNFL, AINEX 1481da177e4SLinus Torvaldsunfl_con: 1491da177e4SLinus Torvalds btstb #unfl_bit,FPCR_ENABLE(%a6) 1501da177e4SLinus Torvalds beqs unfl_dis 1511da177e4SLinus Torvalds 1521da177e4SLinus Torvaldsunfl_ena: 1531da177e4SLinus Torvalds bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 1541da177e4SLinus Torvalds bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 1551da177e4SLinus Torvalds bsetb #sticky_bit,STICKY(%a6) |set sticky bit 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvaldsunfl_dis: 1601da177e4SLinus Torvalds bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) 1631da177e4SLinus Torvalds sne LOCAL_SGN(%a0) |convert to internal ext format 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds bsr unf_sub |returns IEEE result at a0 1661da177e4SLinus Torvalds| ;and sets FPSR_CC accordingly 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 1691da177e4SLinus Torvalds beqs unfl_fin 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 1721da177e4SLinus Torvalds bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvaldsunfl_fin: 1751da177e4SLinus Torvalds fmovemx (%a0),%fp0-%fp0 |store result in fp0 1761da177e4SLinus Torvalds rts 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds| 1801da177e4SLinus Torvalds| t_ovfl2 --- OVFL exception (without inex2 returned) 1811da177e4SLinus Torvalds| 1821da177e4SLinus Torvalds| This entry is used by scale to force catastrophic overflow. The 1831da177e4SLinus Torvalds| ovfl, aovfl, and ainex bits are set, but not the inex2 bit. 1841da177e4SLinus Torvalds| 1851da177e4SLinus Torvaldst_ovfl2: 1861da177e4SLinus Torvalds orl #ovfl_inx_mask,USER_FPSR(%a6) 1871da177e4SLinus Torvalds movel ETEMP(%a6),FP_SCR1(%a6) 1881da177e4SLinus Torvalds movel ETEMP_HI(%a6),FP_SCR1+4(%a6) 1891da177e4SLinus Torvalds movel ETEMP_LO(%a6),FP_SCR1+8(%a6) 1901da177e4SLinus Torvalds| 1911da177e4SLinus Torvalds| Check for single or double round precision. If single, check if 1921da177e4SLinus Torvalds| the lower 40 bits of ETEMP are zero; if not, set inex2. If double, 1931da177e4SLinus Torvalds| check if the lower 21 bits are zero; if not, set inex2. 1941da177e4SLinus Torvalds| 1951da177e4SLinus Torvalds moveb FPCR_MODE(%a6),%d0 1961da177e4SLinus Torvalds andib #0xc0,%d0 1971da177e4SLinus Torvalds beq t_work |if extended, finish ovfl processing 1981da177e4SLinus Torvalds cmpib #0x40,%d0 |test for single 1991da177e4SLinus Torvalds bnes t_dbl 2001da177e4SLinus Torvaldst_sgl: 2011da177e4SLinus Torvalds tstb ETEMP_LO(%a6) 2021da177e4SLinus Torvalds bnes t_setinx2 2031da177e4SLinus Torvalds movel ETEMP_HI(%a6),%d0 2041da177e4SLinus Torvalds andil #0xff,%d0 |look at only lower 8 bits 2051da177e4SLinus Torvalds bnes t_setinx2 2061da177e4SLinus Torvalds bra t_work 2071da177e4SLinus Torvaldst_dbl: 2081da177e4SLinus Torvalds movel ETEMP_LO(%a6),%d0 2091da177e4SLinus Torvalds andil #0x7ff,%d0 |look at only lower 11 bits 2101da177e4SLinus Torvalds beq t_work 2111da177e4SLinus Torvaldst_setinx2: 2121da177e4SLinus Torvalds orl #inex2_mask,USER_FPSR(%a6) 2131da177e4SLinus Torvalds bras t_work 2141da177e4SLinus Torvalds| 2151da177e4SLinus Torvalds| t_ovfl --- OVFL exception 2161da177e4SLinus Torvalds| 2171da177e4SLinus Torvalds|** Note: the exc operand is returned in ETEMP. 2181da177e4SLinus Torvalds| 2191da177e4SLinus Torvaldst_ovfl: 2201da177e4SLinus Torvalds orl #ovfinx_mask,USER_FPSR(%a6) 2211da177e4SLinus Torvaldst_work: 2221da177e4SLinus Torvalds btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled 2231da177e4SLinus Torvalds beqs ovf_dis 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvaldsovf_ena: 2261da177e4SLinus Torvalds clrl FP_SCR1(%a6) |set exceptional operand 2271da177e4SLinus Torvalds clrl FP_SCR1+4(%a6) 2281da177e4SLinus Torvalds clrl FP_SCR1+8(%a6) 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 2311da177e4SLinus Torvalds bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15 2321da177e4SLinus Torvalds bsetb #sticky_bit,STICKY(%a6) |set sticky bit 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 2351da177e4SLinus Torvalds| ;fall through to disabled case 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds| For disabled overflow call 'ovf_r_k'. This routine loads the 2381da177e4SLinus Torvalds| correct result based on the rounding precision, destination 2391da177e4SLinus Torvalds| format, rounding mode and sign. 2401da177e4SLinus Torvalds| 2411da177e4SLinus Torvaldsovf_dis: 2421da177e4SLinus Torvalds bsr ovf_r_k |returns unsigned ETEMP_EX 2431da177e4SLinus Torvalds| ;and sets FPSR_CC accordingly. 2441da177e4SLinus Torvalds bfclr ETEMP_SGN(%a6){#0:#8} |fix sign 2451da177e4SLinus Torvalds beqs ovf_pos 2461da177e4SLinus Torvalds bsetb #sign_bit,ETEMP_EX(%a6) 2471da177e4SLinus Torvalds bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign 2481da177e4SLinus Torvaldsovf_pos: 2491da177e4SLinus Torvalds fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0 2501da177e4SLinus Torvalds rts 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds| 2541da177e4SLinus Torvalds| INEX2 exception 2551da177e4SLinus Torvalds| 2561da177e4SLinus Torvalds| The inex2 and ainex bits are set. 2571da177e4SLinus Torvalds| 2581da177e4SLinus Torvaldst_inx2: 2591da177e4SLinus Torvalds orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 2601da177e4SLinus Torvalds rts 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds| 2631da177e4SLinus Torvalds| Force Inex2 2641da177e4SLinus Torvalds| 2651da177e4SLinus Torvalds| This routine is called by the transcendental routines to force 2661da177e4SLinus Torvalds| the inex2 exception bits set in the FPSR. If the underflow bit 2671da177e4SLinus Torvalds| is set, but the underflow trap was not taken, the aunfl bit in 2681da177e4SLinus Torvalds| the FPSR must be set. 2691da177e4SLinus Torvalds| 2701da177e4SLinus Torvaldst_frcinx: 2711da177e4SLinus Torvalds orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 2721da177e4SLinus Torvalds btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set 2731da177e4SLinus Torvalds beqs no_uacc1 |if clear, do not set aunfl 2741da177e4SLinus Torvalds bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 2751da177e4SLinus Torvaldsno_uacc1: 2761da177e4SLinus Torvalds rts 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds| 2791da177e4SLinus Torvalds| DST_NAN 2801da177e4SLinus Torvalds| 2811da177e4SLinus Torvalds| Determine if the destination nan is signalling or non-signalling, 2821da177e4SLinus Torvalds| and set the FPSR bits accordingly. See the MC68040 User's Manual 2831da177e4SLinus Torvalds| section 3.2.2.5 NOT-A-NUMBERS. 2841da177e4SLinus Torvalds| 2851da177e4SLinus Torvaldsdst_nan: 2861da177e4SLinus Torvalds btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan 2871da177e4SLinus Torvalds beqs dst_pos |if clr, it was positive 2881da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set N bit 2891da177e4SLinus Torvaldsdst_pos: 2901da177e4SLinus Torvalds btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling 2911da177e4SLinus Torvalds beqs dst_snan |branch if signalling 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds fmovel %d1,%fpcr |restore user's rmode/prec 2941da177e4SLinus Torvalds fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan 2951da177e4SLinus Torvalds| 2961da177e4SLinus Torvalds| Check the source nan. If it is signalling, snan will be reported. 2971da177e4SLinus Torvalds| 2981da177e4SLinus Torvalds moveb STAG(%a6),%d0 2991da177e4SLinus Torvalds andib #0xe0,%d0 3001da177e4SLinus Torvalds cmpib #0x60,%d0 3011da177e4SLinus Torvalds bnes no_snan 3021da177e4SLinus Torvalds btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 3031da177e4SLinus Torvalds bnes no_snan 3041da177e4SLinus Torvalds orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3051da177e4SLinus Torvaldsno_snan: 3061da177e4SLinus Torvalds rts 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvaldsdst_snan: 3091da177e4SLinus Torvalds btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 3101da177e4SLinus Torvalds beqs dst_dis |branch if disabled 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds orb #nan_tag,DTAG(%a6) |set up dtag for nan 3131da177e4SLinus Torvalds st STORE_FLG(%a6) |do not store a result 3141da177e4SLinus Torvalds orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3151da177e4SLinus Torvalds rts 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvaldsdst_dis: 3181da177e4SLinus Torvalds bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop 3191da177e4SLinus Torvalds fmovel %d1,%fpcr |restore user's rmode/prec 3201da177e4SLinus Torvalds fmovex FPTEMP(%a6),%fp0 |load non-sign. nan 3211da177e4SLinus Torvalds orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3221da177e4SLinus Torvalds rts 3231da177e4SLinus Torvalds 3241da177e4SLinus Torvalds| 3251da177e4SLinus Torvalds| SRC_NAN 3261da177e4SLinus Torvalds| 3271da177e4SLinus Torvalds| Determine if the source nan is signalling or non-signalling, 3281da177e4SLinus Torvalds| and set the FPSR bits accordingly. See the MC68040 User's Manual 3291da177e4SLinus Torvalds| section 3.2.2.5 NOT-A-NUMBERS. 3301da177e4SLinus Torvalds| 3311da177e4SLinus Torvaldssrc_nan: 3321da177e4SLinus Torvalds btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan 3331da177e4SLinus Torvalds beqs src_pos |if clr, it was positive 3341da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set N bit 3351da177e4SLinus Torvaldssrc_pos: 3361da177e4SLinus Torvalds btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 3371da177e4SLinus Torvalds beqs src_snan |branch if signalling 3381da177e4SLinus Torvalds fmovel %d1,%fpcr |restore user's rmode/prec 3391da177e4SLinus Torvalds fmovex ETEMP(%a6),%fp0 |return the non-signalling nan 3401da177e4SLinus Torvalds rts 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvaldssrc_snan: 3431da177e4SLinus Torvalds btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 3441da177e4SLinus Torvalds beqs src_dis |branch if disabled 3451da177e4SLinus Torvalds bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 3461da177e4SLinus Torvalds orb #norm_tag,DTAG(%a6) |set up dtag for norm 3471da177e4SLinus Torvalds orb #nan_tag,STAG(%a6) |set up stag for nan 3481da177e4SLinus Torvalds st STORE_FLG(%a6) |do not store a result 3491da177e4SLinus Torvalds orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3501da177e4SLinus Torvalds rts 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvaldssrc_dis: 3531da177e4SLinus Torvalds bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 3541da177e4SLinus Torvalds fmovel %d1,%fpcr |restore user's rmode/prec 3551da177e4SLinus Torvalds fmovex ETEMP(%a6),%fp0 |load non-sign. nan 3561da177e4SLinus Torvalds orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 3571da177e4SLinus Torvalds rts 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds| 3601da177e4SLinus Torvalds| For all functions that have a denormalized input and that f(x)=x, 3611da177e4SLinus Torvalds| this is the entry point 3621da177e4SLinus Torvalds| 3631da177e4SLinus Torvaldst_extdnrm: 3641da177e4SLinus Torvalds orl #unfinx_mask,USER_FPSR(%a6) 3651da177e4SLinus Torvalds| ;set UNFL, INEX2, AUNFL, AINEX 3661da177e4SLinus Torvalds bras xdnrm_con 3671da177e4SLinus Torvalds| 3681da177e4SLinus Torvalds| Entry point for scale with extended denorm. The function does 3691da177e4SLinus Torvalds| not set inex2, aunfl, or ainex. 3701da177e4SLinus Torvalds| 3711da177e4SLinus Torvaldst_resdnrm: 3721da177e4SLinus Torvalds orl #unfl_mask,USER_FPSR(%a6) 3731da177e4SLinus Torvalds 3741da177e4SLinus Torvaldsxdnrm_con: 3751da177e4SLinus Torvalds btstb #unfl_bit,FPCR_ENABLE(%a6) 3761da177e4SLinus Torvalds beqs xdnrm_dis 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds| 3791da177e4SLinus Torvalds| If exceptions are enabled, the additional task of setting up WBTEMP 3801da177e4SLinus Torvalds| is needed so that when the underflow exception handler is entered, 3811da177e4SLinus Torvalds| the user perceives no difference between what the 040 provides vs. 3821da177e4SLinus Torvalds| what the FPSP provides. 3831da177e4SLinus Torvalds| 3841da177e4SLinus Torvaldsxdnrm_ena: 3851da177e4SLinus Torvalds movel %a0,-(%a7) 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds movel LOCAL_EX(%a0),FP_SCR1(%a6) 3881da177e4SLinus Torvalds movel LOCAL_HI(%a0),FP_SCR1+4(%a6) 3891da177e4SLinus Torvalds movel LOCAL_LO(%a0),FP_SCR1+8(%a6) 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds lea FP_SCR1(%a6),%a0 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) 3941da177e4SLinus Torvalds sne LOCAL_SGN(%a0) |convert to internal ext format 3951da177e4SLinus Torvalds tstw LOCAL_EX(%a0) |check if input is denorm 3961da177e4SLinus Torvalds beqs xdnrm_dn |if so, skip nrm_set 3971da177e4SLinus Torvalds bsr nrm_set |normalize the result (exponent 3981da177e4SLinus Torvalds| ;will be negative 3991da177e4SLinus Torvaldsxdnrm_dn: 4001da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign 4011da177e4SLinus Torvalds bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 4021da177e4SLinus Torvalds beqs xdep 4031da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 4041da177e4SLinus Torvaldsxdep: 4051da177e4SLinus Torvalds bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 4061da177e4SLinus Torvalds bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 4071da177e4SLinus Torvalds bclrb #sticky_bit,STICKY(%a6) |clear sticky bit 4081da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a6) 4091da177e4SLinus Torvalds movel (%a7)+,%a0 4101da177e4SLinus Torvaldsxdnrm_dis: 4111da177e4SLinus Torvalds bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 4121da177e4SLinus Torvalds bnes not_ext |if not round extended, store 4131da177e4SLinus Torvalds| ;IEEE defaults 4141da177e4SLinus Torvaldsis_ext: 4151da177e4SLinus Torvalds btstb #sign_bit,LOCAL_EX(%a0) 4161da177e4SLinus Torvalds beqs xdnrm_store 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds bras xdnrm_store 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvaldsnot_ext: 4231da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) 4241da177e4SLinus Torvalds sne LOCAL_SGN(%a0) |convert to internal ext format 4251da177e4SLinus Torvalds bsr unf_sub |returns IEEE result pointed by 4261da177e4SLinus Torvalds| ;a0; sets FPSR_CC accordingly 4271da177e4SLinus Torvalds bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4281da177e4SLinus Torvalds beqs xdnrm_store 4291da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 4301da177e4SLinus Torvaldsxdnrm_store: 4311da177e4SLinus Torvalds fmovemx (%a0),%fp0-%fp0 |store result in fp0 4321da177e4SLinus Torvalds rts 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds| 4351da177e4SLinus Torvalds| This subroutine is used for dyadic operations that use an extended 4361da177e4SLinus Torvalds| denorm within the kernel. The approach used is to capture the frame, 4371da177e4SLinus Torvalds| fix/restore. 4381da177e4SLinus Torvalds| 4391da177e4SLinus Torvalds .global t_avoid_unsupp 4401da177e4SLinus Torvaldst_avoid_unsupp: 4411da177e4SLinus Torvalds link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative 4421da177e4SLinus Torvalds| ;offsets may be used 4431da177e4SLinus Torvalds fsave -(%a7) 4441da177e4SLinus Torvalds tstb 1(%a7) |check if idle, exit if so 4451da177e4SLinus Torvalds beq idle_end 4461da177e4SLinus Torvalds btstb #E1,E_BYTE(%a2) |check for an E1 exception if 4471da177e4SLinus Torvalds| ;enabled, there is an unsupp 4481da177e4SLinus Torvalds beq end_avun |else, exit 4491da177e4SLinus Torvalds btstb #7,DTAG(%a2) |check for denorm destination 4501da177e4SLinus Torvalds beqs src_den |else, must be a source denorm 4511da177e4SLinus Torvalds| 4521da177e4SLinus Torvalds| handle destination denorm 4531da177e4SLinus Torvalds| 4541da177e4SLinus Torvalds lea FPTEMP(%a2),%a0 4551da177e4SLinus Torvalds btstb #sign_bit,LOCAL_EX(%a0) 4561da177e4SLinus Torvalds sne LOCAL_SGN(%a0) |convert to internal ext format 4571da177e4SLinus Torvalds bclrb #7,DTAG(%a2) |set DTAG to norm 4581da177e4SLinus Torvalds bsr nrm_set |normalize result, exponent 4591da177e4SLinus Torvalds| ;will become negative 4601da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 4611da177e4SLinus Torvalds bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4621da177e4SLinus Torvalds beqs ck_src_den |check if source is also denorm 4631da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 4641da177e4SLinus Torvaldsck_src_den: 4651da177e4SLinus Torvalds btstb #7,STAG(%a2) 4661da177e4SLinus Torvalds beqs end_avun 4671da177e4SLinus Torvaldssrc_den: 4681da177e4SLinus Torvalds lea ETEMP(%a2),%a0 4691da177e4SLinus Torvalds btstb #sign_bit,LOCAL_EX(%a0) 4701da177e4SLinus Torvalds sne LOCAL_SGN(%a0) |convert to internal ext format 4711da177e4SLinus Torvalds bclrb #7,STAG(%a2) |set STAG to norm 4721da177e4SLinus Torvalds bsr nrm_set |normalize result, exponent 4731da177e4SLinus Torvalds| ;will become negative 4741da177e4SLinus Torvalds bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 4751da177e4SLinus Torvalds bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 4761da177e4SLinus Torvalds beqs den_com 4771da177e4SLinus Torvalds bsetb #sign_bit,LOCAL_EX(%a0) 4781da177e4SLinus Torvaldsden_com: 4791da177e4SLinus Torvalds moveb #0xfe,CU_SAVEPC(%a2) |set continue frame 4801da177e4SLinus Torvalds clrw NMNEXC(%a2) |clear NMNEXC 4811da177e4SLinus Torvalds bclrb #E1,E_BYTE(%a2) 4821da177e4SLinus Torvalds| fmove.l %FPSR,FPSR_SHADOW(%a2) 4831da177e4SLinus Torvalds| bset.b #SFLAG,E_BYTE(%a2) 4841da177e4SLinus Torvalds| bset.b #XFLAG,T_BYTE(%a2) 4851da177e4SLinus Torvaldsend_avun: 4861da177e4SLinus Torvalds frestore (%a7)+ 4871da177e4SLinus Torvalds unlk %a2 4881da177e4SLinus Torvalds rts 4891da177e4SLinus Torvaldsidle_end: 4901da177e4SLinus Torvalds addl #4,%a7 4911da177e4SLinus Torvalds unlk %a2 4921da177e4SLinus Torvalds rts 4931da177e4SLinus Torvalds |end 494