11.6Sandvar* $NetBSD: round.sa,v 1.6 2022/04/08 14:33:24 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* round.sa 3.4 7/29/91 351.1Smycroft* 361.1Smycroft* handle rounding and normalization tasks 371.1Smycroft* 381.1Smycroft 391.1SmycroftROUND IDNT 2,1 Motorola 040 Floating Point Software Package 401.1Smycroft 411.1Smycroft section 8 421.1Smycroft 431.1Smycroft include fpsp.h 441.1Smycroft 451.1Smycroft* 461.1Smycroft* round --- round result according to precision/mode 471.1Smycroft* 481.1Smycroft* a0 points to the input operand in the internal extended format 491.1Smycroft* d1(high word) contains rounding precision: 501.1Smycroft* ext = $0000xxxx 511.1Smycroft* sgl = $0001xxxx 521.1Smycroft* dbl = $0002xxxx 531.1Smycroft* d1(low word) contains rounding mode: 541.1Smycroft* RN = $xxxx0000 551.1Smycroft* RZ = $xxxx0001 561.1Smycroft* RM = $xxxx0010 571.1Smycroft* RP = $xxxx0011 581.1Smycroft* d0{31:29} contains the g,r,s bits (extended) 591.1Smycroft* 601.1Smycroft* On return the value pointed to by a0 is correctly rounded, 611.1Smycroft* a0 is preserved and the g-r-s bits in d0 are cleared. 621.1Smycroft* The result is not typed - the tag field is invalid. The 631.1Smycroft* result is still in the internal extended format. 641.1Smycroft* 651.1Smycroft* The INEX bit of USER_FPSR will be set if the rounded result was 661.1Smycroft* inexact (i.e. if any of the g-r-s bits were set). 671.1Smycroft* 681.1Smycroft 691.1Smycroft xdef round 701.1Smycroftround: 711.1Smycroft* If g=r=s=0 then result is exact and round is done, else set 721.1Smycroft* the inex flag in status reg and continue. 731.1Smycroft* 741.1Smycroft bsr.b ext_grs ;this subroutine looks at the 751.1Smycroft* :rounding precision and sets 761.1Smycroft* ;the appropriate g-r-s bits. 771.1Smycroft tst.l d0 ;if grs are zero, go force 781.1Smycroft bne.w rnd_cont ;lower bits to zero for size 791.1Smycroft 801.1Smycroft swap d1 ;set up d1.w for round prec. 811.1Smycroft bra.w truncate 821.1Smycroft 831.1Smycroftrnd_cont: 841.1Smycroft* 851.1Smycroft* Use rounding mode as an index into a jump table for these modes. 861.1Smycroft* 871.1Smycroft or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex 881.1Smycroft lea mode_tab,a1 891.1Smycroft move.l (a1,d1.w*4),a1 901.1Smycroft jmp (a1) 911.1Smycroft* 921.1Smycroft* Jump table indexed by rounding mode in d1.w. All following assumes 931.1Smycroft* grs != 0. 941.1Smycroft* 951.1Smycroftmode_tab: 961.1Smycroft dc.l rnd_near 971.1Smycroft dc.l rnd_zero 981.1Smycroft dc.l rnd_mnus 991.1Smycroft dc.l rnd_plus 1001.1Smycroft* 1011.1Smycroft* ROUND PLUS INFINITY 1021.1Smycroft* 1031.1Smycroft* If sign of fp number = 0 (positive), then add 1 to l. 1041.1Smycroft* 1051.1Smycroftrnd_plus: 1061.1Smycroft swap d1 ;set up d1 for round prec. 1071.1Smycroft tst.b LOCAL_SGN(a0) ;check for sign 1081.1Smycroft bmi.w truncate ;if positive then truncate 1091.1Smycroft move.l #$ffffffff,d0 ;force g,r,s to be all f's 1101.1Smycroft lea add_to_l,a1 1111.1Smycroft move.l (a1,d1.w*4),a1 1121.1Smycroft jmp (a1) 1131.1Smycroft* 1141.1Smycroft* ROUND MINUS INFINITY 1151.1Smycroft* 1161.1Smycroft* If sign of fp number = 1 (negative), then add 1 to l. 1171.1Smycroft* 1181.1Smycroftrnd_mnus: 1191.1Smycroft swap d1 ;set up d1 for round prec. 1201.1Smycroft tst.b LOCAL_SGN(a0) ;check for sign 1211.1Smycroft bpl.w truncate ;if negative then truncate 1221.1Smycroft move.l #$ffffffff,d0 ;force g,r,s to be all f's 1231.1Smycroft lea add_to_l,a1 1241.1Smycroft move.l (a1,d1.w*4),a1 1251.1Smycroft jmp (a1) 1261.1Smycroft* 1271.1Smycroft* ROUND ZERO 1281.1Smycroft* 1291.1Smycroft* Always truncate. 1301.1Smycroftrnd_zero: 1311.1Smycroft swap d1 ;set up d1 for round prec. 1321.1Smycroft bra.w truncate 1331.1Smycroft* 1341.1Smycroft* 1351.1Smycroft* ROUND NEAREST 1361.1Smycroft* 1371.1Smycroft* If (g=1), then add 1 to l and if (r=s=0), then clear l 1381.1Smycroft* Note that this will round to even in case of a tie. 1391.1Smycroft* 1401.1Smycroftrnd_near: 1411.1Smycroft swap d1 ;set up d1 for round prec. 1421.2Smycroft add.l d0,d0 ;shift g-bit to c-bit 1431.1Smycroft bcc.w truncate ;if (g=1) then 1441.1Smycroft lea add_to_l,a1 1451.1Smycroft move.l (a1,d1.w*4),a1 1461.1Smycroft jmp (a1) 1471.1Smycroft 1481.1Smycroft* 1491.1Smycroft* ext_grs --- extract guard, round and sticky bits 1501.1Smycroft* 1511.1Smycroft* Input: d1 = PREC:ROUND 1521.1Smycroft* Output: d0{31:29}= guard, round, sticky 1531.1Smycroft* 1541.1Smycroft* The ext_grs extract the guard/round/sticky bits according to the 1551.1Smycroft* selected rounding precision. It is called by the round subroutine 1561.1Smycroft* only. All registers except d0 are kept intact. d0 becomes an 1571.1Smycroft* updated guard,round,sticky in d0{31:29} 1581.1Smycroft* 1591.1Smycroft* Notes: the ext_grs uses the round PREC, and therefore has to swap d1 1601.1Smycroft* prior to usage, and needs to restore d1 to original. 1611.1Smycroft* 1621.1Smycroftext_grs: 1631.1Smycroft swap d1 ;have d1.w point to round precision 1641.2Smycroft tst.w d1 1651.1Smycroft bne.b sgl_or_dbl 1661.1Smycroft bra.b end_ext_grs 1671.1Smycroft 1681.1Smycroftsgl_or_dbl: 1691.1Smycroft movem.l d2/d3,-(a7) ;make some temp registers 1701.1Smycroft cmpi.w #1,d1 1711.1Smycroft bne.b grs_dbl 1721.1Smycroftgrs_sgl: 1731.1Smycroft bfextu LOCAL_HI(a0){24:2},d3 ;sgl prec. g-r are 2 bits right 1741.1Smycroft move.l #30,d2 ;of the sgl prec. limits 1751.1Smycroft lsl.l d2,d3 ;shift g-r bits to MSB of d3 1761.1Smycroft move.l LOCAL_HI(a0),d2 ;get word 2 for s-bit test 1771.1Smycroft andi.l #$0000003f,d2 ;s bit is the or of all other 1781.1Smycroft bne.b st_stky ;bits to the right of g-r 1791.1Smycroft tst.l LOCAL_LO(a0) ;test lower mantissa 1801.1Smycroft bne.b st_stky ;if any are set, set sticky 1811.1Smycroft tst.l d0 ;test original g,r,s 1821.1Smycroft bne.b st_stky ;if any are set, set sticky 1831.1Smycroft bra.b end_sd ;if words 3 and 4 are clr, exit 1841.1Smycroftgrs_dbl: 1851.1Smycroft bfextu LOCAL_LO(a0){21:2},d3 ;dbl-prec. g-r are 2 bits right 1861.1Smycroft move.l #30,d2 ;of the dbl prec. limits 1871.1Smycroft lsl.l d2,d3 ;shift g-r bits to the MSB of d3 1881.1Smycroft move.l LOCAL_LO(a0),d2 ;get lower mantissa for s-bit test 1891.1Smycroft andi.l #$000001ff,d2 ;s bit is the or-ing of all 1901.1Smycroft bne.b st_stky ;other bits to the right of g-r 1911.1Smycroft tst.l d0 ;test word original g,r,s 1921.1Smycroft bne.b st_stky ;if any are set, set sticky 1931.1Smycroft bra.b end_sd ;if clear, exit 1941.1Smycroftst_stky: 1951.1Smycroft bset #rnd_stky_bit,d3 1961.1Smycroftend_sd: 1971.1Smycroft move.l d3,d0 ;return grs to d0 1981.1Smycroft movem.l (a7)+,d2/d3 ;restore scratch registers 1991.1Smycroftend_ext_grs: 2001.1Smycroft swap d1 ;restore d1 to original 2011.1Smycroft rts 2021.1Smycroft 2031.1Smycroft******************** Local Equates 2041.1Smycroftad_1_sgl equ $00000100 constant to add 1 to l-bit in sgl prec 2051.1Smycroftad_1_dbl equ $00000800 constant to add 1 to l-bit in dbl prec 2061.1Smycroft 2071.1Smycroft 2081.1Smycroft*Jump table for adding 1 to the l-bit indexed by rnd prec 2091.1Smycroft 2101.1Smycroftadd_to_l: 2111.1Smycroft dc.l add_ext 2121.1Smycroft dc.l add_sgl 2131.1Smycroft dc.l add_dbl 2141.1Smycroft dc.l add_dbl 2151.1Smycroft* 2161.1Smycroft* ADD SINGLE 2171.1Smycroft* 2181.1Smycroftadd_sgl: 2191.1Smycroft add.l #ad_1_sgl,LOCAL_HI(a0) 2201.1Smycroft bcc.b scc_clr ;no mantissa overflow 2211.1Smycroft roxr.w LOCAL_HI(a0) ;shift v-bit back in 2221.1Smycroft roxr.w LOCAL_HI+2(a0) ;shift v-bit back in 2231.1Smycroft add.w #$1,LOCAL_EX(a0) ;and incr exponent 2241.1Smycroftscc_clr: 2251.1Smycroft tst.l d0 ;test for rs = 0 2261.1Smycroft bne.b sgl_done 2271.1Smycroft andi.w #$fe00,LOCAL_HI+2(a0) ;clear the l-bit 2281.1Smycroftsgl_done: 2291.1Smycroft andi.l #$ffffff00,LOCAL_HI(a0) ;truncate bits beyond sgl limit 2301.1Smycroft clr.l LOCAL_LO(a0) ;clear d2 2311.1Smycroft rts 2321.1Smycroft 2331.1Smycroft* 2341.1Smycroft* ADD EXTENDED 2351.1Smycroft* 2361.1Smycroftadd_ext: 2371.1Smycroft addq.l #1,LOCAL_LO(a0) ;add 1 to l-bit 2381.1Smycroft bcc.b xcc_clr ;test for carry out 2391.5Sandvar addq.l #1,LOCAL_HI(a0) ;propagate carry 2401.1Smycroft bcc.b xcc_clr 2411.1Smycroft roxr.w LOCAL_HI(a0) ;mant is 0 so restore v-bit 2421.1Smycroft roxr.w LOCAL_HI+2(a0) ;mant is 0 so restore v-bit 2431.1Smycroft roxr.w LOCAL_LO(a0) 2441.1Smycroft roxr.w LOCAL_LO+2(a0) 2451.1Smycroft add.w #$1,LOCAL_EX(a0) ;and inc exp 2461.1Smycroftxcc_clr: 2471.1Smycroft tst.l d0 ;test rs = 0 2481.1Smycroft bne.b add_ext_done 2491.1Smycroft andi.b #$fe,LOCAL_LO+3(a0) ;clear the l bit 2501.1Smycroftadd_ext_done: 2511.1Smycroft rts 2521.1Smycroft* 2531.1Smycroft* ADD DOUBLE 2541.1Smycroft* 2551.1Smycroftadd_dbl: 2561.1Smycroft add.l #ad_1_dbl,LOCAL_LO(a0) 2571.1Smycroft bcc.b dcc_clr 2581.5Sandvar addq.l #1,LOCAL_HI(a0) ;propagate carry 2591.1Smycroft bcc.b dcc_clr 2601.1Smycroft roxr.w LOCAL_HI(a0) ;mant is 0 so restore v-bit 2611.1Smycroft roxr.w LOCAL_HI+2(a0) ;mant is 0 so restore v-bit 2621.1Smycroft roxr.w LOCAL_LO(a0) 2631.1Smycroft roxr.w LOCAL_LO+2(a0) 2641.1Smycroft add.w #$1,LOCAL_EX(a0) ;incr exponent 2651.1Smycroftdcc_clr: 2661.1Smycroft tst.l d0 ;test for rs = 0 2671.1Smycroft bne.b dbl_done 2681.1Smycroft andi.w #$f000,LOCAL_LO+2(a0) ;clear the l-bit 2691.1Smycroft 2701.1Smycroftdbl_done: 2711.1Smycroft andi.l #$fffff800,LOCAL_LO(a0) ;truncate bits beyond dbl limit 2721.1Smycroft rts 2731.1Smycroft 2741.1Smycrofterror: 2751.1Smycroft rts 2761.1Smycroft* 2771.1Smycroft* Truncate all other bits 2781.1Smycroft* 2791.1Smycrofttrunct: 2801.1Smycroft dc.l end_rnd 2811.1Smycroft dc.l sgl_done 2821.1Smycroft dc.l dbl_done 2831.1Smycroft dc.l dbl_done 2841.1Smycroft 2851.1Smycrofttruncate: 2861.1Smycroft lea trunct,a1 2871.1Smycroft move.l (a1,d1.w*4),a1 2881.1Smycroft jmp (a1) 2891.1Smycroft 2901.1Smycroftend_rnd: 2911.1Smycroft rts 2921.1Smycroft 2931.1Smycroft* 2941.1Smycroft* NORMALIZE 2951.1Smycroft* 2961.1Smycroft* These routines (nrm_zero & nrm_set) normalize the unnorm. This 2971.1Smycroft* is done by shifting the mantissa left while decrementing the 2981.1Smycroft* exponent. 2991.1Smycroft* 3001.1Smycroft* NRM_SET shifts and decrements until there is a 1 set in the integer 3011.1Smycroft* bit of the mantissa (msb in d1). 3021.1Smycroft* 3031.1Smycroft* NRM_ZERO shifts and decrements until there is a 1 set in the integer 3041.1Smycroft* bit of the mantissa (msb in d1) unless this would mean the exponent 3051.1Smycroft* would go less than 0. In that case the number becomes a denorm - the 3061.1Smycroft* exponent (d0) is set to 0 and the mantissa (d1 & d2) is not 3071.1Smycroft* normalized. 3081.1Smycroft* 3091.1Smycroft* Note that both routines have been optimized (for the worst case) and 3101.1Smycroft* therefore do not have the easy to follow decrement/shift loop. 3111.1Smycroft* 3121.1Smycroft* NRM_ZERO 3131.1Smycroft* 3141.1Smycroft* Distance to first 1 bit in mantissa = X 3151.1Smycroft* Distance to 0 from exponent = Y 3161.1Smycroft* If X < Y 3171.1Smycroft* Then 3181.1Smycroft* nrm_set 3191.1Smycroft* Else 3201.1Smycroft* shift mantissa by Y 3211.1Smycroft* set exponent = 0 3221.1Smycroft* 3231.1Smycroft*input: 3241.1Smycroft* FP_SCR1 = exponent, ms mantissa part, ls mantissa part 3251.1Smycroft*output: 3261.1Smycroft* L_SCR1{4} = fpte15 or ete15 bit 3271.1Smycroft* 3281.1Smycroft xdef nrm_zero 3291.1Smycroftnrm_zero: 3301.1Smycroft move.w LOCAL_EX(a0),d0 3311.1Smycroft cmp.w #64,d0 ;see if exp > 64 3321.1Smycroft bmi.b d0_less 3331.1Smycroft bsr nrm_set ;exp > 64 so exp won't exceed 0 3341.1Smycroft rts 3351.1Smycroftd0_less: 3361.1Smycroft movem.l d2/d3/d5/d6,-(a7) 3371.1Smycroft move.l LOCAL_HI(a0),d1 3381.1Smycroft move.l LOCAL_LO(a0),d2 3391.1Smycroft 3401.1Smycroft bfffo d1{0:32},d3 ;get the distance to the first 1 3411.1Smycroft* ;in ms mant 3421.1Smycroft beq.b ms_clr ;branch if no bits were set 3431.1Smycroft cmp.w d3,d0 ;of X>Y 3441.1Smycroft bmi.b greater ;then exp will go past 0 (neg) if 3451.1Smycroft* ;it is just shifted 3461.1Smycroft bsr nrm_set ;else exp won't go past 0 3471.1Smycroft movem.l (a7)+,d2/d3/d5/d6 3481.1Smycroft rts 3491.1Smycroftgreater: 3501.1Smycroft move.l d2,d6 ;save ls mant in d6 3511.1Smycroft lsl.l d0,d2 ;shift ls mant by count 3521.1Smycroft lsl.l d0,d1 ;shift ms mant by count 3531.1Smycroft move.l #32,d5 3541.1Smycroft sub.l d0,d5 ;make op a denorm by shifting bits 3551.1Smycroft lsr.l d5,d6 ;by the number in the exp, then 3561.1Smycroft* ;set exp = 0. 3571.1Smycroft or.l d6,d1 ;shift the ls mant bits into the ms mant 3581.2Smycroft clr.l d0 ;same as if decremented exp to 0 3591.1Smycroft* ;while shifting 3601.1Smycroft move.w d0,LOCAL_EX(a0) 3611.1Smycroft move.l d1,LOCAL_HI(a0) 3621.1Smycroft move.l d2,LOCAL_LO(a0) 3631.1Smycroft movem.l (a7)+,d2/d3/d5/d6 3641.1Smycroft rts 3651.1Smycroftms_clr: 3661.1Smycroft bfffo d2{0:32},d3 ;check if any bits set in ls mant 3671.1Smycroft beq.b all_clr ;branch if none set 3681.1Smycroft add.w #32,d3 3691.1Smycroft cmp.w d3,d0 ;if X>Y 3701.1Smycroft bmi.b greater ;then branch 3711.1Smycroft bsr nrm_set ;else exp won't go past 0 3721.1Smycroft movem.l (a7)+,d2/d3/d5/d6 3731.1Smycroft rts 3741.1Smycroftall_clr: 3751.2Smycroft clr.w LOCAL_EX(a0) ;no mantissa bits set. Set exp = 0. 3761.1Smycroft movem.l (a7)+,d2/d3/d5/d6 3771.1Smycroft rts 3781.1Smycroft* 3791.1Smycroft* NRM_SET 3801.1Smycroft* 3811.1Smycroft xdef nrm_set 3821.1Smycroftnrm_set: 3831.1Smycroft move.l d7,-(a7) 3841.1Smycroft bfffo LOCAL_HI(a0){0:32},d7 ;find first 1 in ms mant to d7) 3851.1Smycroft beq.b lower ;branch if ms mant is all 0's 3861.1Smycroft 3871.1Smycroft move.l d6,-(a7) 3881.1Smycroft 3891.1Smycroft sub.w d7,LOCAL_EX(a0) ;sub exponent by count 3901.1Smycroft move.l LOCAL_HI(a0),d0 ;d0 has ms mant 3911.1Smycroft move.l LOCAL_LO(a0),d1 ;d1 has ls mant 3921.1Smycroft 3931.1Smycroft lsl.l d7,d0 ;shift first 1 to j bit position 3941.1Smycroft move.l d1,d6 ;copy ls mant into d6 3951.1Smycroft lsl.l d7,d6 ;shift ls mant by count 3961.1Smycroft move.l d6,LOCAL_LO(a0) ;store ls mant into memory 3971.1Smycroft moveq.l #32,d6 3981.1Smycroft sub.l d7,d6 ;continue shift 3991.1Smycroft lsr.l d6,d1 ;shift off all bits but those that will 4001.1Smycroft* ;be shifted into ms mant 4011.1Smycroft or.l d1,d0 ;shift the ls mant bits into the ms mant 4021.1Smycroft move.l d0,LOCAL_HI(a0) ;store ms mant into memory 4031.1Smycroft movem.l (a7)+,d7/d6 ;restore registers 4041.1Smycroft rts 4051.1Smycroft 4061.1Smycroft* 4071.1Smycroft* We get here if ms mant was = 0, and we assume ls mant has bits 4081.1Smycroft* set (otherwise this would have been tagged a zero not a denorm). 4091.1Smycroft* 4101.1Smycroftlower: 4111.1Smycroft move.w LOCAL_EX(a0),d0 ;d0 has exponent 4121.1Smycroft move.l LOCAL_LO(a0),d1 ;d1 has ls mant 4131.1Smycroft sub.w #32,d0 ;account for ms mant being all zeros 4141.1Smycroft bfffo d1{0:32},d7 ;find first 1 in ls mant to d7) 4151.1Smycroft sub.w d7,d0 ;subtract shift count from exp 4161.1Smycroft lsl.l d7,d1 ;shift first 1 to integer bit in ms mant 4171.1Smycroft move.w d0,LOCAL_EX(a0) ;store ms mant 4181.1Smycroft move.l d1,LOCAL_HI(a0) ;store exp 4191.1Smycroft clr.l LOCAL_LO(a0) ;clear ls mant 4201.1Smycroft move.l (a7)+,d7 4211.1Smycroft rts 4221.1Smycroft* 4231.1Smycroft* denorm --- denormalize an intermediate result 4241.1Smycroft* 4251.1Smycroft* Used by underflow. 4261.1Smycroft* 4271.1Smycroft* Input: 4281.1Smycroft* a0 points to the operand to be denormalized 4291.1Smycroft* (in the internal extended format) 4301.1Smycroft* 4311.1Smycroft* d0: rounding precision 4321.1Smycroft* Output: 4331.1Smycroft* a0 points to the denormalized result 4341.1Smycroft* (in the internal extended format) 4351.1Smycroft* 4361.1Smycroft* d0 is guard,round,sticky 4371.1Smycroft* 4381.1Smycroft* d0 comes into this routine with the rounding precision. It 4391.1Smycroft* is then loaded with the denormalized exponent threshold for the 4401.1Smycroft* rounding precision. 4411.1Smycroft* 4421.1Smycroft 4431.1Smycroft xdef denorm 4441.1Smycroftdenorm: 4451.1Smycroft btst.b #6,LOCAL_EX(a0) ;check for exponents between $7fff-$4000 4461.1Smycroft beq.b no_sgn_ext 4471.1Smycroft bset.b #7,LOCAL_EX(a0) ;sign extend if it is so 4481.1Smycroftno_sgn_ext: 4491.1Smycroft 4501.2Smycroft tst.b d0 ;if 0 then extended precision 4511.1Smycroft bne.b not_ext ;else branch 4521.1Smycroft 4531.1Smycroft clr.l d1 ;load d1 with ext threshold 4541.1Smycroft clr.l d0 ;clear the sticky flag 4551.1Smycroft bsr dnrm_lp ;denormalize the number 4561.1Smycroft tst.b d1 ;check for inex 4571.1Smycroft beq.w no_inex ;if clr, no inex 4581.1Smycroft bra.b dnrm_inex ;if set, set inex 4591.1Smycroft 4601.1Smycroftnot_ext: 4611.1Smycroft cmpi.l #1,d0 ;if 1 then single precision 4621.1Smycroft beq.b load_sgl ;else must be 2, double prec 4631.1Smycroft 4641.1Smycroftload_dbl: 4651.1Smycroft move.w #dbl_thresh,d1 ;put copy of threshold in d1 4661.1Smycroft move.l d1,d0 ;copy d1 into d0 4671.1Smycroft sub.w LOCAL_EX(a0),d0 ;diff = threshold - exp 4681.1Smycroft cmp.w #67,d0 ;if diff > 67 (mant + grs bits) 4691.1Smycroft bpl.b chk_stky ;then branch (all bits would be 4701.1Smycroft* ; shifted off in denorm routine) 4711.1Smycroft clr.l d0 ;else clear the sticky flag 4721.1Smycroft bsr dnrm_lp ;denormalize the number 4731.1Smycroft tst.b d1 ;check flag 4741.1Smycroft beq.b no_inex ;if clr, no inex 4751.1Smycroft bra.b dnrm_inex ;if set, set inex 4761.1Smycroft 4771.1Smycroftload_sgl: 4781.1Smycroft move.w #sgl_thresh,d1 ;put copy of threshold in d1 4791.1Smycroft move.l d1,d0 ;copy d1 into d0 4801.1Smycroft sub.w LOCAL_EX(a0),d0 ;diff = threshold - exp 4811.1Smycroft cmp.w #67,d0 ;if diff > 67 (mant + grs bits) 4821.1Smycroft bpl.b chk_stky ;then branch (all bits would be 4831.1Smycroft* ; shifted off in denorm routine) 4841.1Smycroft clr.l d0 ;else clear the sticky flag 4851.1Smycroft bsr dnrm_lp ;denormalize the number 4861.1Smycroft tst.b d1 ;check flag 4871.1Smycroft beq.b no_inex ;if clr, no inex 4881.1Smycroft bra.b dnrm_inex ;if set, set inex 4891.1Smycroft 4901.1Smycroftchk_stky: 4911.1Smycroft tst.l LOCAL_HI(a0) ;check for any bits set 4921.1Smycroft bne.b set_stky 4931.1Smycroft tst.l LOCAL_LO(a0) ;check for any bits set 4941.1Smycroft bne.b set_stky 4951.1Smycroft bra.b clr_mant 4961.1Smycroftset_stky: 4971.1Smycroft or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex 4981.1Smycroft move.l #$20000000,d0 ;set sticky bit in return value 4991.1Smycroftclr_mant: 5001.1Smycroft move.w d1,LOCAL_EX(a0) ;load exp with threshold 5011.2Smycroft clr.l LOCAL_HI(a0) ;set d1 = 0 (ms mantissa) 5021.2Smycroft clr.l LOCAL_LO(a0) ;set d2 = 0 (ms mantissa) 5031.1Smycroft rts 5041.1Smycroftdnrm_inex: 5051.1Smycroft or.l #inx2a_mask,USER_FPSR(a6) ;set inex2/ainex 5061.1Smycroftno_inex: 5071.1Smycroft rts 5081.1Smycroft 5091.1Smycroft* 5101.4Sandvar* dnrm_lp --- normalize exponent/mantissa to specified threshold 5111.1Smycroft* 5121.1Smycroft* Input: 5131.1Smycroft* a0 points to the operand to be denormalized 5141.1Smycroft* d0{31:29} initial guard,round,sticky 5151.1Smycroft* d1{15:0} denormalization threshold 5161.1Smycroft* Output: 5171.1Smycroft* a0 points to the denormalized operand 5181.1Smycroft* d0{31:29} final guard,round,sticky 5191.1Smycroft* d1.b inexact flag: all ones means inexact result 5201.1Smycroft* 5211.1Smycroft* The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2 5221.1Smycroft* so that bfext can be used to extract the new low part of the mantissa. 5231.1Smycroft* Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there 5241.1Smycroft* is no LOCAL_GRS scratch word following it on the fsave frame. 5251.1Smycroft* 5261.1Smycroft xdef dnrm_lp 5271.1Smycroftdnrm_lp: 5281.1Smycroft move.l d2,-(sp) ;save d2 for temp use 5291.1Smycroft btst.b #E3,E_BYTE(a6) ;test for type E3 exception 5301.1Smycroft beq.b not_E3 ;not type E3 exception 5311.1Smycroft bfextu WBTEMP_GRS(a6){6:3},d2 ;extract guard,round, sticky bit 5321.1Smycroft move.l #29,d0 5331.6Sandvar lsl.l d0,d2 ;shift g,r,s to their positions 5341.1Smycroft move.l d2,d0 5351.1Smycroftnot_E3: 5361.1Smycroft move.l (sp)+,d2 ;restore d2 5371.1Smycroft move.l LOCAL_LO(a0),FP_SCR2+LOCAL_LO(a6) 5381.1Smycroft move.l d0,FP_SCR2+LOCAL_GRS(a6) 5391.1Smycroft move.l d1,d0 ;copy the denorm threshold 5401.1Smycroft sub.w LOCAL_EX(a0),d1 ;d1 = threshold - uns exponent 5411.1Smycroft ble.b no_lp ;d1 <= 0 5421.1Smycroft cmp.w #32,d1 5431.1Smycroft blt.b case_1 ;0 = d1 < 32 5441.1Smycroft cmp.w #64,d1 5451.1Smycroft blt.b case_2 ;32 <= d1 < 64 5461.1Smycroft bra.w case_3 ;d1 >= 64 5471.1Smycroft* 5481.1Smycroft* No normalization necessary 5491.1Smycroft* 5501.1Smycroftno_lp: 5511.1Smycroft clr.b d1 ;set no inex2 reported 5521.1Smycroft move.l FP_SCR2+LOCAL_GRS(a6),d0 ;restore original g,r,s 5531.1Smycroft rts 5541.1Smycroft* 5551.1Smycroft* case (0<d1<32) 5561.1Smycroft* 5571.1Smycroftcase_1: 5581.1Smycroft move.l d2,-(sp) 5591.1Smycroft move.w d0,LOCAL_EX(a0) ;exponent = denorm threshold 5601.1Smycroft move.l #32,d0 5611.1Smycroft sub.w d1,d0 ;d0 = 32 - d1 5621.1Smycroft bfextu LOCAL_EX(a0){d0:32},d2 5631.1Smycroft bfextu d2{d1:d0},d2 ;d2 = new LOCAL_HI 5641.1Smycroft bfextu LOCAL_HI(a0){d0:32},d1 ;d1 = new LOCAL_LO 5651.1Smycroft bfextu FP_SCR2+LOCAL_LO(a6){d0:32},d0 ;d0 = new G,R,S 5661.1Smycroft move.l d2,LOCAL_HI(a0) ;store new LOCAL_HI 5671.1Smycroft move.l d1,LOCAL_LO(a0) ;store new LOCAL_LO 5681.1Smycroft clr.b d1 5691.1Smycroft bftst d0{2:30} 5701.1Smycroft beq.b c1nstky 5711.1Smycroft bset.l #rnd_stky_bit,d0 5721.1Smycroft st.b d1 5731.1Smycroftc1nstky: 5741.1Smycroft move.l FP_SCR2+LOCAL_GRS(a6),d2 ;restore original g,r,s 5751.1Smycroft andi.l #$e0000000,d2 ;clear all but G,R,S 5761.1Smycroft tst.l d2 ;test if original G,R,S are clear 5771.1Smycroft beq.b grs_clear 5781.1Smycroft or.l #$20000000,d0 ;set sticky bit in d0 5791.1Smycroftgrs_clear: 5801.1Smycroft andi.l #$e0000000,d0 ;clear all but G,R,S 5811.1Smycroft move.l (sp)+,d2 5821.1Smycroft rts 5831.1Smycroft* 5841.1Smycroft* case (32<=d1<64) 5851.1Smycroft* 5861.1Smycroftcase_2: 5871.1Smycroft move.l d2,-(sp) 5881.1Smycroft move.w d0,LOCAL_EX(a0) ;unsigned exponent = threshold 5891.1Smycroft sub.w #32,d1 ;d1 now between 0 and 32 5901.1Smycroft move.l #32,d0 5911.1Smycroft sub.w d1,d0 ;d0 = 32 - d1 5921.1Smycroft bfextu LOCAL_EX(a0){d0:32},d2 5931.1Smycroft bfextu d2{d1:d0},d2 ;d2 = new LOCAL_LO 5941.1Smycroft bfextu LOCAL_HI(a0){d0:32},d1 ;d1 = new G,R,S 5951.1Smycroft bftst d1{2:30} 5961.1Smycroft bne.b c2_sstky ;bra if sticky bit to be set 5971.1Smycroft bftst FP_SCR2+LOCAL_LO(a6){d0:32} 5981.1Smycroft bne.b c2_sstky ;bra if sticky bit to be set 5991.1Smycroft move.l d1,d0 6001.1Smycroft clr.b d1 6011.1Smycroft bra.b end_c2 6021.1Smycroftc2_sstky: 6031.1Smycroft move.l d1,d0 6041.1Smycroft bset.l #rnd_stky_bit,d0 6051.1Smycroft st.b d1 6061.1Smycroftend_c2: 6071.1Smycroft clr.l LOCAL_HI(a0) ;store LOCAL_HI = 0 6081.1Smycroft move.l d2,LOCAL_LO(a0) ;store LOCAL_LO 6091.1Smycroft move.l FP_SCR2+LOCAL_GRS(a6),d2 ;restore original g,r,s 6101.1Smycroft andi.l #$e0000000,d2 ;clear all but G,R,S 6111.1Smycroft tst.l d2 ;test if original G,R,S are clear 6121.1Smycroft beq.b clear_grs 6131.1Smycroft or.l #$20000000,d0 ;set sticky bit in d0 6141.1Smycroftclear_grs: 6151.1Smycroft andi.l #$e0000000,d0 ;get rid of all but G,R,S 6161.1Smycroft move.l (sp)+,d2 6171.1Smycroft rts 6181.1Smycroft* 6191.1Smycroft* d1 >= 64 Force the exponent to be the denorm threshold with the 6201.1Smycroft* correct sign. 6211.1Smycroft* 6221.1Smycroftcase_3: 6231.1Smycroft move.w d0,LOCAL_EX(a0) 6241.1Smycroft tst.w LOCAL_SGN(a0) 6251.1Smycroft bge.b c3con 6261.1Smycroftc3neg: 6271.1Smycroft or.l #$80000000,LOCAL_EX(a0) 6281.1Smycroftc3con: 6291.1Smycroft cmp.w #64,d1 6301.1Smycroft beq.b sixty_four 6311.1Smycroft cmp.w #65,d1 6321.1Smycroft beq.b sixty_five 6331.1Smycroft* 6341.1Smycroft* Shift value is out of range. Set d1 for inex2 flag and 6351.1Smycroft* return a zero with the given threshold. 6361.1Smycroft* 6371.1Smycroft clr.l LOCAL_HI(a0) 6381.1Smycroft clr.l LOCAL_LO(a0) 6391.1Smycroft move.l #$20000000,d0 6401.1Smycroft st.b d1 6411.1Smycroft rts 6421.1Smycroft 6431.1Smycroftsixty_four: 6441.1Smycroft move.l LOCAL_HI(a0),d0 6451.1Smycroft bfextu d0{2:30},d1 6461.1Smycroft andi.l #$c0000000,d0 6471.1Smycroft bra.b c3com 6481.1Smycroft 6491.1Smycroftsixty_five: 6501.1Smycroft move.l LOCAL_HI(a0),d0 6511.1Smycroft bfextu d0{1:31},d1 6521.1Smycroft andi.l #$80000000,d0 6531.1Smycroft lsr.l #1,d0 ;shift high bit into R bit 6541.1Smycroft 6551.1Smycroftc3com: 6561.1Smycroft tst.l d1 6571.1Smycroft bne.b c3ssticky 6581.1Smycroft tst.l LOCAL_LO(a0) 6591.1Smycroft bne.b c3ssticky 6601.1Smycroft tst.b FP_SCR2+LOCAL_GRS(a6) 6611.1Smycroft bne.b c3ssticky 6621.1Smycroft clr.b d1 6631.1Smycroft bra.b c3end 6641.1Smycroft 6651.1Smycroftc3ssticky: 6661.1Smycroft bset.l #rnd_stky_bit,d0 6671.1Smycroft st.b d1 6681.1Smycroftc3end: 6691.1Smycroft clr.l LOCAL_HI(a0) 6701.1Smycroft clr.l LOCAL_LO(a0) 6711.1Smycroft rts 6721.1Smycroft 6731.1Smycroft end 674