📄 bindec.s
字号:
fmovel #rz_mode,fpcr | set RZ rounding mode| A9. Scale X -> Y.| The mantissa is scaled to the desired number of significant| digits. The excess digits are collected in INEX2. If mul,| Check d2 for excess 10 exponential value. If not zero,| the iscale value would have caused the __x_pwrten calculation| to overflow. Only a negative iscale can cause this, so| multiply by d2@(10^), which is now only allowed to be 24,| with a multiply by 10^8 and 10^16, which is exact since| 10^24 is exact. If the input was denormalized, we must| create a busy stack frame with the mul command and the| two operands, and allow the fpu to complete the multiply.|| 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 __x_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 0x3fff 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 jne __x_sc_mul | if neg (LAMBDA = 0), scale by mul fdivx fp1,fp0 | calculate X / SCALE -> Y to fp0 jra __A10_st | branch to A10__x_sc_mul: tstb a6@(BINDEC_FLG) | check for denorm jeq A9_norm | if norm, continue with mul fmovemx fp1-fp1,a7@- | load ETEMP with 10^ISCALE movel a0@(8),a7@- | load FPTEMP with input arg movel a0@(4),a7@- movel a0@,a7@- movel #18,d3 | load count for busy stackA9_loop: clrl a7@- | clear lword on stack dbf d3,A9_loop moveb a6@(VER_TMP),a7@ | write current version number moveb #BUSY_SIZE-4,a7@(1) | write current busy size moveb #0x10,a7@(0x44) | set fcefpte[15] bit movew #0x0023,a7@(0x40) | load cmdreg1b with mul command moveb #0xfe,a7@(0x8) | load all 1s to cu savepc frestore a7@+ | restore frame to fpu for completion fmulx a1@(36),fp0 | multiply fp0 by 10^8 fmulx a1@(48),fp0 | multiply fp0 by 10^16 jra __A10_stA9_norm: tstw d2 | test for small exp case jeq A9_con | if zero, continue as normal fmulx a1@(36),fp0 | multiply fp0 by 10^8 fmulx a1@(48),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 occured. 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 a6@(FP_SCR2)| fp0: Y/Y with lsb adjusted| fp1: 10^ISCALE/Unchanged| fp2: x/x__A10_st: fmovel FPSR,d0 | get FPSR fmovex fp0,a6@(FP_SCR2) | move Y to memory lea a6@(FP_SCR2),a2 | load a2 with ptr to FP_SCR2 btst #9,d0 | check if INEX2 set jeq __A11_st | if clear, skip rest oril #1,a2@(8) | or in 1 to lsb of mantissa fmovex a6@(FP_SCR2),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 __x_sintdo entry point in the __x_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 a6@(USER_FPCR),a6@(L_SCR1) | save it for later andil #0x00000030,a6@(USER_FPCR) | set size to ext,| | block exceptions/* | A12. Calculate YINT = FINT(Y) according to user's rounding mode. */| The FPSP routine __x_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 __x_sintdo| a1: ptr to PTENxx array/Unchanged| a2: ptr to a6@(FP_SCR2)/Unchanged| a6: temp pointer to a6@(FP_SCR2) - 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/Unchanged__A12_st: moveml d0-d1/a0-a1,a7@- | save regs used by __x_sintd0 movel a6@(L_SCR1),a7@- movel a6@(L_SCR2),a7@- lea a6@(FP_SCR2),a0 | a0 is ptr to a6@(F_SCR2) fmovex fp0,a0@ | move Y to memory at a6@(FP_SCR2) tstl a6@(L_SCR2) | test sign of original operand jge do_fint | if pos, use Y orl #0x80000000,a0@ | if neg, use -Ydo_fint: movel a6@(USER_FPSR),a7@- bsrl __x_sintdo | sint routine returns int in fp0 moveb a7@,a6@(USER_FPSR) addl #4,a7 movel a7@+,a6@(L_SCR2) movel a7@+,a6@(L_SCR1) moveml a7@+,d0-d1/a0-a1 | restore regs used by __x_sint movel a6@(L_SCR2),a6@(FP_SCR2) | restore original exponent movel a6@(L_SCR1),a6@(USER_FPCR) /* | 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 a6@(FP_SCR2)/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/Unchanged__A13_st: swap d5 | put ICTR in lower word of d5 tstw d5 | check if ICTR = 0 jne 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 jcc 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 __x_pwrten table entry tstl d0 | test if LEN is zero jne 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 a6@(BINDEC_FLG) | check if input was norm jeq __A13_con | if norm, continue with checking fabsx fp0 | take abs of YINT jra 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 jra __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 jra __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 jra __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 jcc 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 __x_pwrten table entry tstl d0 | test if LEN is zero jne 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 __x_binstr routine is used to convert the LEN digit| mantissa to bcd in memory. The input to __x_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 __x_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 a6@(FP_SCR2)/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/Unchanged__A14_st: fmovel #rz_mode,fpcr | force rz for conversion fdivx fp2,fp0 | divide abs(YINT) by 10^LEN lea a6@(FP_SCR1),a0 fmovex fp0,a0@ | move abs(YINT)/10^LEN to memory movel a0@(4),d2 | move 2nd word of FP_RES to d2 movel a0@(8),d3 | move 3rd word of FP_RES to d3 clrl a0@(4) | zero word 2 of FP_RES clrl a0@(8) | zero word 3 of FP_RES movel a0@,d0 | move exponent to d0 swap d0 | put exponent in lower word jeq no_sft /* | if zero, don't shift */ subil #0x3ffd,d0 | sub bias less 2 to make fract tstl d0 | check if > 1 jgt 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 jne no_zr | if not, go on tstl d3 | continue zero check jeq zer_m | if zero, go directly to __x_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 __x_binstr call addql #3,a0 | a0 points to M16 byte in result bsrl __x_binstr | call __x_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 a6@(L_SCR1) 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 __x_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 a6@(L_SCR1)| a1: ptr to PTENxx array/Unchanged| a2: ptr to a6@(FP_SCR2)/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 __x_binstr| L_SCR2:first word of X packed/Unchanged__A15_st: tstb a6@(BINDEC_FLG) | check for denorm jeq 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 jra convrtden_zero: tstl d7 | check sign of the k-factor jlt use_ilog | if negative, use ILOG fmoves F4933,fp0 | force exponent to 4933 jra convrt | do ituse_ilog: fmovel d6,fp0 | float ILOG fabsx fp0 | get abs of ILOG jra convrtnot_denorm: ftstx fp0 | test for zero fbne not_zero | if zero, force exponent fmoves FONE,fp0 | force exponent to 1 jra convrt | do itnot_zero: fmovel d6,fp0 | float ILOG fabsx fp0 | get abs of ILOGconvrt: fdivx a1@(24),fp0 | compute ILOG/10^4 fmovex fp0,a6@(FP_SCR2) | store fp0 in memory movel a2@(4),d2 | move word 2 to d2 movel a2@(8),d3 | move word 3 to d3 movew a2@,d0 | move exp to d0 jeq 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 __x_binstr call lea a6@(L_SCR1),a0 | a0 is ptr to L_SCR1 for exp digits bsrl __x_binstr | call __x_binstr to convert exp movel a6@(L_SCR1),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,a6@(FP_SCR1){#4:#12} | put e3:e2:e1 in FP_SCR1 lsrl d1,d0 | shift d0 right by 12 bfins d0,a6@(FP_SCR1){#16:#4} | put e4 in FP_SCR1 tstb d0 | check if e4 is zero jeq __A16_st | if zero, skip rest orl #opaop_mask,a6@(USER_FPSR) | 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 a6@(L_SCR1)/Unchanged| a1: ptr to PTENxx array/Unchanged| a2: ptr to a6@(FP_SCR2)/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 __x_binstr| L_SCR2:first word of X packed/Unchanged__A16_st: clrl d0 | clr d0 for collection of signs andib #0x0f,a6@(FP_SCR1) | clear first nibble of FP_SCR1 tstl a6@(L_SCR2) | check sign of original mantissa jge 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 jge wr_sgn /* | if pos, don't set SE */ addql #1,d0 | set bit 0 in d0 for SEwr_sgn: bfins d0,a6@(FP_SCR1){#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 + -