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