162306a36Sopenharmony_ci| 262306a36Sopenharmony_ci| kernel_ex.sa 3.3 12/19/90 362306a36Sopenharmony_ci| 462306a36Sopenharmony_ci| This file contains routines to force exception status in the 562306a36Sopenharmony_ci| fpu for exceptional cases detected or reported within the 662306a36Sopenharmony_ci| transcendental functions. Typically, the t_xx routine will 762306a36Sopenharmony_ci| set the appropriate bits in the USER_FPSR word on the stack. 862306a36Sopenharmony_ci| The bits are tested in gen_except.sa to determine if an exceptional 962306a36Sopenharmony_ci| situation needs to be created on return from the FPSP. 1062306a36Sopenharmony_ci| 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci| Copyright (C) Motorola, Inc. 1990 1362306a36Sopenharmony_ci| All Rights Reserved 1462306a36Sopenharmony_ci| 1562306a36Sopenharmony_ci| For details on the license for this file, please see the 1662306a36Sopenharmony_ci| file, README, in this same directory. 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciKERNEL_EX: |idnt 2,1 | Motorola 040 Floating Point Software Package 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci |section 8 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "fpsp.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cimns_inf: .long 0xffff0000,0x00000000,0x00000000 2562306a36Sopenharmony_cipls_inf: .long 0x7fff0000,0x00000000,0x00000000 2662306a36Sopenharmony_cinan: .long 0x7fff0000,0xffffffff,0xffffffff 2762306a36Sopenharmony_cihuge: .long 0x7ffe0000,0xffffffff,0xffffffff 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci |xref ovf_r_k 3062306a36Sopenharmony_ci |xref unf_sub 3162306a36Sopenharmony_ci |xref nrm_set 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci .global t_dz 3462306a36Sopenharmony_ci .global t_dz2 3562306a36Sopenharmony_ci .global t_operr 3662306a36Sopenharmony_ci .global t_unfl 3762306a36Sopenharmony_ci .global t_ovfl 3862306a36Sopenharmony_ci .global t_ovfl2 3962306a36Sopenharmony_ci .global t_inx2 4062306a36Sopenharmony_ci .global t_frcinx 4162306a36Sopenharmony_ci .global t_extdnrm 4262306a36Sopenharmony_ci .global t_resdnrm 4362306a36Sopenharmony_ci .global dst_nan 4462306a36Sopenharmony_ci .global src_nan 4562306a36Sopenharmony_ci| 4662306a36Sopenharmony_ci| DZ exception 4762306a36Sopenharmony_ci| 4862306a36Sopenharmony_ci| 4962306a36Sopenharmony_ci| if dz trap disabled 5062306a36Sopenharmony_ci| store properly signed inf (use sign of etemp) into fp0 5162306a36Sopenharmony_ci| set FPSR exception status dz bit, condition code 5262306a36Sopenharmony_ci| inf bit, and accrued dz bit 5362306a36Sopenharmony_ci| return 5462306a36Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 5562306a36Sopenharmony_ci| 5662306a36Sopenharmony_ci| else dz trap enabled 5762306a36Sopenharmony_ci| set exception status bit & accrued bits in FPSR 5862306a36Sopenharmony_ci| set flag to disable sto_res from corrupting fp register 5962306a36Sopenharmony_ci| return 6062306a36Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 6162306a36Sopenharmony_ci| 6262306a36Sopenharmony_ci| t_dz2 is used by monadic functions such as flogn (from do_func). 6362306a36Sopenharmony_ci| t_dz is used by monadic functions such as satanh (from the 6462306a36Sopenharmony_ci| transcendental function). 6562306a36Sopenharmony_ci| 6662306a36Sopenharmony_cit_dz2: 6762306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 6862306a36Sopenharmony_ci fmovel #0,%FPSR |clr status bits (Z set) 6962306a36Sopenharmony_ci btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 7062306a36Sopenharmony_ci bnes dz_ena_end 7162306a36Sopenharmony_ci bras m_inf |flogx always returns -inf 7262306a36Sopenharmony_cit_dz: 7362306a36Sopenharmony_ci fmovel #0,%FPSR |clr status bits (Z set) 7462306a36Sopenharmony_ci btstb #dz_bit,FPCR_ENABLE(%a6) |test FPCR for dz exc enabled 7562306a36Sopenharmony_ci bnes dz_ena 7662306a36Sopenharmony_ci| 7762306a36Sopenharmony_ci| dz disabled 7862306a36Sopenharmony_ci| 7962306a36Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 8062306a36Sopenharmony_ci beqs p_inf |branch if pos sign 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cim_inf: 8362306a36Sopenharmony_ci fmovemx mns_inf,%fp0-%fp0 |load -inf 8462306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 8562306a36Sopenharmony_ci bras set_fpsr 8662306a36Sopenharmony_cip_inf: 8762306a36Sopenharmony_ci fmovemx pls_inf,%fp0-%fp0 |load +inf 8862306a36Sopenharmony_ciset_fpsr: 8962306a36Sopenharmony_ci orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 9062306a36Sopenharmony_ci rts 9162306a36Sopenharmony_ci| 9262306a36Sopenharmony_ci| dz enabled 9362306a36Sopenharmony_ci| 9462306a36Sopenharmony_cidz_ena: 9562306a36Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |check sign for neg or pos 9662306a36Sopenharmony_ci beqs dz_ena_end 9762306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set neg bit in FPSR 9862306a36Sopenharmony_cidz_ena_end: 9962306a36Sopenharmony_ci orl #dzinf_mask,USER_FPSR(%a6) |set I,DZ,ADZ 10062306a36Sopenharmony_ci st STORE_FLG(%a6) 10162306a36Sopenharmony_ci rts 10262306a36Sopenharmony_ci| 10362306a36Sopenharmony_ci| OPERR exception 10462306a36Sopenharmony_ci| 10562306a36Sopenharmony_ci| if (operr trap disabled) 10662306a36Sopenharmony_ci| set FPSR exception status operr bit, condition code 10762306a36Sopenharmony_ci| nan bit; Store default NAN into fp0 10862306a36Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 10962306a36Sopenharmony_ci| 11062306a36Sopenharmony_ci| else (operr trap enabled) 11162306a36Sopenharmony_ci| set FPSR exception status operr bit, accrued operr bit 11262306a36Sopenharmony_ci| set flag to disable sto_res from corrupting fp register 11362306a36Sopenharmony_ci| frestore the frame into the machine (done by unimp_hd) 11462306a36Sopenharmony_ci| 11562306a36Sopenharmony_cit_operr: 11662306a36Sopenharmony_ci orl #opnan_mask,USER_FPSR(%a6) |set NaN, OPERR, AIOP 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci btstb #operr_bit,FPCR_ENABLE(%a6) |test FPCR for operr enabled 11962306a36Sopenharmony_ci bnes op_ena 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci fmovemx nan,%fp0-%fp0 |load default nan 12262306a36Sopenharmony_ci rts 12362306a36Sopenharmony_ciop_ena: 12462306a36Sopenharmony_ci st STORE_FLG(%a6) |do not corrupt destination 12562306a36Sopenharmony_ci rts 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci| 12862306a36Sopenharmony_ci| t_unfl --- UNFL exception 12962306a36Sopenharmony_ci| 13062306a36Sopenharmony_ci| This entry point is used by all routines requiring unfl, inex2, 13162306a36Sopenharmony_ci| aunfl, and ainex to be set on exit. 13262306a36Sopenharmony_ci| 13362306a36Sopenharmony_ci| On entry, a0 points to the exceptional operand. The final exceptional 13462306a36Sopenharmony_ci| operand is built in FP_SCR1 and only the sign from the original operand 13562306a36Sopenharmony_ci| is used. 13662306a36Sopenharmony_ci| 13762306a36Sopenharmony_cit_unfl: 13862306a36Sopenharmony_ci clrl FP_SCR1(%a6) |set exceptional operand to zero 13962306a36Sopenharmony_ci clrl FP_SCR1+4(%a6) 14062306a36Sopenharmony_ci clrl FP_SCR1+8(%a6) 14162306a36Sopenharmony_ci tstb (%a0) |extract sign from caller's exop 14262306a36Sopenharmony_ci bpls unfl_signok 14362306a36Sopenharmony_ci bset #sign_bit,FP_SCR1(%a6) 14462306a36Sopenharmony_ciunfl_signok: 14562306a36Sopenharmony_ci leal FP_SCR1(%a6),%a0 14662306a36Sopenharmony_ci orl #unfinx_mask,USER_FPSR(%a6) 14762306a36Sopenharmony_ci| ;set UNFL, INEX2, AUNFL, AINEX 14862306a36Sopenharmony_ciunfl_con: 14962306a36Sopenharmony_ci btstb #unfl_bit,FPCR_ENABLE(%a6) 15062306a36Sopenharmony_ci beqs unfl_dis 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ciunfl_ena: 15362306a36Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 15462306a36Sopenharmony_ci bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 15562306a36Sopenharmony_ci bsetb #sticky_bit,STICKY(%a6) |set sticky bit 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciunfl_dis: 16062306a36Sopenharmony_ci bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 16362306a36Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci bsr unf_sub |returns IEEE result at a0 16662306a36Sopenharmony_ci| ;and sets FPSR_CC accordingly 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 16962306a36Sopenharmony_ci beqs unfl_fin 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 17262306a36Sopenharmony_ci bsetb #sign_bit,FP_SCR1(%a6) |set sign bit of exc operand 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ciunfl_fin: 17562306a36Sopenharmony_ci fmovemx (%a0),%fp0-%fp0 |store result in fp0 17662306a36Sopenharmony_ci rts 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci| 18062306a36Sopenharmony_ci| t_ovfl2 --- OVFL exception (without inex2 returned) 18162306a36Sopenharmony_ci| 18262306a36Sopenharmony_ci| This entry is used by scale to force catastrophic overflow. The 18362306a36Sopenharmony_ci| ovfl, aovfl, and ainex bits are set, but not the inex2 bit. 18462306a36Sopenharmony_ci| 18562306a36Sopenharmony_cit_ovfl2: 18662306a36Sopenharmony_ci orl #ovfl_inx_mask,USER_FPSR(%a6) 18762306a36Sopenharmony_ci movel ETEMP(%a6),FP_SCR1(%a6) 18862306a36Sopenharmony_ci movel ETEMP_HI(%a6),FP_SCR1+4(%a6) 18962306a36Sopenharmony_ci movel ETEMP_LO(%a6),FP_SCR1+8(%a6) 19062306a36Sopenharmony_ci| 19162306a36Sopenharmony_ci| Check for single or double round precision. If single, check if 19262306a36Sopenharmony_ci| the lower 40 bits of ETEMP are zero; if not, set inex2. If double, 19362306a36Sopenharmony_ci| check if the lower 21 bits are zero; if not, set inex2. 19462306a36Sopenharmony_ci| 19562306a36Sopenharmony_ci moveb FPCR_MODE(%a6),%d0 19662306a36Sopenharmony_ci andib #0xc0,%d0 19762306a36Sopenharmony_ci beq t_work |if extended, finish ovfl processing 19862306a36Sopenharmony_ci cmpib #0x40,%d0 |test for single 19962306a36Sopenharmony_ci bnes t_dbl 20062306a36Sopenharmony_cit_sgl: 20162306a36Sopenharmony_ci tstb ETEMP_LO(%a6) 20262306a36Sopenharmony_ci bnes t_setinx2 20362306a36Sopenharmony_ci movel ETEMP_HI(%a6),%d0 20462306a36Sopenharmony_ci andil #0xff,%d0 |look at only lower 8 bits 20562306a36Sopenharmony_ci bnes t_setinx2 20662306a36Sopenharmony_ci bra t_work 20762306a36Sopenharmony_cit_dbl: 20862306a36Sopenharmony_ci movel ETEMP_LO(%a6),%d0 20962306a36Sopenharmony_ci andil #0x7ff,%d0 |look at only lower 11 bits 21062306a36Sopenharmony_ci beq t_work 21162306a36Sopenharmony_cit_setinx2: 21262306a36Sopenharmony_ci orl #inex2_mask,USER_FPSR(%a6) 21362306a36Sopenharmony_ci bras t_work 21462306a36Sopenharmony_ci| 21562306a36Sopenharmony_ci| t_ovfl --- OVFL exception 21662306a36Sopenharmony_ci| 21762306a36Sopenharmony_ci|** Note: the exc operand is returned in ETEMP. 21862306a36Sopenharmony_ci| 21962306a36Sopenharmony_cit_ovfl: 22062306a36Sopenharmony_ci orl #ovfinx_mask,USER_FPSR(%a6) 22162306a36Sopenharmony_cit_work: 22262306a36Sopenharmony_ci btstb #ovfl_bit,FPCR_ENABLE(%a6) |test FPCR for ovfl enabled 22362306a36Sopenharmony_ci beqs ovf_dis 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ciovf_ena: 22662306a36Sopenharmony_ci clrl FP_SCR1(%a6) |set exceptional operand 22762306a36Sopenharmony_ci clrl FP_SCR1+4(%a6) 22862306a36Sopenharmony_ci clrl FP_SCR1+8(%a6) 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 23162306a36Sopenharmony_ci bclrb #wbtemp15_bit,WB_BYTE(%a6) |clear wbtemp15 23262306a36Sopenharmony_ci bsetb #sticky_bit,STICKY(%a6) |set sticky bit 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 23562306a36Sopenharmony_ci| ;fall through to disabled case 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci| For disabled overflow call 'ovf_r_k'. This routine loads the 23862306a36Sopenharmony_ci| correct result based on the rounding precision, destination 23962306a36Sopenharmony_ci| format, rounding mode and sign. 24062306a36Sopenharmony_ci| 24162306a36Sopenharmony_ciovf_dis: 24262306a36Sopenharmony_ci bsr ovf_r_k |returns unsigned ETEMP_EX 24362306a36Sopenharmony_ci| ;and sets FPSR_CC accordingly. 24462306a36Sopenharmony_ci bfclr ETEMP_SGN(%a6){#0:#8} |fix sign 24562306a36Sopenharmony_ci beqs ovf_pos 24662306a36Sopenharmony_ci bsetb #sign_bit,ETEMP_EX(%a6) 24762306a36Sopenharmony_ci bsetb #sign_bit,FP_SCR1(%a6) |set exceptional operand sign 24862306a36Sopenharmony_ciovf_pos: 24962306a36Sopenharmony_ci fmovemx ETEMP(%a6),%fp0-%fp0 |move the result to fp0 25062306a36Sopenharmony_ci rts 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci| 25462306a36Sopenharmony_ci| INEX2 exception 25562306a36Sopenharmony_ci| 25662306a36Sopenharmony_ci| The inex2 and ainex bits are set. 25762306a36Sopenharmony_ci| 25862306a36Sopenharmony_cit_inx2: 25962306a36Sopenharmony_ci orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 26062306a36Sopenharmony_ci rts 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci| 26362306a36Sopenharmony_ci| Force Inex2 26462306a36Sopenharmony_ci| 26562306a36Sopenharmony_ci| This routine is called by the transcendental routines to force 26662306a36Sopenharmony_ci| the inex2 exception bits set in the FPSR. If the underflow bit 26762306a36Sopenharmony_ci| is set, but the underflow trap was not taken, the aunfl bit in 26862306a36Sopenharmony_ci| the FPSR must be set. 26962306a36Sopenharmony_ci| 27062306a36Sopenharmony_cit_frcinx: 27162306a36Sopenharmony_ci orl #inx2a_mask,USER_FPSR(%a6) |set INEX2, AINEX 27262306a36Sopenharmony_ci btstb #unfl_bit,FPSR_EXCEPT(%a6) |test for unfl bit set 27362306a36Sopenharmony_ci beqs no_uacc1 |if clear, do not set aunfl 27462306a36Sopenharmony_ci bsetb #aunfl_bit,FPSR_AEXCEPT(%a6) 27562306a36Sopenharmony_cino_uacc1: 27662306a36Sopenharmony_ci rts 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci| 27962306a36Sopenharmony_ci| DST_NAN 28062306a36Sopenharmony_ci| 28162306a36Sopenharmony_ci| Determine if the destination nan is signalling or non-signalling, 28262306a36Sopenharmony_ci| and set the FPSR bits accordingly. See the MC68040 User's Manual 28362306a36Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS. 28462306a36Sopenharmony_ci| 28562306a36Sopenharmony_cidst_nan: 28662306a36Sopenharmony_ci btstb #sign_bit,FPTEMP_EX(%a6) |test sign of nan 28762306a36Sopenharmony_ci beqs dst_pos |if clr, it was positive 28862306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit 28962306a36Sopenharmony_cidst_pos: 29062306a36Sopenharmony_ci btstb #signan_bit,FPTEMP_HI(%a6) |check if signalling 29162306a36Sopenharmony_ci beqs dst_snan |branch if signalling 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 29462306a36Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |return the non-signalling nan 29562306a36Sopenharmony_ci| 29662306a36Sopenharmony_ci| Check the source nan. If it is signalling, snan will be reported. 29762306a36Sopenharmony_ci| 29862306a36Sopenharmony_ci moveb STAG(%a6),%d0 29962306a36Sopenharmony_ci andib #0xe0,%d0 30062306a36Sopenharmony_ci cmpib #0x60,%d0 30162306a36Sopenharmony_ci bnes no_snan 30262306a36Sopenharmony_ci btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 30362306a36Sopenharmony_ci bnes no_snan 30462306a36Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 30562306a36Sopenharmony_cino_snan: 30662306a36Sopenharmony_ci rts 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cidst_snan: 30962306a36Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 31062306a36Sopenharmony_ci beqs dst_dis |branch if disabled 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci orb #nan_tag,DTAG(%a6) |set up dtag for nan 31362306a36Sopenharmony_ci st STORE_FLG(%a6) |do not store a result 31462306a36Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 31562306a36Sopenharmony_ci rts 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cidst_dis: 31862306a36Sopenharmony_ci bsetb #signan_bit,FPTEMP_HI(%a6) |set SNAN bit in sop 31962306a36Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 32062306a36Sopenharmony_ci fmovex FPTEMP(%a6),%fp0 |load non-sign. nan 32162306a36Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 32262306a36Sopenharmony_ci rts 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci| 32562306a36Sopenharmony_ci| SRC_NAN 32662306a36Sopenharmony_ci| 32762306a36Sopenharmony_ci| Determine if the source nan is signalling or non-signalling, 32862306a36Sopenharmony_ci| and set the FPSR bits accordingly. See the MC68040 User's Manual 32962306a36Sopenharmony_ci| section 3.2.2.5 NOT-A-NUMBERS. 33062306a36Sopenharmony_ci| 33162306a36Sopenharmony_cisrc_nan: 33262306a36Sopenharmony_ci btstb #sign_bit,ETEMP_EX(%a6) |test sign of nan 33362306a36Sopenharmony_ci beqs src_pos |if clr, it was positive 33462306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit 33562306a36Sopenharmony_cisrc_pos: 33662306a36Sopenharmony_ci btstb #signan_bit,ETEMP_HI(%a6) |check if signalling 33762306a36Sopenharmony_ci beqs src_snan |branch if signalling 33862306a36Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 33962306a36Sopenharmony_ci fmovex ETEMP(%a6),%fp0 |return the non-signalling nan 34062306a36Sopenharmony_ci rts 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cisrc_snan: 34362306a36Sopenharmony_ci btstb #snan_bit,FPCR_ENABLE(%a6) |check if trap enabled 34462306a36Sopenharmony_ci beqs src_dis |branch if disabled 34562306a36Sopenharmony_ci bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 34662306a36Sopenharmony_ci orb #norm_tag,DTAG(%a6) |set up dtag for norm 34762306a36Sopenharmony_ci orb #nan_tag,STAG(%a6) |set up stag for nan 34862306a36Sopenharmony_ci st STORE_FLG(%a6) |do not store a result 34962306a36Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 35062306a36Sopenharmony_ci rts 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cisrc_dis: 35362306a36Sopenharmony_ci bsetb #signan_bit,ETEMP_HI(%a6) |set SNAN bit in sop 35462306a36Sopenharmony_ci fmovel %d1,%fpcr |restore user's rmode/prec 35562306a36Sopenharmony_ci fmovex ETEMP(%a6),%fp0 |load non-sign. nan 35662306a36Sopenharmony_ci orl #snaniop_mask,USER_FPSR(%a6) |set NAN, SNAN, AIOP 35762306a36Sopenharmony_ci rts 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci| 36062306a36Sopenharmony_ci| For all functions that have a denormalized input and that f(x)=x, 36162306a36Sopenharmony_ci| this is the entry point 36262306a36Sopenharmony_ci| 36362306a36Sopenharmony_cit_extdnrm: 36462306a36Sopenharmony_ci orl #unfinx_mask,USER_FPSR(%a6) 36562306a36Sopenharmony_ci| ;set UNFL, INEX2, AUNFL, AINEX 36662306a36Sopenharmony_ci bras xdnrm_con 36762306a36Sopenharmony_ci| 36862306a36Sopenharmony_ci| Entry point for scale with extended denorm. The function does 36962306a36Sopenharmony_ci| not set inex2, aunfl, or ainex. 37062306a36Sopenharmony_ci| 37162306a36Sopenharmony_cit_resdnrm: 37262306a36Sopenharmony_ci orl #unfl_mask,USER_FPSR(%a6) 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cixdnrm_con: 37562306a36Sopenharmony_ci btstb #unfl_bit,FPCR_ENABLE(%a6) 37662306a36Sopenharmony_ci beqs xdnrm_dis 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci| 37962306a36Sopenharmony_ci| If exceptions are enabled, the additional task of setting up WBTEMP 38062306a36Sopenharmony_ci| is needed so that when the underflow exception handler is entered, 38162306a36Sopenharmony_ci| the user perceives no difference between what the 040 provides vs. 38262306a36Sopenharmony_ci| what the FPSP provides. 38362306a36Sopenharmony_ci| 38462306a36Sopenharmony_cixdnrm_ena: 38562306a36Sopenharmony_ci movel %a0,-(%a7) 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci movel LOCAL_EX(%a0),FP_SCR1(%a6) 38862306a36Sopenharmony_ci movel LOCAL_HI(%a0),FP_SCR1+4(%a6) 38962306a36Sopenharmony_ci movel LOCAL_LO(%a0),FP_SCR1+8(%a6) 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci lea FP_SCR1(%a6),%a0 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 39462306a36Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 39562306a36Sopenharmony_ci tstw LOCAL_EX(%a0) |check if input is denorm 39662306a36Sopenharmony_ci beqs xdnrm_dn |if so, skip nrm_set 39762306a36Sopenharmony_ci bsr nrm_set |normalize the result (exponent 39862306a36Sopenharmony_ci| ;will be negative 39962306a36Sopenharmony_cixdnrm_dn: 40062306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |take off false sign 40162306a36Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |change back to IEEE ext format 40262306a36Sopenharmony_ci beqs xdep 40362306a36Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 40462306a36Sopenharmony_cixdep: 40562306a36Sopenharmony_ci bfclr STAG(%a6){#5:#3} |clear wbtm66,wbtm1,wbtm0 40662306a36Sopenharmony_ci bsetb #wbtemp15_bit,WB_BYTE(%a6) |set wbtemp15 40762306a36Sopenharmony_ci bclrb #sticky_bit,STICKY(%a6) |clear sticky bit 40862306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a6) 40962306a36Sopenharmony_ci movel (%a7)+,%a0 41062306a36Sopenharmony_cixdnrm_dis: 41162306a36Sopenharmony_ci bfextu FPCR_MODE(%a6){#0:#2},%d0 |get round precision 41262306a36Sopenharmony_ci bnes not_ext |if not round extended, store 41362306a36Sopenharmony_ci| ;IEEE defaults 41462306a36Sopenharmony_ciis_ext: 41562306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 41662306a36Sopenharmony_ci beqs xdnrm_store 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci bsetb #neg_bit,FPSR_CC(%a6) |set N bit in FPSR_CC 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci bras xdnrm_store 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cinot_ext: 42362306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) 42462306a36Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 42562306a36Sopenharmony_ci bsr unf_sub |returns IEEE result pointed by 42662306a36Sopenharmony_ci| ;a0; sets FPSR_CC accordingly 42762306a36Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 42862306a36Sopenharmony_ci beqs xdnrm_store 42962306a36Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 43062306a36Sopenharmony_cixdnrm_store: 43162306a36Sopenharmony_ci fmovemx (%a0),%fp0-%fp0 |store result in fp0 43262306a36Sopenharmony_ci rts 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci| 43562306a36Sopenharmony_ci| This subroutine is used for dyadic operations that use an extended 43662306a36Sopenharmony_ci| denorm within the kernel. The approach used is to capture the frame, 43762306a36Sopenharmony_ci| fix/restore. 43862306a36Sopenharmony_ci| 43962306a36Sopenharmony_ci .global t_avoid_unsupp 44062306a36Sopenharmony_cit_avoid_unsupp: 44162306a36Sopenharmony_ci link %a2,#-LOCAL_SIZE |so that a2 fpsp.h negative 44262306a36Sopenharmony_ci| ;offsets may be used 44362306a36Sopenharmony_ci fsave -(%a7) 44462306a36Sopenharmony_ci tstb 1(%a7) |check if idle, exit if so 44562306a36Sopenharmony_ci beq idle_end 44662306a36Sopenharmony_ci btstb #E1,E_BYTE(%a2) |check for an E1 exception if 44762306a36Sopenharmony_ci| ;enabled, there is an unsupp 44862306a36Sopenharmony_ci beq end_avun |else, exit 44962306a36Sopenharmony_ci btstb #7,DTAG(%a2) |check for denorm destination 45062306a36Sopenharmony_ci beqs src_den |else, must be a source denorm 45162306a36Sopenharmony_ci| 45262306a36Sopenharmony_ci| handle destination denorm 45362306a36Sopenharmony_ci| 45462306a36Sopenharmony_ci lea FPTEMP(%a2),%a0 45562306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 45662306a36Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 45762306a36Sopenharmony_ci bclrb #7,DTAG(%a2) |set DTAG to norm 45862306a36Sopenharmony_ci bsr nrm_set |normalize result, exponent 45962306a36Sopenharmony_ci| ;will become negative 46062306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 46162306a36Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 46262306a36Sopenharmony_ci beqs ck_src_den |check if source is also denorm 46362306a36Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 46462306a36Sopenharmony_cick_src_den: 46562306a36Sopenharmony_ci btstb #7,STAG(%a2) 46662306a36Sopenharmony_ci beqs end_avun 46762306a36Sopenharmony_cisrc_den: 46862306a36Sopenharmony_ci lea ETEMP(%a2),%a0 46962306a36Sopenharmony_ci btstb #sign_bit,LOCAL_EX(%a0) 47062306a36Sopenharmony_ci sne LOCAL_SGN(%a0) |convert to internal ext format 47162306a36Sopenharmony_ci bclrb #7,STAG(%a2) |set STAG to norm 47262306a36Sopenharmony_ci bsr nrm_set |normalize result, exponent 47362306a36Sopenharmony_ci| ;will become negative 47462306a36Sopenharmony_ci bclrb #sign_bit,LOCAL_EX(%a0) |get rid of fake sign 47562306a36Sopenharmony_ci bfclr LOCAL_SGN(%a0){#0:#8} |convert back to IEEE ext format 47662306a36Sopenharmony_ci beqs den_com 47762306a36Sopenharmony_ci bsetb #sign_bit,LOCAL_EX(%a0) 47862306a36Sopenharmony_ciden_com: 47962306a36Sopenharmony_ci moveb #0xfe,CU_SAVEPC(%a2) |set continue frame 48062306a36Sopenharmony_ci clrw NMNEXC(%a2) |clear NMNEXC 48162306a36Sopenharmony_ci bclrb #E1,E_BYTE(%a2) 48262306a36Sopenharmony_ci| fmove.l %FPSR,FPSR_SHADOW(%a2) 48362306a36Sopenharmony_ci| bset.b #SFLAG,E_BYTE(%a2) 48462306a36Sopenharmony_ci| bset.b #XFLAG,T_BYTE(%a2) 48562306a36Sopenharmony_ciend_avun: 48662306a36Sopenharmony_ci frestore (%a7)+ 48762306a36Sopenharmony_ci unlk %a2 48862306a36Sopenharmony_ci rts 48962306a36Sopenharmony_ciidle_end: 49062306a36Sopenharmony_ci addl #4,%a7 49162306a36Sopenharmony_ci unlk %a2 49262306a36Sopenharmony_ci rts 49362306a36Sopenharmony_ci |end 494