11.6Sandvar* $NetBSD: x_unfl.sa,v 1.6 2024/09/20 19:38:53 andvar Exp $ 21.3Scgd 31.1Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 41.1Smycroft* M68000 Hi-Performance Microprocessor Division 51.1Smycroft* M68040 Software Package 61.1Smycroft* 71.1Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 81.1Smycroft* All rights reserved. 91.1Smycroft* 101.1Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 111.1Smycroft* To the maximum extent permitted by applicable law, 121.1Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 131.1Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 141.1Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 151.1Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 161.1Smycroft* and any accompanying written materials. 171.1Smycroft* 181.1Smycroft* To the maximum extent permitted by applicable law, 191.1Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 201.1Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 211.1Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 221.1Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 231.1Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 241.1Smycroft* and support of the SOFTWARE. 251.1Smycroft* 261.1Smycroft* You are hereby granted a copyright license to use, modify, and 271.1Smycroft* distribute the SOFTWARE so long as this entire notice is retained 281.1Smycroft* without alteration in any modified and/or redistributed versions, 291.1Smycroft* and that such modified versions are clearly identified as such. 301.1Smycroft* No licenses are granted by implication, estoppel or otherwise 311.1Smycroft* under any patents or trademarks of Motorola, Inc. 321.1Smycroft 331.1Smycroft* 341.1Smycroft* x_unfl.sa 3.4 7/1/91 351.1Smycroft* 361.1Smycroft* fpsp_unfl --- FPSP handler for underflow exception 371.1Smycroft* 381.1Smycroft* Trap disabled results 391.1Smycroft* For 881/2 compatibility, sw must denormalize the intermediate 401.1Smycroft* result, then store the result. Denormalization is accomplished 411.1Smycroft* by taking the intermediate result (which is always normalized) and 421.1Smycroft* shifting the mantissa right while incrementing the exponent until 431.1Smycroft* it is equal to the denormalized exponent for the destination 441.5Sandvar* format. After denormalization, the result is rounded to the 451.1Smycroft* destination format. 461.1Smycroft* 471.1Smycroft* Trap enabled results 481.1Smycroft* All trap disabled code applies. In addition the exceptional 491.1Smycroft* operand needs to made available to the user with a bias of $6000 501.1Smycroft* added to the exponent. 511.1Smycroft* 521.1Smycroft 531.1SmycroftX_UNFL IDNT 2,1 Motorola 040 Floating Point Software Package 541.1Smycroft 551.1Smycroft section 8 561.1Smycroft 571.1Smycroft include fpsp.h 581.1Smycroft 591.1Smycroft xref denorm 601.1Smycroft xref round 611.1Smycroft xref store 621.1Smycroft xref g_rndpr 631.1Smycroft xref g_opcls 641.1Smycroft xref g_dfmtou 651.1Smycroft xref real_unfl 661.1Smycroft xref real_inex 671.1Smycroft xref fpsp_done 681.1Smycroft xref b1238_fix 691.1Smycroft 701.1Smycroft xdef fpsp_unfl 711.1Smycroftfpsp_unfl: 721.1Smycroft link a6,#-LOCAL_SIZE 731.1Smycroft fsave -(a7) 741.1Smycroft movem.l d0-d1/a0-a1,USER_DA(a6) 751.1Smycroft fmovem.x fp0-fp3,USER_FP0(a6) 761.1Smycroft fmovem.l fpcr/fpsr/fpiar,USER_FPCR(a6) 771.1Smycroft 781.1Smycroft* 791.1Smycroft bsr.l unf_res ;denormalize, round & store interm op 801.1Smycroft* 811.1Smycroft* If underflow exceptions are not enabled, check for inexact 821.1Smycroft* exception 831.1Smycroft* 841.1Smycroft btst.b #unfl_bit,FPCR_ENABLE(a6) 851.1Smycroft beq.b ck_inex 861.1Smycroft 871.1Smycroft btst.b #E3,E_BYTE(a6) 881.1Smycroft beq.b no_e3_1 891.1Smycroft* 901.6Sandvar* Clear dirty bit on dest register in the frame before branching 911.1Smycroft* to b1238_fix. 921.1Smycroft* 931.1Smycroft bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no 941.1Smycroft bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 951.1Smycroft bsr.l b1238_fix ;test for bug1238 case 961.1Smycroft move.l USER_FPSR(a6),FPSR_SHADOW(a6) 971.1Smycroft or.l #sx_mask,E_BYTE(a6) 981.1Smycroftno_e3_1: 991.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 1001.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 1011.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 1021.1Smycroft frestore (a7)+ 1031.1Smycroft unlk a6 1041.1Smycroft bra.l real_unfl 1051.1Smycroft* 1061.1Smycroft* It is possible to have either inex2 or inex1 exceptions with the 1071.1Smycroft* unfl. If the inex enable bit is set in the FPCR, and either 1081.4Swiz* inex2 or inex1 occurred, we must clean up and branch to the 1091.1Smycroft* real inex handler. 1101.1Smycroft* 1111.1Smycroftck_inex: 1121.1Smycroft move.b FPCR_ENABLE(a6),d0 1131.1Smycroft and.b FPSR_EXCEPT(a6),d0 1141.1Smycroft andi.b #$3,d0 1151.1Smycroft beq.b unfl_done 1161.1Smycroft 1171.1Smycroft* 1181.1Smycroft* Inexact enabled and reported, and we must take an inexact exception 1191.1Smycroft* 1201.1Smycrofttake_inex: 1211.1Smycroft btst.b #E3,E_BYTE(a6) 1221.1Smycroft beq.b no_e3_2 1231.1Smycroft* 1241.6Sandvar* Clear dirty bit on dest register in the frame before branching 1251.1Smycroft* to b1238_fix. 1261.1Smycroft* 1271.1Smycroft bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no 1281.1Smycroft bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 1291.1Smycroft bsr.l b1238_fix ;test for bug1238 case 1301.1Smycroft move.l USER_FPSR(a6),FPSR_SHADOW(a6) 1311.1Smycroft or.l #sx_mask,E_BYTE(a6) 1321.1Smycroftno_e3_2: 1331.1Smycroft move.b #INEX_VEC,EXC_VEC+1(a6) 1341.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 1351.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 1361.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 1371.1Smycroft frestore (a7)+ 1381.1Smycroft unlk a6 1391.1Smycroft bra.l real_inex 1401.1Smycroft 1411.1Smycroftunfl_done: 1421.1Smycroft bclr.b #E3,E_BYTE(a6) 1431.1Smycroft beq.b e1_set ;if set then branch 1441.1Smycroft* 1451.6Sandvar* Clear dirty bit on dest register in the frame before branching 1461.1Smycroft* to b1238_fix. 1471.1Smycroft* 1481.1Smycroft bfextu CMDREG3B(a6){6:3},d0 ;get dest reg no 1491.1Smycroft bclr.b d0,FPR_DIRTY_BITS(a6) ;clr dest dirty bit 1501.1Smycroft bsr.l b1238_fix ;test for bug1238 case 1511.1Smycroft move.l USER_FPSR(a6),FPSR_SHADOW(a6) 1521.1Smycroft or.l #sx_mask,E_BYTE(a6) 1531.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 1541.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 1551.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 1561.1Smycroft frestore (a7)+ 1571.1Smycroft unlk a6 1581.1Smycroft bra.l fpsp_done 1591.1Smycrofte1_set: 1601.1Smycroft movem.l USER_DA(a6),d0-d1/a0-a1 1611.1Smycroft fmovem.x USER_FP0(a6),fp0-fp3 1621.1Smycroft fmovem.l USER_FPCR(a6),fpcr/fpsr/fpiar 1631.1Smycroft unlk a6 1641.1Smycroft bra.l fpsp_done 1651.1Smycroft* 1661.1Smycroft* unf_res --- underflow result calculation 1671.1Smycroft* 1681.1Smycroftunf_res: 1691.1Smycroft bsr.l g_rndpr ;returns RND_PREC in d0 0=ext, 1701.1Smycroft* ;1=sgl, 2=dbl 1711.1Smycroft* ;we need the RND_PREC in the 1721.1Smycroft* ;upper word for round 1731.2Smycroft clr.w -(a7) 1741.1Smycroft move.w d0,-(a7) ;copy RND_PREC to stack 1751.1Smycroft* 1761.1Smycroft* 1771.1Smycroft* If the exception bit set is E3, the exceptional operand from the 1781.1Smycroft* fpu is in WBTEMP; else it is in FPTEMP. 1791.1Smycroft* 1801.1Smycroft btst.b #E3,E_BYTE(a6) 1811.1Smycroft beq.b unf_E1 1821.1Smycroftunf_E3: 1831.1Smycroft lea WBTEMP(a6),a0 ;a0 now points to operand 1841.1Smycroft* 1851.1Smycroft* Test for fsgldiv and fsglmul. If the inst was one of these, then 1861.1Smycroft* force the precision to extended for the denorm routine. Use 1871.1Smycroft* the user's precision for the round routine. 1881.1Smycroft* 1891.1Smycroft move.w CMDREG3B(a6),d1 ;check for fsgldiv or fsglmul 1901.1Smycroft andi.w #$7f,d1 1911.1Smycroft cmpi.w #$30,d1 ;check for sgldiv 1921.1Smycroft beq.b unf_sgl 1931.1Smycroft cmpi.w #$33,d1 ;check for sglmul 1941.1Smycroft bne.b unf_cont ;if not, use fpcr prec in round 1951.1Smycroftunf_sgl: 1961.1Smycroft clr.l d0 1971.1Smycroft move.w #$1,(a7) ;override g_rndpr precision 1981.1Smycroft* ;force single 1991.1Smycroft bra.b unf_cont 2001.1Smycroftunf_E1: 2011.1Smycroft lea FPTEMP(a6),a0 ;a0 now points to operand 2021.1Smycroftunf_cont: 2031.1Smycroft bclr.b #sign_bit,LOCAL_EX(a0) ;clear sign bit 2041.1Smycroft sne LOCAL_SGN(a0) ;store sign 2051.1Smycroft 2061.1Smycroft bsr.l denorm ;returns denorm, a0 points to it 2071.1Smycroft* 2081.1Smycroft* WARNING: 2091.1Smycroft* ;d0 has guard,round sticky bit 2101.1Smycroft* ;make sure that it is not corrupted 2111.1Smycroft* ;before it reaches the round subroutine 2121.1Smycroft* ;also ensure that a0 isn't corrupted 2131.1Smycroft 2141.1Smycroft* 2151.1Smycroft* Set up d1 for round subroutine d1 contains the PREC/MODE 2161.1Smycroft* information respectively on upper/lower register halves. 2171.1Smycroft* 2181.1Smycroft bfextu FPCR_MODE(a6){2:2},d1 ;get mode from FPCR 2191.1Smycroft* ;mode in lower d1 2201.1Smycroft add.l (a7)+,d1 ;merge PREC/MODE 2211.1Smycroft* 2221.1Smycroft* WARNING: a0 and d0 are assumed to be intact between the denorm and 2231.1Smycroft* round subroutines. All code between these two subroutines 2241.1Smycroft* must not corrupt a0 and d0. 2251.1Smycroft* 2261.1Smycroft* 2271.1Smycroft* Perform Round 2281.1Smycroft* Input: a0 points to input operand 2291.1Smycroft* d0{31:29} has guard, round, sticky 2301.1Smycroft* d1{01:00} has rounding mode 2311.1Smycroft* d1{17:16} has rounding precision 2321.1Smycroft* Output: a0 points to rounded operand 2331.1Smycroft* 2341.1Smycroft 2351.1Smycroft bsr.l round ;returns rounded denorm at (a0) 2361.1Smycroft* 2371.1Smycroft* Differentiate between store to memory vs. store to register 2381.1Smycroft* 2391.1Smycroftunf_store: 2401.1Smycroft bsr.l g_opcls ;returns opclass in d0{2:0} 2411.1Smycroft cmpi.b #$3,d0 2421.1Smycroft bne.b not_opc011 2431.1Smycroft* 2441.1Smycroft* At this point, a store to memory is pending 2451.1Smycroft* 2461.1Smycroftopc011: 2471.1Smycroft bsr.l g_dfmtou 2481.1Smycroft tst.b d0 2491.1Smycroft beq.b ext_opc011 ;If extended, do not subtract 2501.1Smycroft* ;If destination format is sgl/dbl, 2511.1Smycroft tst.b LOCAL_HI(a0) ;If rounded result is normal,don't 2521.1Smycroft* ;subtract 2531.1Smycroft bmi.b ext_opc011 2541.1Smycroft subq.w #1,LOCAL_EX(a0) ;account for denorm bias vs. 2551.1Smycroft* ;normalized bias 2561.1Smycroft* ; normalized denormalized 2571.1Smycroft* ;single $7f $7e 2581.1Smycroft* ;double $3ff $3fe 2591.1Smycroft* 2601.1Smycroftext_opc011: 2611.1Smycroft bsr.l store ;stores to memory 2621.1Smycroft bra.b unf_done ;finish up 2631.1Smycroft 2641.1Smycroft* 2651.1Smycroft* At this point, a store to a float register is pending 2661.1Smycroft* 2671.1Smycroftnot_opc011: 2681.1Smycroft bsr.l store ;stores to float register 2691.1Smycroft* ;a0 is not corrupted on a store to a 2701.1Smycroft* ;float register. 2711.1Smycroft* 2721.1Smycroft* Set the condition codes according to result 2731.1Smycroft* 2741.1Smycroft tst.l LOCAL_HI(a0) ;check upper mantissa 2751.1Smycroft bne.b ck_sgn 2761.1Smycroft tst.l LOCAL_LO(a0) ;check lower mantissa 2771.1Smycroft bne.b ck_sgn 2781.1Smycroft bset.b #z_bit,FPSR_CC(a6) ;set condition codes if zero 2791.1Smycroftck_sgn: 2801.1Smycroft btst.b #sign_bit,LOCAL_EX(a0) ;check the sign bit 2811.1Smycroft beq.b unf_done 2821.1Smycroft bset.b #neg_bit,FPSR_CC(a6) 2831.1Smycroft 2841.1Smycroft* 2851.1Smycroft* Finish. 2861.1Smycroft* 2871.1Smycroftunf_done: 2881.1Smycroft btst.b #inex2_bit,FPSR_EXCEPT(a6) 2891.1Smycroft beq.b no_aunfl 2901.1Smycroft bset.b #aunfl_bit,FPSR_AEXCEPT(a6) 2911.1Smycroftno_aunfl: 2921.1Smycroft rts 2931.1Smycroft 2941.1Smycroft end 295