📄 bindec.s
字号:
// 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 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 + -