?? round.s
字號:
/* round.s - Motorola 68040 FP rounding routines (EXC) *//* Copyright 1991-1993 Wind River Systems, Inc. */ .data .globl _copyright_wind_river .long _copyright_wind_river/*modification history--------------------01g,21jul93,kdl added .text (SPR #2372).01f,23aug92,jcf changed bxxx to jxx.01e,26may92,rrr the tree shuffle01d,10jan92,kdl general cleanup.01c,01jan92,jcf reversed order of cmp <reg>,<reg>01b,17dec91,kdl put in changes from Motorola v3.4 (from FPSP 2.1): use register for fixing "lsll 29" problem (01a); add check for negative loop count in __x_dnrm_lp.01a,31jul91,kdl original version, from Motorola FPSP v2.0; divided "lsll #29" into smaller bit shifts.*//*DESCRIPTION roundsa 3.2 2/18/91 handle rounding and normalization tasks Copyright (C) Motorola, Inc. 1990 All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA The copyright notice above does not evidence any actual or intended publication of such source code.ROUND idnt 2,1 Motorola 040 Floating Point Software Package section 8NOMANUAL*/#include "fpsp040E.h"|| __x_round --- round result according to precision/mode|| a0 points to the input operand in the internal extended format| d1(high word) contains rounding precision:| ext = 0x0000xxxx| sgl = 0x0001xxxx| dbl = 0x0002xxxx| d1(low word) contains rounding mode:| RN = $xxxx0000| RZ = $xxxx0001| RM = $xxxx0010| RP = $xxxx0011| d0{31:29} contains the g,r,s bits (extended)|| On return the value pointed to by a0 is correctly rounded,| a0 is preserved and the g-r-s bits in d0 are cleared.| The result is not typed - the tag field is invalid. The| result is still in the internal extended format.|| The INEX bit of USER_FPSR will be set if the rounded result was| inexact (i.e. if any of the g-r-s bits were set).| .globl __x_round .text__x_round:| If g=r=s=0 then result is exact and round is done, else set| the inex flag in status reg and continue.| bsrl ext_grs | this subroutine looks at the| | rounding precision and sets| | the appropriate g-r-s bits. tstl d0 | if grs are zero, go force jne rnd_cont | lower bits to zero for size swap d1 | set up d1:w for round prec. jra truncaternd_cont:|| Use rounding mode as an index into a jump table for these modes.| orl #inx2a_mask,a6@(USER_FPSR) | set inex2/ainex lea mode_tab,a1 movel a1@(d1:w:4),a1 jmp a1@|| Jump table indexed by rounding mode in d1:w. All following assumes| grs != 0.|mode_tab: .long rnd_near .long rnd_zero .long rnd_mnus .long rnd_plus|| ROUND PLUS INFINITY|| If sign of fp number = 0 (positive), then add 1 to l.|rnd_plus: swap d1 | set up d1 for round prec. tstb a0@(LOCAL_SGN) | check for sign jmi truncate | if positive then truncate movel #0xffffffff,d0 /* | force g,r,s to be all f's */ lea add_to_l,a1 movel a1@(d1:w:4),a1 jmp a1@|| ROUND MINUS INFINITY|| If sign of fp number = 1 (negative), then add 1 to l.|rnd_mnus: swap d1 | set up d1 for round prec. tstb a0@(LOCAL_SGN) | check for sign jpl truncate | if negative then truncate movel #0xffffffff,d0 /* | force g,r,s to be all f's */ lea add_to_l,a1 movel a1@(d1:w:4),a1 jmp a1@|| ROUND ZERO|| Always truncate.rnd_zero: swap d1 | set up d1 for round prec. jra truncate||| ROUND NEAREST|| If (g=1), then add 1 to l and if (r=s=0), then clear l| Note that this will round to even in case of a tie.|rnd_near: swap d1 | set up d1 for round prec. asll #1,d0 | shift g-bit to c-bit jcc truncate | if (g=1) then lea add_to_l,a1 movel a1@(d1:w:4),a1 jmp a1@|| ext_grs --- extract guard, round and sticky bits|| Input: d1 = PREC:ROUND| Output: d0{31:29}= guard, round, sticky|| The ext_grs extract the guard/round/sticky bits according to the| selected rounding precision. It is called by the round subroutine| only. All registers except d0 are kept intact. d0 becomes an| updated guard,round,sticky in d0{31:29}|| Notes: the ext_grs uses the round PREC, and therefore has to swap d1| prior to usage, and needs to restore d1 to original.|ext_grs: swap d1 | have d1:w point to round precision cmpiw #0,d1 jne sgl_or_dbl jra end_ext_grssgl_or_dbl: moveml d2/d3,a7@- | make some temp registers cmpiw #1,d1 jne grs_dblgrs_sgl: bfextu a0@(LOCAL_HI){#24:#2},d3 | sgl prec. g-r are 2 bits right movel #30,d2 | of the sgl prec. limits lsll d2,d3 | shift g-r bits to MSB of d3 movel a0@(LOCAL_HI),d2 | get word 2 for s-bit test andil #0x0000003f,d2 | s bit is the or of all other jne st_stky | bits to the right of g-r tstl a0@(LOCAL_LO) | test lower mantissa jne st_stky | if any are set, set sticky tstl d0 | test original g,r,s jne st_stky | if any are set, set sticky jra end_sd | if words 3 and 4 are clr, exitgrs_dbl: bfextu a0@(LOCAL_LO){#21:#2},d3 | dbl-prec. g-r are 2 bits right movel #30,d2 | of the dbl prec. limits lsll d2,d3 | shift g-r bits to the MSB of d3 movel a0@(LOCAL_LO),d2 | get lower mantissa for s-bit test andil #0x000001ff,d2 | s bit is the or-ing of all jne st_stky | other bits to the right of g-r tstl d0 | test word original g,r,s jne st_stky | if any are set, set sticky jra end_sd | if clear, exitst_stky: bset #rnd_stky_bit,d3end_sd: movel d3,d0 | return grs to d0 moveml a7@+,d2/d3 | restore scratch registersend_ext_grs: swap d1 | restore d1 to original rts|******************* Local Equates#define ad_1_sgl 0x00000100 /* constant to add 1 to l-bit in sgl prec */#define ad_1_dbl 0x00000800 /* constant to add 1 to l-bit in dbl prec */|Jump table for adding 1 to the l-bit indexed by rnd precadd_to_l: .long add_ext .long add_sgl .long add_dbl .long add_dbl|| ADD SINGLE|add_sgl: addl #ad_1_sgl,a0@(LOCAL_HI) jcc scc_clr | no mantissa overflow roxrw a0@(LOCAL_HI) | shift v-bit back in roxrw a0@(LOCAL_HI+2) | shift v-bit back in addw #0x1,a0@(LOCAL_EX) | and incr exponentscc_clr: tstl d0 | test for rs = 0 jne sgl_done andiw #0xfe00,a0@(LOCAL_HI+2) | clear the l-bitsgl_done: andil #0xffffff00,a0@(LOCAL_HI) | truncate bits beyond sgl limit clrl a0@(LOCAL_LO) | clear d2 rts|| ADD EXTENDED|add_ext: addql #1,a0@(LOCAL_LO) | add 1 to l-bit jcc xcc_clr | test for carry out addql #1,a0@(LOCAL_HI) | propogate carry jcc xcc_clr roxrw a0@(LOCAL_HI) | mant is 0 so restore v-bit roxrw a0@(LOCAL_HI+2) | mant is 0 so restore v-bit roxrw a0@(LOCAL_LO) roxrw a0@(LOCAL_LO+2) addw #0x1,a0@(LOCAL_EX) | and inc expxcc_clr: tstl d0 | test rs = 0 jne add_ext_done andib #0xfe,a0@(LOCAL_LO+3) | clear the l bitadd_ext_done: rts|| ADD DOUBLE|add_dbl: addl #ad_1_dbl,a0@(LOCAL_LO) jcc dcc_clr addql #1,a0@(LOCAL_HI) | propogate carry jcc dcc_clr roxrw a0@(LOCAL_HI) | mant is 0 so restore v-bit roxrw a0@(LOCAL_HI+2) | mant is 0 so restore v-bit roxrw a0@(LOCAL_LO) roxrw a0@(LOCAL_LO+2) addw #0x1,a0@(LOCAL_EX) | incr exponentdcc_clr: tstl d0 | test for rs = 0 jne dbl_done andiw #0xf000,a0@(LOCAL_LO+2) | clear the l-bitdbl_done: andil #0xfffff800,a0@(LOCAL_LO) | truncate bits beyond dbl limit rtserror: rts|| Truncate all other bits|trunct: .long end_rnd .long sgl_done .long dbl_done .long dbl_donetruncate: lea trunct,a1 movel a1@(d1:w:4),a1 jmp a1@end_rnd: rts|| NORMALIZE|| These routines (nrm_zero # __x_nrm_set) normalize the unnorm. This| is done by shifting the mantissa left while decrementing the| exponent.|| NRM_SET shifts and decrements until there is a 1 set in the integer| bit of the mantissa (msb in d1).|| NRM_ZERO shifts and decrements until there is a 1 set in the integer| bit of the mantissa (msb in d1) unless this would mean the exponent| would go less than 0. In that case the number becomes a denorm - the| exponent d0@ is set to 0 and the mantissa (d1 # d2) is not| normalized.|| Note that both routines have been optimized (for the worst case) and| therefore do not have the easy to follow decrement/shift loop.|| NRM_ZERO|| Distance to first 1 bit in mantissa = X| Distance to 0 from exponent = Y| If X < Y| Then| __x_nrm_set| Else| shift mantissa by Y| set exponent = 0||input:| FP_SCR1 = exponent, ms mantissa part, ls mantissa part|output:| L_SCR1{4} = fpte15 or ete15 bit| .globl __x_nrm_zero__x_nrm_zero: movew a0@(LOCAL_EX),d0 cmpw #64,d0 | see if exp > 64 jmi d0_less bsrl __x_nrm_set /* | exp > 64 so exp won't exceed 0 */ rtsd0_less: moveml d2/d3/d5/d6,a7@- movel a0@(LOCAL_HI),d1 movel a0@(LOCAL_LO),d2 bfffo d1{#0:#32},d3 | get the distance to the first 1| | in ms mant
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -