📄 round.s
字号:
jeq ms_clr | branch if no bits were set cmpw d3,d0 | of X>Y jmi greater | then exp will go past 0 (neg) if| | it is just shifted bsrl __x_nrm_set /* | else exp won't go past 0 */ moveml a7@+,d2/d3/d5/d6 rtsgreater: movel d2,d6 | save ls mant in d6 lsll d0,d2 | shift ls mant by count lsll d0,d1 | shift ms mant by count movel #32,d5 subl d0,d5 | make op a denorm by shifting bits lsrl d5,d6 | by the number in the exp, then| | set exp = 0. orl d6,d1 | shift the ls mant bits into the ms mant movel #0,d0 | same as if decremented exp to 0| | while shifting movew d0,a0@(LOCAL_EX) movel d1,a0@(LOCAL_HI) movel d2,a0@(LOCAL_LO) moveml a7@+,d2/d3/d5/d6 rtsms_clr: bfffo d2{#0:#32},d3 | check if any bits set in ls mant jeq all_clr | branch if none set addw #32,d3 cmpw d3,d0 | if X>Y jmi greater | then branch bsrl __x_nrm_set /* | else exp won't go past 0 */ moveml a7@+,d2/d3/d5/d6 rtsall_clr: movew #0,a0@(LOCAL_EX) | no mantissa bits set. Set exp = 0. moveml a7@+,d2/d3/d5/d6 rts|| NRM_SET| .globl __x_nrm_set__x_nrm_set: movel d7,a7@- bfffo a0@(LOCAL_HI){#0:#32},d7 | find first 1 in ms mant to d7) jeq lower /* | branch if ms mant is all 0's */ movel d6,a7@- subw d7,a0@(LOCAL_EX) | sub exponent by count movel a0@(LOCAL_HI),d0 | d0 has ms mant movel a0@(LOCAL_LO),d1 | d1 has ls mant lsll d7,d0 | shift first 1 to j bit position movel d1,d6 | copy ls mant into d6 lsll d7,d6 | shift ls mant by count movel d6,a0@(LOCAL_LO) | store ls mant into memory moveql #32,d6 subl d7,d6 | continue shift lsrl d6,d1 | shift off all bits but those that will| | be shifted into ms mant orl d1,d0 | shift the ls mant bits into the ms mant movel d0,a0@(LOCAL_HI) | store ms mant into memory moveml a7@+,d7/d6 | restore registers rts|| We get here if ms mant was = 0, and we assume ls mant has bits| set (otherwise this would have been tagged a zero not a denorm).|lower: movew a0@(LOCAL_EX),d0 | d0 has exponent movel a0@(LOCAL_LO),d1 | d1 has ls mant subw #32,d0 | account for ms mant being all zeros bfffo d1{#0:#32},d7 | find first 1 in ls mant to d7) subw d7,d0 | subtract shift count from exp lsll d7,d1 | shift first 1 to integer bit in ms mant movew d0,a0@(LOCAL_EX) | store ms mant movel d1,a0@(LOCAL_HI) | store exp clrl a0@(LOCAL_LO) | clear ls mant movel a7@+,d7 rts|| __x_denorm --- denormalize an intermediate result|| Used by underflow.|| Input:| a0 points to the operand to be denormalized| (in the internal extended format)|| d0: rounding precision| Output:| a0 points to the denormalized result| (in the internal extended format)|| d0 is guard,round,sticky|| d0 comes into this routine with the rounding precision. It| is then loaded with the denormalized exponent threshold for the| rounding precision.| .globl __x_denorm__x_denorm: btst #6,a0@(LOCAL_EX) | check for exponents between 0x7fff-0x4000 jeq no_sgn_ext bset #7,a0@(LOCAL_EX) | sign extend if it is sono_sgn_ext: cmpib #0,d0 | if 0 then extended precision jne not_ext | else branch clrl d1 | load d1 with ext threshold clrl d0 | clear the sticky flag bsrl __x_dnrm_lp | denormalize the number tstb d1 | check for inex jeq no_inex | if clr, no inex jra dnrm_inex | if set, set inexnot_ext: cmpil #1,d0 | if 1 then single precision jeq load_sgl | else must be 2, double precload_dbl: movew #dbl_thresh,d1 | put copy of threshold in d1 movel d1,d0 | copy d1 into d0 subw a0@(LOCAL_EX),d0 | diff = threshold - exp cmpw #67,d0 | if diff > 67 (mant + grs bits) jpl chk_stky | then branch (all bits would be| | shifted off in denorm routine) clrl d0 | else clear the sticky flag bsrl __x_dnrm_lp | denormalize the number tstb d1 | check flag jeq no_inex | if clr, no inex jra dnrm_inex | if set, set inexload_sgl: movew #sgl_thresh,d1 | put copy of threshold in d1 movel d1,d0 | copy d1 into d0 subw a0@(LOCAL_EX),d0 | diff = threshold - exp cmpw #67,d0 | if diff > 67 (mant + grs bits) jpl chk_stky | then branch (all bits would be| | shifted off in __x_denorm routine) clrl d0 | else clear the sticky flag bsrl __x_dnrm_lp | denormalize the number tstb d1 | check flag jeq no_inex | if clr, no inex jra dnrm_inex | if set, set inexchk_stky: tstl a0@(LOCAL_HI) | check for any bits set jne set_stky tstl a0@(LOCAL_LO) | check for any bits set jne set_stky jra clr_mantset_stky: orl #inx2a_mask,a6@(USER_FPSR) | set inex2/ainex movel #0x20000000,d0 | set sticky bit in return valueclr_mant: movew d1,a0@(LOCAL_EX) | load exp with threshold movel #0,a0@(LOCAL_HI) | set d1 = 0 (ms mantissa) movel #0,a0@(LOCAL_LO) | set d2 = 0 (ms mantissa) rtsdnrm_inex: orl #inx2a_mask,a6@(USER_FPSR) | set inex2/ainexno_inex: rts|| __x_dnrm_lp --- normalize exponent/mantissa to specified threshhold|| Input:| a0 points to the operand to be denormalized| d0{31:29} initial guard,round,sticky| d1{15:0} denormalization threshold| Output:| a0 points to the denormalized operand| d0{31:29} final guard,round,sticky| d1b inexact flag: all ones means inexact result|| The LOCAL_LO and LOCAL_GRS parts of the value are copied to FP_SCR2| so that bfext can be used to extract the new low part of the mantissa.| Dnrm_lp can be called with a0 pointing to ETEMP or WBTEMP and there| is no LOCAL_GRS scratch word following it on the fsave frame.| .globl __x_dnrm_lp__x_dnrm_lp: movel d2,a7@- | save d2 for temp use btst #E3,a6@(E_BYTE) | test for type E3 exception jeq not_E3 | not type E3 exception clrl d0 | guard,round,sticky init. bfextu a6@(WBTEMP_GRS){#6:#3},d2 | extract guard,round, sticky bit| The following bit shift specifies a larger number of bits than actually| allowed (8). So, it was divided into a series of smaller shifts.| lsll #29,d2 | original shift g,r,s to their postions||| lsll #8,d2 | shift g,r,s 8 bits| lsll #8,d2 | shift g,r,s 8 bits (total 16)| lsll #8,d2 | shift g,r,s 8 bits (total 24)| lsll #5,d2 | shift g,r,s 5 bits (total 29)| orl d2,d0 | in d0 movel #29,d0 lsll d0,d2 | shift g,r,s to their postions movel d2,d0not_E3: movel a7@+,d2 | restore d2 movel a0@(LOCAL_LO),a6@(FP_SCR2+LOCAL_LO) movel d0,a6@(FP_SCR2+LOCAL_GRS) movel d1,d0 | copy the denorm threshold subw a0@(LOCAL_EX),d1 | d1 = threshold - uns exponent jle no_lp | d1 <= 0 cmpw #32,d1 jlt case_1 | 0 = d1 < 32 cmpw #64,d1 jlt case_2 | 32 <= d1 < 64 jra case_3 | d1 >= 64|| No normalization necessary|no_lp: clrb d1 | set no inex2 reported movel a6@(FP_SCR2+LOCAL_GRS),d0 | restore original g,r,s rts|| case (0<d1<32)|case_1: movel d2,a7@- movew d0,a0@(LOCAL_EX) | exponent = denorm threshold movel #32,d0 subw d1,d0 | d0 = 32 - d1 bfextu a0@(LOCAL_EX){d0:#32},d2 bfextu d2{d1:d0},d2 | d2 = new LOCAL_HI bfextu a0@(LOCAL_HI){d0:#32},d1 | d1 = new LOCAL_LO bfextu a6@(FP_SCR2+LOCAL_LO){d0:#32},d0 | d0 = new G,R,S movel d2,a0@(LOCAL_HI) | store new LOCAL_HI movel d1,a0@(LOCAL_LO) | store new LOCAL_LO clrb d1 bftst d0{#2:#30} jeq c1nstky bset #rnd_stky_bit,d0 st d1c1nstky: movel a6@(FP_SCR2+LOCAL_GRS),d2 | restore original g,r,s andil #0xe0000000,d2 | clear all but G,R,S tstl d2 | test if original G,R,S are clear jeq grs_clear orl #0x20000000,d0 | set sticky bit in d0grs_clear: andil #0xe0000000,d0 | clear all but G,R,S movel a7@+,d2 rts|| case (32<=d1<64)|case_2: movel d2,a7@- movew d0,a0@(LOCAL_EX) | unsigned exponent = threshold subw #32,d1 | d1 now between 0 and 32 movel #32,d0 subw d1,d0 | d0 = 32 - d1 bfextu a0@(LOCAL_EX){d0:#32},d2 bfextu d2{d1:d0},d2 | d2 = new LOCAL_LO bfextu a0@(LOCAL_HI){d0:#32},d1 | d1 = new G,R,S bftst d1{#2:#30} jne c2_sstky | jra if sticky bit to be set bftst a6@(FP_SCR2+LOCAL_LO){d0:#32} jne c2_sstky | jra if sticky bit to be set movel d1,d0 clrb d1 jra end_c2c2_sstky: movel d1,d0 bset #rnd_stky_bit,d0 st d1end_c2: clrl a0@(LOCAL_HI) | store LOCAL_HI = 0 movel d2,a0@(LOCAL_LO) | store LOCAL_LO movel a6@(FP_SCR2+LOCAL_GRS),d2 | restore original g,r,s andil #0xe0000000,d2 | clear all but G,R,S tstl d2 | test if original G,R,S are clear jeq clear_grs orl #0x20000000,d0 | set sticky bit in d0clear_grs: andil #0xe0000000,d0 | get rid of all but G,R,S movel a7@+,d2 rts|| d1 >= 64 Force the exponent to be the denorm threshold with the| correct sign.|case_3: movew d0,a0@(LOCAL_EX) tstw a0@(LOCAL_SGN) jge c3conc3neg: orl #0x80000000,a0@(LOCAL_EX)c3con: cmpw #64,d1 jeq sixty_four cmpw #65,d1 jeq sixty_five|| Shift value is out of range. Set d1 for inex2 flag and| return a zero with the given threshold.| clrl a0@(LOCAL_HI) clrl a0@(LOCAL_LO) movel #0x20000000,d0 st d1 rtssixty_four: movel a0@(LOCAL_HI),d0 bfextu d0{#2:#30},d1 andil #0xc0000000,d0 jra c3comsixty_five: movel a0@(LOCAL_HI),d0 bfextu d0{#1:#31},d1 andil #0x80000000,d0 lsrl #1,d0 | shift high bit into R bitc3com: tstl d1 jne c3ssticky tstl a0@(LOCAL_LO) jne c3ssticky tstb a6@(FP_SCR2+LOCAL_GRS) jne c3ssticky clrb d1 jra c3endc3ssticky: bset #rnd_stky_bit,d0 st d1c3end: clrl a0@(LOCAL_HI) clrl a0@(LOCAL_LO) rts| end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -