📄 bindec.s
字号:
|| Register usage:| Input/Output| d0: FPCR with RZ mode/Unchanged| d2: 0 or 24/unchanged| d3: x/x| d4: LEN/Unchanged| d5: ICTR:LAMBDA| d6: ILOG/Unchanged| d7: k-factor/Unchanged| a0: ptr for original operand/final result| a1: ptr to PTENRM array/Unchanged| a2: x/x| fp0: float(ILOG)/X adjusted for SCALE (Y)| fp1: 10^ISCALE/Unchanged| fp2: x/x| F_SCR1:x/x| F_SCR2:Abs(X) with $3fff exponent/Unchanged| L_SCR1:x/x| L_SCR2:first word of X packed/UnchangedA9_str: fmovex (%a0),%fp0 |load X from memory fabsx %fp0 |use abs(X) tstw %d5 |LAMBDA is in lower word of d5 bne sc_mul |if neg (LAMBDA = 1), scale by mul fdivx %fp1,%fp0 |calculate X / SCALE -> Y to fp0 bras A10_st |branch to A10sc_mul: tstb BINDEC_FLG(%a6) |check for denorm beqs A9_norm |if norm, continue with mul fmovemx %fp1-%fp1,-(%a7) |load ETEMP with 10^ISCALE movel 8(%a0),-(%a7) |load FPTEMP with input arg movel 4(%a0),-(%a7) movel (%a0),-(%a7) movel #18,%d3 |load count for busy stackA9_loop: clrl -(%a7) |clear lword on stack dbf %d3,A9_loop moveb VER_TMP(%a6),(%a7) |write current version number moveb #BUSY_SIZE-4,1(%a7) |write current busy size moveb #0x10,0x44(%a7) |set fcefpte[15] bit movew #0x0023,0x40(%a7) |load cmdreg1b with mul command moveb #0xfe,0x8(%a7) |load all 1s to cu savepc frestore (%a7)+ |restore frame to fpu for completion fmulx 36(%a1),%fp0 |multiply fp0 by 10^8 fmulx 48(%a1),%fp0 |multiply fp0 by 10^16 bras A10_stA9_norm: tstw %d2 |test for small exp case beqs A9_con |if zero, continue as normal fmulx 36(%a1),%fp0 |multiply fp0 by 10^8 fmulx 48(%a1),%fp0 |multiply fp0 by 10^16A9_con: fmulx %fp1,%fp0 |calculate X * SCALE -> Y to fp0| A10. Or in INEX.| If INEX is set, round error occurred. This is compensated| for by 'or-ing' in the INEX2 flag to the lsb of Y.|| Register usage:| Input/Output| d0: FPCR with RZ mode/FPSR with INEX2 isolated| d2: x/x| d3: x/x| d4: LEN/Unchanged| d5: ICTR:LAMBDA| d6: ILOG/Unchanged| d7: k-factor/Unchanged| a0: ptr for original operand/final result| a1: ptr to PTENxx array/Unchanged| a2: x/ptr to FP_SCR2(a6)| fp0: Y/Y with lsb adjusted| fp1: 10^ISCALE/Unchanged| fp2: x/xA10_st: fmovel %FPSR,%d0 |get FPSR fmovex %fp0,FP_SCR2(%a6) |move Y to memory leal FP_SCR2(%a6),%a2 |load a2 with ptr to FP_SCR2 btstl #9,%d0 |check if INEX2 set beqs A11_st |if clear, skip rest oril #1,8(%a2) |or in 1 to lsb of mantissa fmovex FP_SCR2(%a6),%fp0 |write adjusted Y back to fpu| A11. Restore original FPCR; set size ext.| Perform FINT operation in the user's rounding mode. Keep| the size to extended. The sintdo entry point in the sint| routine expects the FPCR value to be in USER_FPCR for| mode and precision. The original FPCR is saved in L_SCR1.A11_st: movel USER_FPCR(%a6),L_SCR1(%a6) |save it for later andil #0x00000030,USER_FPCR(%a6) |set size to ext, | ;block exceptions| A12. Calculate YINT = FINT(Y) according to user's rounding mode.| The FPSP routine sintd0 is used. The output is in fp0.|| Register usage:| Input/Output| d0: FPSR with AINEX cleared/FPCR with size set to ext| d2: x/x/scratch| d3: x/x| d4: LEN/Unchanged| d5: ICTR:LAMBDA/Unchanged| d6: ILOG/Unchanged| d7: k-factor/Unchanged| a0: ptr for original operand/src ptr for sintdo| a1: ptr to PTENxx array/Unchanged| a2: ptr to FP_SCR2(a6)/Unchanged| a6: temp pointer to FP_SCR2(a6) - orig value saved and restored| fp0: Y/YINT| fp1: 10^ISCALE/Unchanged| fp2: x/x| F_SCR1:x/x| F_SCR2:Y adjusted for inex/Y with original exponent| L_SCR1:x/original USER_FPCR| L_SCR2:first word of X packed/UnchangedA12_st: moveml %d0-%d1/%a0-%a1,-(%a7) |save regs used by sintd0 movel L_SCR1(%a6),-(%a7) movel L_SCR2(%a6),-(%a7) leal FP_SCR2(%a6),%a0 |a0 is ptr to F_SCR2(a6) fmovex %fp0,(%a0) |move Y to memory at FP_SCR2(a6) tstl L_SCR2(%a6) |test sign of original operand bges do_fint |if pos, use Y orl #0x80000000,(%a0) |if neg, use -Ydo_fint: movel USER_FPSR(%a6),-(%a7) bsr sintdo |sint routine returns int in fp0 moveb (%a7),USER_FPSR(%a6) addl #4,%a7 movel (%a7)+,L_SCR2(%a6) movel (%a7)+,L_SCR1(%a6) moveml (%a7)+,%d0-%d1/%a0-%a1 |restore regs used by sint movel L_SCR2(%a6),FP_SCR2(%a6) |restore original exponent movel L_SCR1(%a6),USER_FPCR(%a6) |restore user's FPCR| A13. Check for LEN digits.| If the int operation results in more than LEN digits,| or less than LEN -1 digits, adjust ILOG and repeat from| A6. This test occurs only on the first pass. If the| result is exactly 10^LEN, decrement ILOG and divide| the mantissa by 10. The calculation of 10^LEN cannot| be inexact, since all powers of ten upto 10^27 are exact| in extended precision, so the use of a previous power-of-ten| table will introduce no error.||| Register usage:| Input/Output| d0: FPCR with size set to ext/scratch final = 0| d2: x/x| d3: x/scratch final = x| d4: LEN/LEN adjusted| d5: ICTR:LAMBDA/LAMBDA:ICTR| d6: ILOG/ILOG adjusted| d7: k-factor/Unchanged| a0: pointer into memory for packed bcd string formation| a1: ptr to PTENxx array/Unchanged| a2: ptr to FP_SCR2(a6)/Unchanged| fp0: int portion of Y/abs(YINT) adjusted| fp1: 10^ISCALE/Unchanged| fp2: x/10^LEN| F_SCR1:x/x| F_SCR2:Y with original exponent/Unchanged| L_SCR1:original USER_FPCR/Unchanged| L_SCR2:first word of X packed/UnchangedA13_st: swap %d5 |put ICTR in lower word of d5 tstw %d5 |check if ICTR = 0 bne not_zr |if non-zero, go to second test|| Compute 10^(LEN-1)| fmoves FONE,%fp2 |init fp2 to 1.0 movel %d4,%d0 |put LEN in d0 subql #1,%d0 |d0 = LEN -1 clrl %d3 |clr table indexl_loop: lsrl #1,%d0 |shift next bit into carry bccs l_next |if zero, skip the mul fmulx (%a1,%d3),%fp2 |mul by 10**(d3_bit_no)l_next: addl #12,%d3 |inc d3 to next pwrten table entry tstl %d0 |test if LEN is zero bnes l_loop |if not, loop|| 10^LEN-1 is computed for this test and A14. If the input was| denormalized, check only the case in which YINT > 10^LEN.| tstb BINDEC_FLG(%a6) |check if input was norm beqs A13_con |if norm, continue with checking fabsx %fp0 |take abs of YINT bra test_2|| Compare abs(YINT) to 10^(LEN-1) and 10^LEN|A13_con: fabsx %fp0 |take abs of YINT fcmpx %fp2,%fp0 |compare abs(YINT) with 10^(LEN-1) fbge test_2 |if greater, do next test subql #1,%d6 |subtract 1 from ILOG movew #1,%d5 |set ICTR fmovel #rm_mode,%FPCR |set rmode to RM fmuls FTEN,%fp2 |compute 10^LEN bra A6_str |return to A6 and recompute YINTtest_2: fmuls FTEN,%fp2 |compute 10^LEN fcmpx %fp2,%fp0 |compare abs(YINT) with 10^LEN fblt A14_st |if less, all is ok, go to A14 fbgt fix_ex |if greater, fix and redo fdivs FTEN,%fp0 |if equal, divide by 10 addql #1,%d6 | and inc ILOG bras A14_st | and continue elsewherefix_ex: addql #1,%d6 |increment ILOG by 1 movew #1,%d5 |set ICTR fmovel #rm_mode,%FPCR |set rmode to RM bra A6_str |return to A6 and recompute YINT|| Since ICTR <> 0, we have already been through one adjustment, | and shouldn't have another; this is to check if abs(YINT) = 10^LEN| 10^LEN is again computed using whatever table is in a1 since the| value calculated cannot be inexact.|not_zr: fmoves FONE,%fp2 |init fp2 to 1.0 movel %d4,%d0 |put LEN in d0 clrl %d3 |clr table indexz_loop: lsrl #1,%d0 |shift next bit into carry bccs z_next |if zero, skip the mul fmulx (%a1,%d3),%fp2 |mul by 10**(d3_bit_no)z_next: addl #12,%d3 |inc d3 to next pwrten table entry tstl %d0 |test if LEN is zero bnes z_loop |if not, loop fabsx %fp0 |get abs(YINT) fcmpx %fp2,%fp0 |check if abs(YINT) = 10^LEN fbne A14_st |if not, skip this fdivs FTEN,%fp0 |divide abs(YINT) by 10 addql #1,%d6 |and inc ILOG by 1 addql #1,%d4 | and inc LEN fmuls FTEN,%fp2 | if LEN++, the get 10^^LEN| A14. Convert the mantissa to bcd.| The binstr routine is used to convert the LEN digit | mantissa to bcd in memory. The input to binstr is| to be a fraction; i.e. (mantissa)/10^LEN and adjusted| such that the decimal point is to the left of bit 63.| The bcd digits are stored in the correct position in | the final string area in memory.||| Register usage:| Input/Output| d0: x/LEN call to binstr - final is 0| d1: x/0| d2: x/ms 32-bits of mant of abs(YINT)| d3: x/ls 32-bits of mant of abs(YINT)| d4: LEN/Unchanged| d5: ICTR:LAMBDA/LAMBDA:ICTR| d6: ILOG| d7: k-factor/Unchanged| a0: pointer into memory for packed bcd string formation| /ptr to first mantissa byte in result string| a1: ptr to PTENxx array/Unchanged| a2: ptr to FP_SCR2(a6)/Unchanged| fp0: int portion of Y/abs(YINT) adjusted| fp1: 10^ISCALE/Unchanged| fp2: 10^LEN/Unchanged| F_SCR1:x/Work area for final result| F_SCR2:Y with original exponent/Unchanged| L_SCR1:original USER_FPCR/Unchanged| L_SCR2:first word of X packed/UnchangedA14_st: fmovel #rz_mode,%FPCR |force rz for conversion fdivx %fp2,%fp0 |divide abs(YINT) by 10^LEN leal FP_SCR1(%a6),%a0 fmovex %fp0,(%a0) |move abs(YINT)/10^LEN to memory movel 4(%a0),%d2 |move 2nd word of FP_RES to d2 movel 8(%a0),%d3 |move 3rd word of FP_RES to d3 clrl 4(%a0) |zero word 2 of FP_RES clrl 8(%a0) |zero word 3 of FP_RES movel (%a0),%d0 |move exponent to d0 swap %d0 |put exponent in lower word beqs no_sft |if zero, don't shift subil #0x3ffd,%d0 |sub bias less 2 to make fract tstl %d0 |check if > 1 bgts no_sft |if so, don't shift negl %d0 |make exp positivem_loop: lsrl #1,%d2 |shift d2:d3 right, add 0s roxrl #1,%d3 |the number of places dbf %d0,m_loop |given in d0no_sft: tstl %d2 |check for mantissa of zero bnes no_zr |if not, go on tstl %d3 |continue zero check beqs zer_m |if zero, go directly to binstrno_zr: clrl %d1 |put zero in d1 for addx addil #0x00000080,%d3 |inc at bit 7 addxl %d1,%d2 |continue inc andil #0xffffff80,%d3 |strip off lsb not used by 882zer_m: movel %d4,%d0 |put LEN in d0 for binstr call addql #3,%a0 |a0 points to M16 byte in result bsr binstr |call binstr to convert mant| A15. Convert the exponent to bcd.| As in A14 above, the exp is converted to bcd and the| digits are stored in the final string.|| Digits are stored in L_SCR1(a6) on return from BINDEC as:|| 32 16 15 0| -----------------------------------------| | 0 | e3 | e2 | e1 | e4 | X | X | X || -----------------------------------------|| And are moved into their proper places in FP_SCR1. If digit e4| is non-zero, OPERR is signaled. In all cases, all 4 digits are| written as specified in the 881/882 manual for packed decimal.|| Register usage:| Input/Output| d0: x/LEN call to binstr - final is 0| d1: x/scratch (0);shift count for final exponent packing| d2: x/ms 32-bits of exp fraction/scratch| d3: x/ls 32-bits of exp fraction| d4: LEN/Unchanged| d5: ICTR:LAMBDA/LAMBDA:ICTR| d6: ILOG| d7: k-factor/Unchanged| a0: ptr to result string/ptr to L_SCR1(a6)| a1: ptr to PTENxx array/Unchanged| a2: ptr to FP_SCR2(a6)/Unchanged| fp0: abs(YINT) adjusted/float(ILOG)| fp1: 10^ISCALE/Unchanged| fp2: 10^LEN/Unchanged| F_SCR1:Work area for final result/BCD result| F_SCR2:Y with original exponent/ILOG/10^4| L_SCR1:original USER_FPCR/Exponent digits on return from binstr| L_SCR2:first word of X packed/UnchangedA15_st: tstb BINDEC_FLG(%a6) |check for denorm beqs not_denorm ftstx %fp0 |test for zero fbeq den_zero |if zero, use k-factor or 4933 fmovel %d6,%fp0 |float ILOG fabsx %fp0 |get abs of ILOG bras convrtden_zero: tstl %d7 |check sign of the k-factor blts use_ilog |if negative, use ILOG fmoves F4933,%fp0 |force exponent to 4933 bras convrt |do ituse_ilog: fmovel %d6,%fp0 |float ILOG fabsx %fp0 |get abs of ILOG bras convrtnot_denorm: ftstx %fp0 |test for zero fbne not_zero |if zero, force exponent fmoves FONE,%fp0 |force exponent to 1 bras convrt |do itnot_zero: fmovel %d6,%fp0 |float ILOG fabsx %fp0 |get abs of ILOGconvrt: fdivx 24(%a1),%fp0 |compute ILOG/10^4 fmovex %fp0,FP_SCR2(%a6) |store fp0 in memory movel 4(%a2),%d2 |move word 2 to d2 movel 8(%a2),%d3 |move word 3 to d3 movew (%a2),%d0 |move exp to d0 beqs x_loop_fin |if zero, skip the shift subiw #0x3ffd,%d0 |subtract off bias negw %d0 |make exp positivex_loop: lsrl #1,%d2 |shift d2:d3 right roxrl #1,%d3 |the number of places dbf %d0,x_loop |given in d0x_loop_fin: clrl %d1 |put zero in d1 for addx addil #0x00000080,%d3 |inc at bit 6 addxl %d1,%d2 |continue inc andil #0xffffff80,%d3 |strip off lsb not used by 882 movel #4,%d0 |put 4 in d0 for binstr call leal L_SCR1(%a6),%a0 |a0 is ptr to L_SCR1 for exp digits bsr binstr |call binstr to convert exp movel L_SCR1(%a6),%d0 |load L_SCR1 lword to d0 movel #12,%d1 |use d1 for shift count lsrl %d1,%d0 |shift d0 right by 12 bfins %d0,FP_SCR1(%a6){#4:#12} |put e3:e2:e1 in FP_SCR1 lsrl %d1,%d0 |shift d0 right by 12 bfins %d0,FP_SCR1(%a6){#16:#4} |put e4 in FP_SCR1 tstb %d0 |check if e4 is zero beqs A16_st |if zero, skip rest orl #opaop_mask,USER_FPSR(%a6) |set OPERR & AIOP in USER_FPSR| A16. Write sign bits to final string.| Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).|| Register usage:| Input/Output| d0: x/scratch - final is x| d2: x/x| d3: x/x| d4: LEN/Unchanged| d5: ICTR:LAMBDA/LAMBDA:ICTR| d6: ILOG/ILOG adjusted| d7: k-factor/Unchanged| a0: ptr to L_SCR1(a6)/Unchanged| a1: ptr to PTENxx array/Unchanged| a2: ptr to FP_SCR2(a6)/Unchanged| fp0: float(ILOG)/Unchanged| fp1: 10^ISCALE/Unchanged| fp2: 10^LEN/Unchanged| F_SCR1:BCD result with correct signs| F_SCR2:ILOG/10^4| L_SCR1:Exponent digits on return from binstr| L_SCR2:first word of X packed/UnchangedA16_st: clrl %d0 |clr d0 for collection of signs andib #0x0f,FP_SCR1(%a6) |clear first nibble of FP_SCR1 tstl L_SCR2(%a6) |check sign of original mantissa bges mant_p |if pos, don't set SM moveql #2,%d0 |move 2 in to d0 for SMmant_p: tstl %d6 |check sign of ILOG bges wr_sgn |if pos, don't set SE addql #1,%d0 |set bit 0 in d0 for SE wr_sgn: bfins %d0,FP_SCR1(%a6){#0:#2} |insert SM and SE into FP_SCR1| Clean up and restore all registers used. fmovel #0,%FPSR |clear possible inex2/ainex bits fmovemx (%a7)+,%fp0-%fp2 moveml (%a7)+,%d2-%d7/%a2 rts |end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -