1*c869df6aSbriggs* $NetBSD: bindec.sa,v 1.5 2001/12/09 01:43:13 briggs Exp $ 257fb77a1Scgd 322ef5fa9Smycroft* MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 422ef5fa9Smycroft* M68000 Hi-Performance Microprocessor Division 522ef5fa9Smycroft* M68040 Software Package 622ef5fa9Smycroft* 722ef5fa9Smycroft* M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc. 822ef5fa9Smycroft* All rights reserved. 922ef5fa9Smycroft* 1022ef5fa9Smycroft* THE SOFTWARE is provided on an "AS IS" basis and without warranty. 1122ef5fa9Smycroft* To the maximum extent permitted by applicable law, 1222ef5fa9Smycroft* MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 1322ef5fa9Smycroft* INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 1422ef5fa9Smycroft* PARTICULAR PURPOSE and any warranty against infringement with 1522ef5fa9Smycroft* regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) 1622ef5fa9Smycroft* and any accompanying written materials. 1722ef5fa9Smycroft* 1822ef5fa9Smycroft* To the maximum extent permitted by applicable law, 1922ef5fa9Smycroft* IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 2022ef5fa9Smycroft* (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS 2122ef5fa9Smycroft* PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR 2222ef5fa9Smycroft* OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE 2322ef5fa9Smycroft* SOFTWARE. Motorola assumes no responsibility for the maintenance 2422ef5fa9Smycroft* and support of the SOFTWARE. 2522ef5fa9Smycroft* 2622ef5fa9Smycroft* You are hereby granted a copyright license to use, modify, and 2722ef5fa9Smycroft* distribute the SOFTWARE so long as this entire notice is retained 2822ef5fa9Smycroft* without alteration in any modified and/or redistributed versions, 2922ef5fa9Smycroft* and that such modified versions are clearly identified as such. 3022ef5fa9Smycroft* No licenses are granted by implication, estoppel or otherwise 3122ef5fa9Smycroft* under any patents or trademarks of Motorola, Inc. 3222ef5fa9Smycroft 3322ef5fa9Smycroft* 3422ef5fa9Smycroft* bindec.sa 3.4 1/3/91 3522ef5fa9Smycroft* 3622ef5fa9Smycroft* bindec 3722ef5fa9Smycroft* 3822ef5fa9Smycroft* Description: 3922ef5fa9Smycroft* Converts an input in extended precision format 4022ef5fa9Smycroft* to bcd format. 4122ef5fa9Smycroft* 4222ef5fa9Smycroft* Input: 4322ef5fa9Smycroft* a0 points to the input extended precision value 4422ef5fa9Smycroft* value in memory; d0 contains the k-factor sign-extended 4522ef5fa9Smycroft* to 32-bits. The input may be either normalized, 4622ef5fa9Smycroft* unnormalized, or denormalized. 4722ef5fa9Smycroft* 4822ef5fa9Smycroft* Output: result in the FP_SCR1 space on the stack. 4922ef5fa9Smycroft* 5022ef5fa9Smycroft* Saves and Modifies: D2-D7,A2,FP2 5122ef5fa9Smycroft* 5222ef5fa9Smycroft* Algorithm: 5322ef5fa9Smycroft* 5422ef5fa9Smycroft* A1. Set RM and size ext; Set SIGMA = sign of input. 5522ef5fa9Smycroft* The k-factor is saved for use in d7. Clear the 5622ef5fa9Smycroft* BINDEC_FLG for separating normalized/denormalized 5722ef5fa9Smycroft* input. If input is unnormalized or denormalized, 5822ef5fa9Smycroft* normalize it. 5922ef5fa9Smycroft* 6022ef5fa9Smycroft* A2. Set X = abs(input). 6122ef5fa9Smycroft* 6222ef5fa9Smycroft* A3. Compute ILOG. 6322ef5fa9Smycroft* ILOG is the log base 10 of the input value. It is 6422ef5fa9Smycroft* approximated by adding e + 0.f when the original 6522ef5fa9Smycroft* value is viewed as 2^^e * 1.f in extended precision. 6622ef5fa9Smycroft* This value is stored in d6. 6722ef5fa9Smycroft* 6822ef5fa9Smycroft* A4. Clr INEX bit. 6922ef5fa9Smycroft* The operation in A3 above may have set INEX2. 7022ef5fa9Smycroft* 7122ef5fa9Smycroft* A5. Set ICTR = 0; 7222ef5fa9Smycroft* ICTR is a flag used in A13. It must be set before the 7322ef5fa9Smycroft* loop entry A6. 7422ef5fa9Smycroft* 7522ef5fa9Smycroft* A6. Calculate LEN. 7622ef5fa9Smycroft* LEN is the number of digits to be displayed. The 7722ef5fa9Smycroft* k-factor can dictate either the total number of digits, 7822ef5fa9Smycroft* if it is a positive number, or the number of digits 7922ef5fa9Smycroft* after the decimal point which are to be included as 8022ef5fa9Smycroft* significant. See the 68882 manual for examples. 8122ef5fa9Smycroft* If LEN is computed to be greater than 17, set OPERR in 8222ef5fa9Smycroft* USER_FPSR. LEN is stored in d4. 8322ef5fa9Smycroft* 8422ef5fa9Smycroft* A7. Calculate SCALE. 8522ef5fa9Smycroft* SCALE is equal to 10^ISCALE, where ISCALE is the number 8622ef5fa9Smycroft* of decimal places needed to insure LEN integer digits 8722ef5fa9Smycroft* in the output before conversion to bcd. LAMBDA is the 8822ef5fa9Smycroft* sign of ISCALE, used in A9. Fp1 contains 8922ef5fa9Smycroft* 10^^(abs(ISCALE)) using a rounding mode which is a 9022ef5fa9Smycroft* function of the original rounding mode and the signs 9122ef5fa9Smycroft* of ISCALE and X. A table is given in the code. 9222ef5fa9Smycroft* 9322ef5fa9Smycroft* A8. Clr INEX; Force RZ. 9422ef5fa9Smycroft* The operation in A3 above may have set INEX2. 9522ef5fa9Smycroft* RZ mode is forced for the scaling operation to insure 9622ef5fa9Smycroft* only one rounding error. The grs bits are collected in 9722ef5fa9Smycroft* the INEX flag for use in A10. 9822ef5fa9Smycroft* 9922ef5fa9Smycroft* A9. Scale X -> Y. 10022ef5fa9Smycroft* The mantissa is scaled to the desired number of 10122ef5fa9Smycroft* significant digits. The excess digits are collected 10222ef5fa9Smycroft* in INEX2. 10322ef5fa9Smycroft* 10422ef5fa9Smycroft* A10. Or in INEX. 105456dff6cSwiz* If INEX is set, round error occurred. This is 10622ef5fa9Smycroft* compensated for by 'or-ing' in the INEX2 flag to 10722ef5fa9Smycroft* the lsb of Y. 10822ef5fa9Smycroft* 10922ef5fa9Smycroft* A11. Restore original FPCR; set size ext. 11022ef5fa9Smycroft* Perform FINT operation in the user's rounding mode. 11122ef5fa9Smycroft* Keep the size to extended. 11222ef5fa9Smycroft* 11322ef5fa9Smycroft* A12. Calculate YINT = FINT(Y) according to user's rounding 11422ef5fa9Smycroft* mode. The FPSP routine sintd0 is used. The output 11522ef5fa9Smycroft* is in fp0. 11622ef5fa9Smycroft* 11722ef5fa9Smycroft* A13. Check for LEN digits. 11822ef5fa9Smycroft* If the int operation results in more than LEN digits, 11922ef5fa9Smycroft* or less than LEN -1 digits, adjust ILOG and repeat from 12022ef5fa9Smycroft* A6. This test occurs only on the first pass. If the 12122ef5fa9Smycroft* result is exactly 10^LEN, decrement ILOG and divide 12222ef5fa9Smycroft* the mantissa by 10. 12322ef5fa9Smycroft* 12422ef5fa9Smycroft* A14. Convert the mantissa to bcd. 12522ef5fa9Smycroft* The binstr routine is used to convert the LEN digit 12622ef5fa9Smycroft* mantissa to bcd in memory. The input to binstr is 12722ef5fa9Smycroft* to be a fraction; i.e. (mantissa)/10^LEN and adjusted 12822ef5fa9Smycroft* such that the decimal point is to the left of bit 63. 12922ef5fa9Smycroft* The bcd digits are stored in the correct position in 13022ef5fa9Smycroft* the final string area in memory. 13122ef5fa9Smycroft* 13222ef5fa9Smycroft* A15. Convert the exponent to bcd. 13322ef5fa9Smycroft* As in A14 above, the exp is converted to bcd and the 13422ef5fa9Smycroft* digits are stored in the final string. 13522ef5fa9Smycroft* Test the length of the final exponent string. If the 13622ef5fa9Smycroft* length is 4, set operr. 13722ef5fa9Smycroft* 13822ef5fa9Smycroft* A16. Write sign bits to final string. 13922ef5fa9Smycroft* 14022ef5fa9Smycroft* Implementation Notes: 14122ef5fa9Smycroft* 14222ef5fa9Smycroft* The registers are used as follows: 14322ef5fa9Smycroft* 14422ef5fa9Smycroft* d0: scratch; LEN input to binstr 14522ef5fa9Smycroft* d1: scratch 14622ef5fa9Smycroft* d2: upper 32-bits of mantissa for binstr 14722ef5fa9Smycroft* d3: scratch;lower 32-bits of mantissa for binstr 14822ef5fa9Smycroft* d4: LEN 14922ef5fa9Smycroft* d5: LAMBDA/ICTR 15022ef5fa9Smycroft* d6: ILOG 15122ef5fa9Smycroft* d7: k-factor 15222ef5fa9Smycroft* a0: ptr for original operand/final result 15322ef5fa9Smycroft* a1: scratch pointer 15422ef5fa9Smycroft* a2: pointer to FP_X; abs(original value) in ext 15522ef5fa9Smycroft* fp0: scratch 15622ef5fa9Smycroft* fp1: scratch 15722ef5fa9Smycroft* fp2: scratch 15822ef5fa9Smycroft* F_SCR1: 15922ef5fa9Smycroft* F_SCR2: 16022ef5fa9Smycroft* L_SCR1: 16122ef5fa9Smycroft* L_SCR2: 16222ef5fa9Smycroft* 16322ef5fa9Smycroft 16422ef5fa9SmycroftBINDEC IDNT 2,1 Motorola 040 Floating Point Software Package 16522ef5fa9Smycroft 16622ef5fa9Smycroft include fpsp.h 16722ef5fa9Smycroft 16822ef5fa9Smycroft section 8 16922ef5fa9Smycroft 17022ef5fa9Smycroft* Constants in extended precision 17122ef5fa9SmycroftLOG2 dc.l $3FFD0000,$9A209A84,$FBCFF798,$00000000 17222ef5fa9SmycroftLOG2UP1 dc.l $3FFD0000,$9A209A84,$FBCFF799,$00000000 17322ef5fa9Smycroft 17422ef5fa9Smycroft* Constants in single precision 17522ef5fa9SmycroftFONE dc.l $3F800000,$00000000,$00000000,$00000000 17622ef5fa9SmycroftFTWO dc.l $40000000,$00000000,$00000000,$00000000 17722ef5fa9SmycroftFTEN dc.l $41200000,$00000000,$00000000,$00000000 17822ef5fa9SmycroftF4933 dc.l $459A2800,$00000000,$00000000,$00000000 17922ef5fa9Smycroft 18022ef5fa9SmycroftRBDTBL dc.b 0,0,0,0 18122ef5fa9Smycroft dc.b 3,3,2,2 18222ef5fa9Smycroft dc.b 3,2,2,3 18322ef5fa9Smycroft dc.b 2,3,3,2 18422ef5fa9Smycroft 18522ef5fa9Smycroft xref binstr 18622ef5fa9Smycroft xref sintdo 18722ef5fa9Smycroft xref ptenrn,ptenrm,ptenrp 18822ef5fa9Smycroft 18922ef5fa9Smycroft xdef bindec 19022ef5fa9Smycroft xdef sc_mul 19122ef5fa9Smycroftbindec: 19222ef5fa9Smycroft movem.l d2-d7/a2,-(a7) 19322ef5fa9Smycroft fmovem.x fp0-fp2,-(a7) 19422ef5fa9Smycroft 19522ef5fa9Smycroft* A1. Set RM and size ext. Set SIGMA = sign input; 19622ef5fa9Smycroft* The k-factor is saved for use in d7. Clear BINDEC_FLG for 19722ef5fa9Smycroft* separating normalized/denormalized input. If the input 19822ef5fa9Smycroft* is a denormalized number, set the BINDEC_FLG memory word 19922ef5fa9Smycroft* to signal denorm. If the input is unnormalized, normalize 20022ef5fa9Smycroft* the input and test for denormalized result. 20122ef5fa9Smycroft* 20222ef5fa9Smycroft fmove.l #rm_mode,FPCR ;set RM and ext 20322ef5fa9Smycroft move.l (a0),L_SCR2(a6) ;save exponent for sign check 20422ef5fa9Smycroft move.l d0,d7 ;move k-factor to d7 20522ef5fa9Smycroft clr.b BINDEC_FLG(a6) ;clr norm/denorm flag 20622ef5fa9Smycroft move.w STAG(a6),d0 ;get stag 20722ef5fa9Smycroft andi.w #$e000,d0 ;isolate stag bits 20822ef5fa9Smycroft beq A2_str ;if zero, input is norm 20922ef5fa9Smycroft* 21022ef5fa9Smycroft* Normalize the denorm 21122ef5fa9Smycroft* 21222ef5fa9Smycroftun_de_norm: 21322ef5fa9Smycroft move.w (a0),d0 21422ef5fa9Smycroft andi.w #$7fff,d0 ;strip sign of normalized exp 21522ef5fa9Smycroft move.l 4(a0),d1 21622ef5fa9Smycroft move.l 8(a0),d2 21722ef5fa9Smycroftnorm_loop: 21822ef5fa9Smycroft sub.w #1,d0 219eddb30abSmycroft add.l d2,d2 220eddb30abSmycroft addx.l d1,d1 22122ef5fa9Smycroft tst.l d1 22222ef5fa9Smycroft bge.b norm_loop 22322ef5fa9Smycroft* 22422ef5fa9Smycroft* Test if the normalized input is denormalized 22522ef5fa9Smycroft* 22622ef5fa9Smycroft tst.w d0 22722ef5fa9Smycroft bgt.b pos_exp ;if greater than zero, it is a norm 22822ef5fa9Smycroft st BINDEC_FLG(a6) ;set flag for denorm 22922ef5fa9Smycroftpos_exp: 23022ef5fa9Smycroft andi.w #$7fff,d0 ;strip sign of normalized exp 23122ef5fa9Smycroft move.w d0,(a0) 23222ef5fa9Smycroft move.l d1,4(a0) 23322ef5fa9Smycroft move.l d2,8(a0) 23422ef5fa9Smycroft 23522ef5fa9Smycroft* A2. Set X = abs(input). 23622ef5fa9Smycroft* 23722ef5fa9SmycroftA2_str: 23822ef5fa9Smycroft move.l (a0),FP_SCR2(a6) ; move input to work space 23922ef5fa9Smycroft move.l 4(a0),FP_SCR2+4(a6) ; move input to work space 24022ef5fa9Smycroft move.l 8(a0),FP_SCR2+8(a6) ; move input to work space 24122ef5fa9Smycroft andi.l #$7fffffff,FP_SCR2(a6) ;create abs(X) 24222ef5fa9Smycroft 24322ef5fa9Smycroft* A3. Compute ILOG. 24422ef5fa9Smycroft* ILOG is the log base 10 of the input value. It is approx- 24522ef5fa9Smycroft* imated by adding e + 0.f when the original value is viewed 24622ef5fa9Smycroft* as 2^^e * 1.f in extended precision. This value is stored 24722ef5fa9Smycroft* in d6. 24822ef5fa9Smycroft* 24922ef5fa9Smycroft* Register usage: 25022ef5fa9Smycroft* Input/Output 25122ef5fa9Smycroft* d0: k-factor/exponent 25222ef5fa9Smycroft* d2: x/x 25322ef5fa9Smycroft* d3: x/x 25422ef5fa9Smycroft* d4: x/x 25522ef5fa9Smycroft* d5: x/x 25622ef5fa9Smycroft* d6: x/ILOG 25722ef5fa9Smycroft* d7: k-factor/Unchanged 25822ef5fa9Smycroft* a0: ptr for original operand/final result 25922ef5fa9Smycroft* a1: x/x 26022ef5fa9Smycroft* a2: x/x 26122ef5fa9Smycroft* fp0: x/float(ILOG) 26222ef5fa9Smycroft* fp1: x/x 26322ef5fa9Smycroft* fp2: x/x 26422ef5fa9Smycroft* F_SCR1:x/x 26522ef5fa9Smycroft* F_SCR2:Abs(X)/Abs(X) with $3fff exponent 26622ef5fa9Smycroft* L_SCR1:x/x 26722ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 26822ef5fa9Smycroft 26922ef5fa9Smycroft tst.b BINDEC_FLG(a6) ;check for denorm 27022ef5fa9Smycroft beq.b A3_cont ;if clr, continue with norm 27122ef5fa9Smycroft move.l #-4933,d6 ;force ILOG = -4933 27222ef5fa9Smycroft bra.b A4_str 27322ef5fa9SmycroftA3_cont: 27422ef5fa9Smycroft move.w FP_SCR2(a6),d0 ;move exp to d0 27522ef5fa9Smycroft move.w #$3fff,FP_SCR2(a6) ;replace exponent with 0x3fff 27622ef5fa9Smycroft fmove.x FP_SCR2(a6),fp0 ;now fp0 has 1.f 27722ef5fa9Smycroft sub.w #$3fff,d0 ;strip off bias 27822ef5fa9Smycroft fadd.w d0,fp0 ;add in exp 27922ef5fa9Smycroft fsub.s FONE,fp0 ;subtract off 1.0 28022ef5fa9Smycroft fbge.w pos_res ;if pos, branch 28122ef5fa9Smycroft fmul.x LOG2UP1,fp0 ;if neg, mul by LOG2UP1 28222ef5fa9Smycroft fmove.l fp0,d6 ;put ILOG in d6 as a lword 28322ef5fa9Smycroft bra.b A4_str ;go move out ILOG 28422ef5fa9Smycroftpos_res: 28522ef5fa9Smycroft fmul.x LOG2,fp0 ;if pos, mul by LOG2 28622ef5fa9Smycroft fmove.l fp0,d6 ;put ILOG in d6 as a lword 28722ef5fa9Smycroft 28822ef5fa9Smycroft 28922ef5fa9Smycroft* A4. Clr INEX bit. 29022ef5fa9Smycroft* The operation in A3 above may have set INEX2. 29122ef5fa9Smycroft 29222ef5fa9SmycroftA4_str: 29322ef5fa9Smycroft fmove.l #0,FPSR ;zero all of fpsr - nothing needed 29422ef5fa9Smycroft 29522ef5fa9Smycroft 29622ef5fa9Smycroft* A5. Set ICTR = 0; 29722ef5fa9Smycroft* ICTR is a flag used in A13. It must be set before the 29822ef5fa9Smycroft* loop entry A6. The lower word of d5 is used for ICTR. 29922ef5fa9Smycroft 30022ef5fa9Smycroft clr.w d5 ;clear ICTR 30122ef5fa9Smycroft 30222ef5fa9Smycroft 30322ef5fa9Smycroft* A6. Calculate LEN. 30422ef5fa9Smycroft* LEN is the number of digits to be displayed. The k-factor 30522ef5fa9Smycroft* can dictate either the total number of digits, if it is 30622ef5fa9Smycroft* a positive number, or the number of digits after the 30722ef5fa9Smycroft* original decimal point which are to be included as 30822ef5fa9Smycroft* significant. See the 68882 manual for examples. 30922ef5fa9Smycroft* If LEN is computed to be greater than 17, set OPERR in 31022ef5fa9Smycroft* USER_FPSR. LEN is stored in d4. 31122ef5fa9Smycroft* 31222ef5fa9Smycroft* Register usage: 31322ef5fa9Smycroft* Input/Output 31422ef5fa9Smycroft* d0: exponent/Unchanged 31522ef5fa9Smycroft* d2: x/x/scratch 31622ef5fa9Smycroft* d3: x/x 31722ef5fa9Smycroft* d4: exc picture/LEN 31822ef5fa9Smycroft* d5: ICTR/Unchanged 31922ef5fa9Smycroft* d6: ILOG/Unchanged 32022ef5fa9Smycroft* d7: k-factor/Unchanged 32122ef5fa9Smycroft* a0: ptr for original operand/final result 32222ef5fa9Smycroft* a1: x/x 32322ef5fa9Smycroft* a2: x/x 32422ef5fa9Smycroft* fp0: float(ILOG)/Unchanged 32522ef5fa9Smycroft* fp1: x/x 32622ef5fa9Smycroft* fp2: x/x 32722ef5fa9Smycroft* F_SCR1:x/x 32822ef5fa9Smycroft* F_SCR2:Abs(X) with $3fff exponent/Unchanged 32922ef5fa9Smycroft* L_SCR1:x/x 33022ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 33122ef5fa9Smycroft 33222ef5fa9SmycroftA6_str: 33322ef5fa9Smycroft tst.l d7 ;branch on sign of k 33422ef5fa9Smycroft ble.b k_neg ;if k <= 0, LEN = ILOG + 1 - k 33522ef5fa9Smycroft move.l d7,d4 ;if k > 0, LEN = k 33622ef5fa9Smycroft bra.b len_ck ;skip to LEN check 33722ef5fa9Smycroftk_neg: 33822ef5fa9Smycroft move.l d6,d4 ;first load ILOG to d4 33922ef5fa9Smycroft sub.l d7,d4 ;subtract off k 34022ef5fa9Smycroft addq.l #1,d4 ;add in the 1 34122ef5fa9Smycroftlen_ck: 34222ef5fa9Smycroft tst.l d4 ;LEN check: branch on sign of LEN 34322ef5fa9Smycroft ble.b LEN_ng ;if neg, set LEN = 1 34422ef5fa9Smycroft cmp.l #17,d4 ;test if LEN > 17 34522ef5fa9Smycroft ble.b A7_str ;if not, forget it 34622ef5fa9Smycroft move.l #17,d4 ;set max LEN = 17 34722ef5fa9Smycroft tst.l d7 ;if negative, never set OPERR 34822ef5fa9Smycroft ble.b A7_str ;if positive, continue 34922ef5fa9Smycroft or.l #opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR 35022ef5fa9Smycroft bra.b A7_str ;finished here 35122ef5fa9SmycroftLEN_ng: 35222ef5fa9Smycroft moveq.l #1,d4 ;min LEN is 1 35322ef5fa9Smycroft 35422ef5fa9Smycroft 35522ef5fa9Smycroft* A7. Calculate SCALE. 35622ef5fa9Smycroft* SCALE is equal to 10^ISCALE, where ISCALE is the number 35722ef5fa9Smycroft* of decimal places needed to insure LEN integer digits 35822ef5fa9Smycroft* in the output before conversion to bcd. LAMBDA is the sign 35922ef5fa9Smycroft* of ISCALE, used in A9. Fp1 contains 10^^(abs(ISCALE)) using 36022ef5fa9Smycroft* the rounding mode as given in the following table (see 36122ef5fa9Smycroft* Coonen, p. 7.23 as ref.; however, the SCALE variable is 36222ef5fa9Smycroft* of opposite sign in bindec.sa from Coonen). 36322ef5fa9Smycroft* 36422ef5fa9Smycroft* Initial USE 36522ef5fa9Smycroft* FPCR[6:5] LAMBDA SIGN(X) FPCR[6:5] 36622ef5fa9Smycroft* ---------------------------------------------- 36722ef5fa9Smycroft* RN 00 0 0 00/0 RN 36822ef5fa9Smycroft* RN 00 0 1 00/0 RN 36922ef5fa9Smycroft* RN 00 1 0 00/0 RN 37022ef5fa9Smycroft* RN 00 1 1 00/0 RN 37122ef5fa9Smycroft* RZ 01 0 0 11/3 RP 37222ef5fa9Smycroft* RZ 01 0 1 11/3 RP 37322ef5fa9Smycroft* RZ 01 1 0 10/2 RM 37422ef5fa9Smycroft* RZ 01 1 1 10/2 RM 37522ef5fa9Smycroft* RM 10 0 0 11/3 RP 37622ef5fa9Smycroft* RM 10 0 1 10/2 RM 37722ef5fa9Smycroft* RM 10 1 0 10/2 RM 37822ef5fa9Smycroft* RM 10 1 1 11/3 RP 37922ef5fa9Smycroft* RP 11 0 0 10/2 RM 38022ef5fa9Smycroft* RP 11 0 1 11/3 RP 38122ef5fa9Smycroft* RP 11 1 0 11/3 RP 38222ef5fa9Smycroft* RP 11 1 1 10/2 RM 38322ef5fa9Smycroft* 38422ef5fa9Smycroft* Register usage: 38522ef5fa9Smycroft* Input/Output 38622ef5fa9Smycroft* d0: exponent/scratch - final is 0 38722ef5fa9Smycroft* d2: x/0 or 24 for A9 38822ef5fa9Smycroft* d3: x/scratch - offset ptr into PTENRM array 38922ef5fa9Smycroft* d4: LEN/Unchanged 39022ef5fa9Smycroft* d5: 0/ICTR:LAMBDA 39122ef5fa9Smycroft* d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k)) 39222ef5fa9Smycroft* d7: k-factor/Unchanged 39322ef5fa9Smycroft* a0: ptr for original operand/final result 39422ef5fa9Smycroft* a1: x/ptr to PTENRM array 39522ef5fa9Smycroft* a2: x/x 39622ef5fa9Smycroft* fp0: float(ILOG)/Unchanged 39722ef5fa9Smycroft* fp1: x/10^ISCALE 39822ef5fa9Smycroft* fp2: x/x 39922ef5fa9Smycroft* F_SCR1:x/x 40022ef5fa9Smycroft* F_SCR2:Abs(X) with $3fff exponent/Unchanged 40122ef5fa9Smycroft* L_SCR1:x/x 40222ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 40322ef5fa9Smycroft 40422ef5fa9SmycroftA7_str: 40522ef5fa9Smycroft tst.l d7 ;test sign of k 40622ef5fa9Smycroft bgt.b k_pos ;if pos and > 0, skip this 40722ef5fa9Smycroft cmp.l d6,d7 ;test k - ILOG 40822ef5fa9Smycroft blt.b k_pos ;if ILOG >= k, skip this 40922ef5fa9Smycroft move.l d7,d6 ;if ((k<0) & (ILOG < k)) ILOG = k 41022ef5fa9Smycroftk_pos: 41122ef5fa9Smycroft move.l d6,d0 ;calc ILOG + 1 - LEN in d0 41222ef5fa9Smycroft addq.l #1,d0 ;add the 1 41322ef5fa9Smycroft sub.l d4,d0 ;sub off LEN 41422ef5fa9Smycroft swap d5 ;use upper word of d5 for LAMBDA 41522ef5fa9Smycroft clr.w d5 ;set it zero initially 41622ef5fa9Smycroft clr.w d2 ;set up d2 for very small case 41722ef5fa9Smycroft tst.l d0 ;test sign of ISCALE 41822ef5fa9Smycroft bge.b iscale ;if pos, skip next inst 41922ef5fa9Smycroft addq.w #1,d5 ;if neg, set LAMBDA true 42022ef5fa9Smycroft cmp.l #$ffffecd4,d0 ;test iscale <= -4908 42122ef5fa9Smycroft bgt.b no_inf ;if false, skip rest 42222ef5fa9Smycroft addi.l #24,d0 ;add in 24 to iscale 42322ef5fa9Smycroft move.l #24,d2 ;put 24 in d2 for A9 42422ef5fa9Smycroftno_inf: 42522ef5fa9Smycroft neg.l d0 ;and take abs of ISCALE 42622ef5fa9Smycroftiscale: 42722ef5fa9Smycroft fmove.s FONE,fp1 ;init fp1 to 1 42822ef5fa9Smycroft bfextu USER_FPCR(a6){26:2},d1 ;get initial rmode bits 429eddb30abSmycroft add.w d1,d1 ;put them in bits 2:1 43022ef5fa9Smycroft add.w d5,d1 ;add in LAMBDA 431eddb30abSmycroft add.w d1,d1 ;put them in bits 3:1 43222ef5fa9Smycroft tst.l L_SCR2(a6) ;test sign of original x 43322ef5fa9Smycroft bge.b x_pos ;if pos, don't set bit 0 43422ef5fa9Smycroft addq.l #1,d1 ;if neg, set bit 0 43522ef5fa9Smycroftx_pos: 43622ef5fa9Smycroft lea.l RBDTBL,a2 ;load rbdtbl base 43722ef5fa9Smycroft move.b (a2,d1),d3 ;load d3 with new rmode 43822ef5fa9Smycroft lsl.l #4,d3 ;put bits in proper position 43922ef5fa9Smycroft fmove.l d3,fpcr ;load bits into fpu 44022ef5fa9Smycroft lsr.l #4,d3 ;put bits in proper position 44122ef5fa9Smycroft tst.b d3 ;decode new rmode for pten table 44222ef5fa9Smycroft bne.b not_rn ;if zero, it is RN 44322ef5fa9Smycroft lea.l PTENRN,a1 ;load a1 with RN table base 44422ef5fa9Smycroft bra.b rmode ;exit decode 44522ef5fa9Smycroftnot_rn: 44622ef5fa9Smycroft lsr.b #1,d3 ;get lsb in carry 44722ef5fa9Smycroft bcc.b not_rp ;if carry clear, it is RM 44822ef5fa9Smycroft lea.l PTENRP,a1 ;load a1 with RP table base 44922ef5fa9Smycroft bra.b rmode ;exit decode 45022ef5fa9Smycroftnot_rp: 45122ef5fa9Smycroft lea.l PTENRM,a1 ;load a1 with RM table base 45222ef5fa9Smycroftrmode: 45322ef5fa9Smycroft clr.l d3 ;clr table index 45422ef5fa9Smycrofte_loop: 45522ef5fa9Smycroft lsr.l #1,d0 ;shift next bit into carry 45622ef5fa9Smycroft bcc.b e_next ;if zero, skip the mul 45722ef5fa9Smycroft fmul.x (a1,d3),fp1 ;mul by 10**(d3_bit_no) 45822ef5fa9Smycrofte_next: 45922ef5fa9Smycroft add.l #12,d3 ;inc d3 to next pwrten table entry 46022ef5fa9Smycroft tst.l d0 ;test if ISCALE is zero 46122ef5fa9Smycroft bne.b e_loop ;if not, loop 46222ef5fa9Smycroft 46322ef5fa9Smycroft 46422ef5fa9Smycroft* A8. Clr INEX; Force RZ. 46522ef5fa9Smycroft* The operation in A3 above may have set INEX2. 46622ef5fa9Smycroft* RZ mode is forced for the scaling operation to insure 46722ef5fa9Smycroft* only one rounding error. The grs bits are collected in 46822ef5fa9Smycroft* the INEX flag for use in A10. 46922ef5fa9Smycroft* 47022ef5fa9Smycroft* Register usage: 47122ef5fa9Smycroft* Input/Output 47222ef5fa9Smycroft 47322ef5fa9Smycroft fmove.l #0,FPSR ;clr INEX 47422ef5fa9Smycroft fmove.l #rz_mode,FPCR ;set RZ rounding mode 47522ef5fa9Smycroft 47622ef5fa9Smycroft 47722ef5fa9Smycroft* A9. Scale X -> Y. 47822ef5fa9Smycroft* The mantissa is scaled to the desired number of significant 47922ef5fa9Smycroft* digits. The excess digits are collected in INEX2. If mul, 48022ef5fa9Smycroft* Check d2 for excess 10 exponential value. If not zero, 48122ef5fa9Smycroft* the iscale value would have caused the pwrten calculation 48222ef5fa9Smycroft* to overflow. Only a negative iscale can cause this, so 48322ef5fa9Smycroft* multiply by 10^(d2), which is now only allowed to be 24, 48422ef5fa9Smycroft* with a multiply by 10^8 and 10^16, which is exact since 48522ef5fa9Smycroft* 10^24 is exact. If the input was denormalized, we must 48622ef5fa9Smycroft* create a busy stack frame with the mul command and the 48722ef5fa9Smycroft* two operands, and allow the fpu to complete the multiply. 48822ef5fa9Smycroft* 48922ef5fa9Smycroft* Register usage: 49022ef5fa9Smycroft* Input/Output 49122ef5fa9Smycroft* d0: FPCR with RZ mode/Unchanged 49222ef5fa9Smycroft* d2: 0 or 24/unchanged 49322ef5fa9Smycroft* d3: x/x 49422ef5fa9Smycroft* d4: LEN/Unchanged 49522ef5fa9Smycroft* d5: ICTR:LAMBDA 49622ef5fa9Smycroft* d6: ILOG/Unchanged 49722ef5fa9Smycroft* d7: k-factor/Unchanged 49822ef5fa9Smycroft* a0: ptr for original operand/final result 49922ef5fa9Smycroft* a1: ptr to PTENRM array/Unchanged 50022ef5fa9Smycroft* a2: x/x 50122ef5fa9Smycroft* fp0: float(ILOG)/X adjusted for SCALE (Y) 50222ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 50322ef5fa9Smycroft* fp2: x/x 50422ef5fa9Smycroft* F_SCR1:x/x 50522ef5fa9Smycroft* F_SCR2:Abs(X) with $3fff exponent/Unchanged 50622ef5fa9Smycroft* L_SCR1:x/x 50722ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 50822ef5fa9Smycroft 50922ef5fa9SmycroftA9_str: 51022ef5fa9Smycroft fmove.x (a0),fp0 ;load X from memory 51122ef5fa9Smycroft fabs.x fp0 ;use abs(X) 51222ef5fa9Smycroft tst.w d5 ;LAMBDA is in lower word of d5 513*c869df6aSbriggs bne.b short_sc_mul ;if neg (LAMBDA = 1), scale by mul 51422ef5fa9Smycroft fdiv.x fp1,fp0 ;calculate X / SCALE -> Y to fp0 51522ef5fa9Smycroft bra.b A10_st ;branch to A10 51622ef5fa9Smycroft 51722ef5fa9Smycroftsc_mul: 518*c869df6aSbriggsshort_sc_mul: 51922ef5fa9Smycroft tst.b BINDEC_FLG(a6) ;check for denorm 52022ef5fa9Smycroft beq.b A9_norm ;if norm, continue with mul 52122ef5fa9Smycroft fmovem.x fp1,-(a7) ;load ETEMP with 10^ISCALE 52222ef5fa9Smycroft move.l 8(a0),-(a7) ;load FPTEMP with input arg 52322ef5fa9Smycroft move.l 4(a0),-(a7) 52422ef5fa9Smycroft move.l (a0),-(a7) 52522ef5fa9Smycroft move.l #18,d3 ;load count for busy stack 52622ef5fa9SmycroftA9_loop: 52722ef5fa9Smycroft clr.l -(a7) ;clear lword on stack 52822ef5fa9Smycroft dbf.w d3,A9_loop 52922ef5fa9Smycroft move.b VER_TMP(a6),(a7) ;write current version number 53022ef5fa9Smycroft move.b #BUSY_SIZE-4,1(a7) ;write current busy size 53122ef5fa9Smycroft move.b #$10,$44(a7) ;set fcefpte[15] bit 53222ef5fa9Smycroft move.w #$0023,$40(a7) ;load cmdreg1b with mul command 53322ef5fa9Smycroft move.b #$fe,$8(a7) ;load all 1s to cu savepc 53422ef5fa9Smycroft frestore (a7)+ ;restore frame to fpu for completion 53522ef5fa9Smycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8 53622ef5fa9Smycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16 53722ef5fa9Smycroft bra.b A10_st 53822ef5fa9SmycroftA9_norm: 53922ef5fa9Smycroft tst.w d2 ;test for small exp case 54022ef5fa9Smycroft beq.b A9_con ;if zero, continue as normal 54122ef5fa9Smycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8 54222ef5fa9Smycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16 54322ef5fa9SmycroftA9_con: 54422ef5fa9Smycroft fmul.x fp1,fp0 ;calculate X * SCALE -> Y to fp0 54522ef5fa9Smycroft 54622ef5fa9Smycroft 54722ef5fa9Smycroft* A10. Or in INEX. 548456dff6cSwiz* If INEX is set, round error occurred. This is compensated 54922ef5fa9Smycroft* for by 'or-ing' in the INEX2 flag to the lsb of Y. 55022ef5fa9Smycroft* 55122ef5fa9Smycroft* Register usage: 55222ef5fa9Smycroft* Input/Output 55322ef5fa9Smycroft* d0: FPCR with RZ mode/FPSR with INEX2 isolated 55422ef5fa9Smycroft* d2: x/x 55522ef5fa9Smycroft* d3: x/x 55622ef5fa9Smycroft* d4: LEN/Unchanged 55722ef5fa9Smycroft* d5: ICTR:LAMBDA 55822ef5fa9Smycroft* d6: ILOG/Unchanged 55922ef5fa9Smycroft* d7: k-factor/Unchanged 56022ef5fa9Smycroft* a0: ptr for original operand/final result 56122ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 56222ef5fa9Smycroft* a2: x/ptr to FP_SCR2(a6) 56322ef5fa9Smycroft* fp0: Y/Y with lsb adjusted 56422ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 56522ef5fa9Smycroft* fp2: x/x 56622ef5fa9Smycroft 56722ef5fa9SmycroftA10_st: 56822ef5fa9Smycroft fmove.l FPSR,d0 ;get FPSR 56922ef5fa9Smycroft fmove.x fp0,FP_SCR2(a6) ;move Y to memory 57022ef5fa9Smycroft lea.l FP_SCR2(a6),a2 ;load a2 with ptr to FP_SCR2 57122ef5fa9Smycroft btst.l #9,d0 ;check if INEX2 set 57222ef5fa9Smycroft beq.b A11_st ;if clear, skip rest 57322ef5fa9Smycroft ori.l #1,8(a2) ;or in 1 to lsb of mantissa 57422ef5fa9Smycroft fmove.x FP_SCR2(a6),fp0 ;write adjusted Y back to fpu 57522ef5fa9Smycroft 57622ef5fa9Smycroft 57722ef5fa9Smycroft* A11. Restore original FPCR; set size ext. 57822ef5fa9Smycroft* Perform FINT operation in the user's rounding mode. Keep 57922ef5fa9Smycroft* the size to extended. The sintdo entry point in the sint 58022ef5fa9Smycroft* routine expects the FPCR value to be in USER_FPCR for 58122ef5fa9Smycroft* mode and precision. The original FPCR is saved in L_SCR1. 58222ef5fa9Smycroft 58322ef5fa9SmycroftA11_st: 58422ef5fa9Smycroft move.l USER_FPCR(a6),L_SCR1(a6) ;save it for later 58522ef5fa9Smycroft andi.l #$00000030,USER_FPCR(a6) ;set size to ext, 58622ef5fa9Smycroft* ;block exceptions 58722ef5fa9Smycroft 58822ef5fa9Smycroft 58922ef5fa9Smycroft* A12. Calculate YINT = FINT(Y) according to user's rounding mode. 59022ef5fa9Smycroft* The FPSP routine sintd0 is used. The output is in fp0. 59122ef5fa9Smycroft* 59222ef5fa9Smycroft* Register usage: 59322ef5fa9Smycroft* Input/Output 59422ef5fa9Smycroft* d0: FPSR with AINEX cleared/FPCR with size set to ext 59522ef5fa9Smycroft* d2: x/x/scratch 59622ef5fa9Smycroft* d3: x/x 59722ef5fa9Smycroft* d4: LEN/Unchanged 59822ef5fa9Smycroft* d5: ICTR:LAMBDA/Unchanged 59922ef5fa9Smycroft* d6: ILOG/Unchanged 60022ef5fa9Smycroft* d7: k-factor/Unchanged 60122ef5fa9Smycroft* a0: ptr for original operand/src ptr for sintdo 60222ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 60322ef5fa9Smycroft* a2: ptr to FP_SCR2(a6)/Unchanged 60422ef5fa9Smycroft* a6: temp pointer to FP_SCR2(a6) - orig value saved and restored 60522ef5fa9Smycroft* fp0: Y/YINT 60622ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 60722ef5fa9Smycroft* fp2: x/x 60822ef5fa9Smycroft* F_SCR1:x/x 60922ef5fa9Smycroft* F_SCR2:Y adjusted for inex/Y with original exponent 61022ef5fa9Smycroft* L_SCR1:x/original USER_FPCR 61122ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 61222ef5fa9Smycroft 61322ef5fa9SmycroftA12_st: 61422ef5fa9Smycroft movem.l d0-d1/a0-a1,-(a7) ;save regs used by sintd0 61522ef5fa9Smycroft move.l L_SCR1(a6),-(a7) 61622ef5fa9Smycroft move.l L_SCR2(a6),-(a7) 61722ef5fa9Smycroft lea.l FP_SCR2(a6),a0 ;a0 is ptr to F_SCR2(a6) 61822ef5fa9Smycroft fmove.x fp0,(a0) ;move Y to memory at FP_SCR2(a6) 61922ef5fa9Smycroft tst.l L_SCR2(a6) ;test sign of original operand 62022ef5fa9Smycroft bge.b do_fint ;if pos, use Y 62122ef5fa9Smycroft or.l #$80000000,(a0) ;if neg, use -Y 62222ef5fa9Smycroftdo_fint: 62322ef5fa9Smycroft move.l USER_FPSR(a6),-(a7) 62422ef5fa9Smycroft bsr sintdo ;sint routine returns int in fp0 62522ef5fa9Smycroft move.b (a7),USER_FPSR(a6) 62622ef5fa9Smycroft add.l #4,a7 62722ef5fa9Smycroft move.l (a7)+,L_SCR2(a6) 62822ef5fa9Smycroft move.l (a7)+,L_SCR1(a6) 62922ef5fa9Smycroft movem.l (a7)+,d0-d1/a0-a1 ;restore regs used by sint 63022ef5fa9Smycroft move.l L_SCR2(a6),FP_SCR2(a6) ;restore original exponent 63122ef5fa9Smycroft move.l L_SCR1(a6),USER_FPCR(a6) ;restore user's FPCR 63222ef5fa9Smycroft 63322ef5fa9Smycroft 63422ef5fa9Smycroft* A13. Check for LEN digits. 63522ef5fa9Smycroft* If the int operation results in more than LEN digits, 63622ef5fa9Smycroft* or less than LEN -1 digits, adjust ILOG and repeat from 63722ef5fa9Smycroft* A6. This test occurs only on the first pass. If the 63822ef5fa9Smycroft* result is exactly 10^LEN, decrement ILOG and divide 63922ef5fa9Smycroft* the mantissa by 10. The calculation of 10^LEN cannot 64022ef5fa9Smycroft* be inexact, since all powers of ten upto 10^27 are exact 64122ef5fa9Smycroft* in extended precision, so the use of a previous power-of-ten 64222ef5fa9Smycroft* table will introduce no error. 64322ef5fa9Smycroft* 64422ef5fa9Smycroft* 64522ef5fa9Smycroft* Register usage: 64622ef5fa9Smycroft* Input/Output 64722ef5fa9Smycroft* d0: FPCR with size set to ext/scratch final = 0 64822ef5fa9Smycroft* d2: x/x 64922ef5fa9Smycroft* d3: x/scratch final = x 65022ef5fa9Smycroft* d4: LEN/LEN adjusted 65122ef5fa9Smycroft* d5: ICTR:LAMBDA/LAMBDA:ICTR 65222ef5fa9Smycroft* d6: ILOG/ILOG adjusted 65322ef5fa9Smycroft* d7: k-factor/Unchanged 65422ef5fa9Smycroft* a0: pointer into memory for packed bcd string formation 65522ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 65622ef5fa9Smycroft* a2: ptr to FP_SCR2(a6)/Unchanged 65722ef5fa9Smycroft* fp0: int portion of Y/abs(YINT) adjusted 65822ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 65922ef5fa9Smycroft* fp2: x/10^LEN 66022ef5fa9Smycroft* F_SCR1:x/x 66122ef5fa9Smycroft* F_SCR2:Y with original exponent/Unchanged 66222ef5fa9Smycroft* L_SCR1:original USER_FPCR/Unchanged 66322ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 66422ef5fa9Smycroft 66522ef5fa9SmycroftA13_st: 66622ef5fa9Smycroft swap d5 ;put ICTR in lower word of d5 66722ef5fa9Smycroft tst.w d5 ;check if ICTR = 0 66822ef5fa9Smycroft bne not_zr ;if non-zero, go to second test 66922ef5fa9Smycroft* 67022ef5fa9Smycroft* Compute 10^(LEN-1) 67122ef5fa9Smycroft* 67222ef5fa9Smycroft fmove.s FONE,fp2 ;init fp2 to 1.0 67322ef5fa9Smycroft move.l d4,d0 ;put LEN in d0 67422ef5fa9Smycroft subq.l #1,d0 ;d0 = LEN -1 67522ef5fa9Smycroft clr.l d3 ;clr table index 67622ef5fa9Smycroftl_loop: 67722ef5fa9Smycroft lsr.l #1,d0 ;shift next bit into carry 67822ef5fa9Smycroft bcc.b l_next ;if zero, skip the mul 67922ef5fa9Smycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no) 68022ef5fa9Smycroftl_next: 68122ef5fa9Smycroft add.l #12,d3 ;inc d3 to next pwrten table entry 68222ef5fa9Smycroft tst.l d0 ;test if LEN is zero 68322ef5fa9Smycroft bne.b l_loop ;if not, loop 68422ef5fa9Smycroft* 68522ef5fa9Smycroft* 10^LEN-1 is computed for this test and A14. If the input was 68622ef5fa9Smycroft* denormalized, check only the case in which YINT > 10^LEN. 68722ef5fa9Smycroft* 68822ef5fa9Smycroft tst.b BINDEC_FLG(a6) ;check if input was norm 68922ef5fa9Smycroft beq.b A13_con ;if norm, continue with checking 69022ef5fa9Smycroft fabs.x fp0 ;take abs of YINT 69122ef5fa9Smycroft bra test_2 69222ef5fa9Smycroft* 69322ef5fa9Smycroft* Compare abs(YINT) to 10^(LEN-1) and 10^LEN 69422ef5fa9Smycroft* 69522ef5fa9SmycroftA13_con: 69622ef5fa9Smycroft fabs.x fp0 ;take abs of YINT 69722ef5fa9Smycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^(LEN-1) 69822ef5fa9Smycroft fbge.w test_2 ;if greater, do next test 69922ef5fa9Smycroft subq.l #1,d6 ;subtract 1 from ILOG 70022ef5fa9Smycroft move.w #1,d5 ;set ICTR 70122ef5fa9Smycroft fmove.l #rm_mode,FPCR ;set rmode to RM 70222ef5fa9Smycroft fmul.s FTEN,fp2 ;compute 10^LEN 70322ef5fa9Smycroft bra.w A6_str ;return to A6 and recompute YINT 70422ef5fa9Smycrofttest_2: 70522ef5fa9Smycroft fmul.s FTEN,fp2 ;compute 10^LEN 70622ef5fa9Smycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^LEN 70722ef5fa9Smycroft fblt.w A14_st ;if less, all is ok, go to A14 70822ef5fa9Smycroft fbgt.w fix_ex ;if greater, fix and redo 70922ef5fa9Smycroft fdiv.s FTEN,fp0 ;if equal, divide by 10 71022ef5fa9Smycroft addq.l #1,d6 ; and inc ILOG 71122ef5fa9Smycroft bra.b A14_st ; and continue elsewhere 71222ef5fa9Smycroftfix_ex: 71322ef5fa9Smycroft addq.l #1,d6 ;increment ILOG by 1 71422ef5fa9Smycroft move.w #1,d5 ;set ICTR 71522ef5fa9Smycroft fmove.l #rm_mode,FPCR ;set rmode to RM 71622ef5fa9Smycroft bra.w A6_str ;return to A6 and recompute YINT 71722ef5fa9Smycroft* 71822ef5fa9Smycroft* Since ICTR <> 0, we have already been through one adjustment, 71922ef5fa9Smycroft* and shouldn't have another; this is to check if abs(YINT) = 10^LEN 72022ef5fa9Smycroft* 10^LEN is again computed using whatever table is in a1 since the 72122ef5fa9Smycroft* value calculated cannot be inexact. 72222ef5fa9Smycroft* 72322ef5fa9Smycroftnot_zr: 72422ef5fa9Smycroft fmove.s FONE,fp2 ;init fp2 to 1.0 72522ef5fa9Smycroft move.l d4,d0 ;put LEN in d0 72622ef5fa9Smycroft clr.l d3 ;clr table index 72722ef5fa9Smycroftz_loop: 72822ef5fa9Smycroft lsr.l #1,d0 ;shift next bit into carry 72922ef5fa9Smycroft bcc.b z_next ;if zero, skip the mul 73022ef5fa9Smycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no) 73122ef5fa9Smycroftz_next: 73222ef5fa9Smycroft add.l #12,d3 ;inc d3 to next pwrten table entry 73322ef5fa9Smycroft tst.l d0 ;test if LEN is zero 73422ef5fa9Smycroft bne.b z_loop ;if not, loop 73522ef5fa9Smycroft fabs.x fp0 ;get abs(YINT) 73622ef5fa9Smycroft fcmp.x fp2,fp0 ;check if abs(YINT) = 10^LEN 73722ef5fa9Smycroft fbne.w A14_st ;if not, skip this 73822ef5fa9Smycroft fdiv.s FTEN,fp0 ;divide abs(YINT) by 10 73922ef5fa9Smycroft addq.l #1,d6 ;and inc ILOG by 1 74022ef5fa9Smycroft addq.l #1,d4 ; and inc LEN 74122ef5fa9Smycroft fmul.s FTEN,fp2 ; if LEN++, the get 10^^LEN 74222ef5fa9Smycroft 74322ef5fa9Smycroft 74422ef5fa9Smycroft* A14. Convert the mantissa to bcd. 74522ef5fa9Smycroft* The binstr routine is used to convert the LEN digit 74622ef5fa9Smycroft* mantissa to bcd in memory. The input to binstr is 74722ef5fa9Smycroft* to be a fraction; i.e. (mantissa)/10^LEN and adjusted 74822ef5fa9Smycroft* such that the decimal point is to the left of bit 63. 74922ef5fa9Smycroft* The bcd digits are stored in the correct position in 75022ef5fa9Smycroft* the final string area in memory. 75122ef5fa9Smycroft* 75222ef5fa9Smycroft* 75322ef5fa9Smycroft* Register usage: 75422ef5fa9Smycroft* Input/Output 75522ef5fa9Smycroft* d0: x/LEN call to binstr - final is 0 75622ef5fa9Smycroft* d1: x/0 75722ef5fa9Smycroft* d2: x/ms 32-bits of mant of abs(YINT) 75822ef5fa9Smycroft* d3: x/ls 32-bits of mant of abs(YINT) 75922ef5fa9Smycroft* d4: LEN/Unchanged 76022ef5fa9Smycroft* d5: ICTR:LAMBDA/LAMBDA:ICTR 76122ef5fa9Smycroft* d6: ILOG 76222ef5fa9Smycroft* d7: k-factor/Unchanged 76322ef5fa9Smycroft* a0: pointer into memory for packed bcd string formation 76422ef5fa9Smycroft* /ptr to first mantissa byte in result string 76522ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 76622ef5fa9Smycroft* a2: ptr to FP_SCR2(a6)/Unchanged 76722ef5fa9Smycroft* fp0: int portion of Y/abs(YINT) adjusted 76822ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 76922ef5fa9Smycroft* fp2: 10^LEN/Unchanged 77022ef5fa9Smycroft* F_SCR1:x/Work area for final result 77122ef5fa9Smycroft* F_SCR2:Y with original exponent/Unchanged 77222ef5fa9Smycroft* L_SCR1:original USER_FPCR/Unchanged 77322ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 77422ef5fa9Smycroft 77522ef5fa9SmycroftA14_st: 77622ef5fa9Smycroft fmove.l #rz_mode,FPCR ;force rz for conversion 77722ef5fa9Smycroft fdiv.x fp2,fp0 ;divide abs(YINT) by 10^LEN 77822ef5fa9Smycroft lea.l FP_SCR1(a6),a0 77922ef5fa9Smycroft fmove.x fp0,(a0) ;move abs(YINT)/10^LEN to memory 78022ef5fa9Smycroft move.l 4(a0),d2 ;move 2nd word of FP_RES to d2 78122ef5fa9Smycroft move.l 8(a0),d3 ;move 3rd word of FP_RES to d3 78222ef5fa9Smycroft clr.l 4(a0) ;zero word 2 of FP_RES 78322ef5fa9Smycroft clr.l 8(a0) ;zero word 3 of FP_RES 78422ef5fa9Smycroft move.l (a0),d0 ;move exponent to d0 78522ef5fa9Smycroft swap d0 ;put exponent in lower word 78622ef5fa9Smycroft beq.b no_sft ;if zero, don't shift 78722ef5fa9Smycroft subi.l #$3ffd,d0 ;sub bias less 2 to make fract 78822ef5fa9Smycroft tst.l d0 ;check if > 1 78922ef5fa9Smycroft bgt.b no_sft ;if so, don't shift 79022ef5fa9Smycroft neg.l d0 ;make exp positive 79122ef5fa9Smycroftm_loop: 79222ef5fa9Smycroft lsr.l #1,d2 ;shift d2:d3 right, add 0s 79322ef5fa9Smycroft roxr.l #1,d3 ;the number of places 79422ef5fa9Smycroft dbf.w d0,m_loop ;given in d0 79522ef5fa9Smycroftno_sft: 79622ef5fa9Smycroft tst.l d2 ;check for mantissa of zero 79722ef5fa9Smycroft bne.b no_zr ;if not, go on 79822ef5fa9Smycroft tst.l d3 ;continue zero check 79922ef5fa9Smycroft beq.b zer_m ;if zero, go directly to binstr 80022ef5fa9Smycroftno_zr: 80122ef5fa9Smycroft clr.l d1 ;put zero in d1 for addx 80222ef5fa9Smycroft addi.l #$00000080,d3 ;inc at bit 7 80322ef5fa9Smycroft addx.l d1,d2 ;continue inc 80422ef5fa9Smycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882 80522ef5fa9Smycroftzer_m: 80622ef5fa9Smycroft move.l d4,d0 ;put LEN in d0 for binstr call 80722ef5fa9Smycroft addq.l #3,a0 ;a0 points to M16 byte in result 80822ef5fa9Smycroft bsr binstr ;call binstr to convert mant 80922ef5fa9Smycroft 81022ef5fa9Smycroft 81122ef5fa9Smycroft* A15. Convert the exponent to bcd. 81222ef5fa9Smycroft* As in A14 above, the exp is converted to bcd and the 81322ef5fa9Smycroft* digits are stored in the final string. 81422ef5fa9Smycroft* 81522ef5fa9Smycroft* Digits are stored in L_SCR1(a6) on return from BINDEC as: 81622ef5fa9Smycroft* 81722ef5fa9Smycroft* 32 16 15 0 81822ef5fa9Smycroft* ----------------------------------------- 81922ef5fa9Smycroft* | 0 | e3 | e2 | e1 | e4 | X | X | X | 82022ef5fa9Smycroft* ----------------------------------------- 82122ef5fa9Smycroft* 82222ef5fa9Smycroft* And are moved into their proper places in FP_SCR1. If digit e4 82322ef5fa9Smycroft* is non-zero, OPERR is signaled. In all cases, all 4 digits are 82422ef5fa9Smycroft* written as specified in the 881/882 manual for packed decimal. 82522ef5fa9Smycroft* 82622ef5fa9Smycroft* Register usage: 82722ef5fa9Smycroft* Input/Output 82822ef5fa9Smycroft* d0: x/LEN call to binstr - final is 0 82922ef5fa9Smycroft* d1: x/scratch (0);shift count for final exponent packing 83022ef5fa9Smycroft* d2: x/ms 32-bits of exp fraction/scratch 83122ef5fa9Smycroft* d3: x/ls 32-bits of exp fraction 83222ef5fa9Smycroft* d4: LEN/Unchanged 83322ef5fa9Smycroft* d5: ICTR:LAMBDA/LAMBDA:ICTR 83422ef5fa9Smycroft* d6: ILOG 83522ef5fa9Smycroft* d7: k-factor/Unchanged 83622ef5fa9Smycroft* a0: ptr to result string/ptr to L_SCR1(a6) 83722ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 83822ef5fa9Smycroft* a2: ptr to FP_SCR2(a6)/Unchanged 83922ef5fa9Smycroft* fp0: abs(YINT) adjusted/float(ILOG) 84022ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 84122ef5fa9Smycroft* fp2: 10^LEN/Unchanged 84222ef5fa9Smycroft* F_SCR1:Work area for final result/BCD result 84322ef5fa9Smycroft* F_SCR2:Y with original exponent/ILOG/10^4 84422ef5fa9Smycroft* L_SCR1:original USER_FPCR/Exponent digits on return from binstr 84522ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 84622ef5fa9Smycroft 84722ef5fa9SmycroftA15_st: 84822ef5fa9Smycroft tst.b BINDEC_FLG(a6) ;check for denorm 84922ef5fa9Smycroft beq.b not_denorm 85022ef5fa9Smycroft ftst.x fp0 ;test for zero 85122ef5fa9Smycroft fbeq.w den_zero ;if zero, use k-factor or 4933 85222ef5fa9Smycroft fmove.l d6,fp0 ;float ILOG 85322ef5fa9Smycroft fabs.x fp0 ;get abs of ILOG 85422ef5fa9Smycroft bra.b convrt 85522ef5fa9Smycroftden_zero: 85622ef5fa9Smycroft tst.l d7 ;check sign of the k-factor 85722ef5fa9Smycroft blt.b use_ilog ;if negative, use ILOG 85822ef5fa9Smycroft fmove.s F4933,fp0 ;force exponent to 4933 85922ef5fa9Smycroft bra.b convrt ;do it 86022ef5fa9Smycroftuse_ilog: 86122ef5fa9Smycroft fmove.l d6,fp0 ;float ILOG 86222ef5fa9Smycroft fabs.x fp0 ;get abs of ILOG 86322ef5fa9Smycroft bra.b convrt 86422ef5fa9Smycroftnot_denorm: 86522ef5fa9Smycroft ftst.x fp0 ;test for zero 86622ef5fa9Smycroft fbne.w not_zero ;if zero, force exponent 86722ef5fa9Smycroft fmove.s FONE,fp0 ;force exponent to 1 86822ef5fa9Smycroft bra.b convrt ;do it 86922ef5fa9Smycroftnot_zero: 87022ef5fa9Smycroft fmove.l d6,fp0 ;float ILOG 87122ef5fa9Smycroft fabs.x fp0 ;get abs of ILOG 87222ef5fa9Smycroftconvrt: 87322ef5fa9Smycroft fdiv.x 24(a1),fp0 ;compute ILOG/10^4 87422ef5fa9Smycroft fmove.x fp0,FP_SCR2(a6) ;store fp0 in memory 87522ef5fa9Smycroft move.l 4(a2),d2 ;move word 2 to d2 87622ef5fa9Smycroft move.l 8(a2),d3 ;move word 3 to d3 87722ef5fa9Smycroft move.w (a2),d0 ;move exp to d0 87822ef5fa9Smycroft beq.b x_loop_fin ;if zero, skip the shift 87922ef5fa9Smycroft subi.w #$3ffd,d0 ;subtract off bias 88022ef5fa9Smycroft neg.w d0 ;make exp positive 88122ef5fa9Smycroftx_loop: 88222ef5fa9Smycroft lsr.l #1,d2 ;shift d2:d3 right 88322ef5fa9Smycroft roxr.l #1,d3 ;the number of places 88422ef5fa9Smycroft dbf.w d0,x_loop ;given in d0 88522ef5fa9Smycroftx_loop_fin: 88622ef5fa9Smycroft clr.l d1 ;put zero in d1 for addx 88722ef5fa9Smycroft addi.l #$00000080,d3 ;inc at bit 6 88822ef5fa9Smycroft addx.l d1,d2 ;continue inc 88922ef5fa9Smycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882 89022ef5fa9Smycroft move.l #4,d0 ;put 4 in d0 for binstr call 89122ef5fa9Smycroft lea.l L_SCR1(a6),a0 ;a0 is ptr to L_SCR1 for exp digits 89222ef5fa9Smycroft bsr binstr ;call binstr to convert exp 89322ef5fa9Smycroft move.l L_SCR1(a6),d0 ;load L_SCR1 lword to d0 89422ef5fa9Smycroft move.l #12,d1 ;use d1 for shift count 89522ef5fa9Smycroft lsr.l d1,d0 ;shift d0 right by 12 89622ef5fa9Smycroft bfins d0,FP_SCR1(a6){4:12} ;put e3:e2:e1 in FP_SCR1 89722ef5fa9Smycroft lsr.l d1,d0 ;shift d0 right by 12 89822ef5fa9Smycroft bfins d0,FP_SCR1(a6){16:4} ;put e4 in FP_SCR1 89922ef5fa9Smycroft tst.b d0 ;check if e4 is zero 90022ef5fa9Smycroft beq.b A16_st ;if zero, skip rest 90122ef5fa9Smycroft or.l #opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR 90222ef5fa9Smycroft 90322ef5fa9Smycroft 90422ef5fa9Smycroft* A16. Write sign bits to final string. 90522ef5fa9Smycroft* Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG). 90622ef5fa9Smycroft* 90722ef5fa9Smycroft* Register usage: 90822ef5fa9Smycroft* Input/Output 90922ef5fa9Smycroft* d0: x/scratch - final is x 91022ef5fa9Smycroft* d2: x/x 91122ef5fa9Smycroft* d3: x/x 91222ef5fa9Smycroft* d4: LEN/Unchanged 91322ef5fa9Smycroft* d5: ICTR:LAMBDA/LAMBDA:ICTR 91422ef5fa9Smycroft* d6: ILOG/ILOG adjusted 91522ef5fa9Smycroft* d7: k-factor/Unchanged 91622ef5fa9Smycroft* a0: ptr to L_SCR1(a6)/Unchanged 91722ef5fa9Smycroft* a1: ptr to PTENxx array/Unchanged 91822ef5fa9Smycroft* a2: ptr to FP_SCR2(a6)/Unchanged 91922ef5fa9Smycroft* fp0: float(ILOG)/Unchanged 92022ef5fa9Smycroft* fp1: 10^ISCALE/Unchanged 92122ef5fa9Smycroft* fp2: 10^LEN/Unchanged 92222ef5fa9Smycroft* F_SCR1:BCD result with correct signs 92322ef5fa9Smycroft* F_SCR2:ILOG/10^4 92422ef5fa9Smycroft* L_SCR1:Exponent digits on return from binstr 92522ef5fa9Smycroft* L_SCR2:first word of X packed/Unchanged 92622ef5fa9Smycroft 92722ef5fa9SmycroftA16_st: 92822ef5fa9Smycroft clr.l d0 ;clr d0 for collection of signs 92922ef5fa9Smycroft andi.b #$0f,FP_SCR1(a6) ;clear first nibble of FP_SCR1 93022ef5fa9Smycroft tst.l L_SCR2(a6) ;check sign of original mantissa 93122ef5fa9Smycroft bge.b mant_p ;if pos, don't set SM 93222ef5fa9Smycroft moveq.l #2,d0 ;move 2 in to d0 for SM 93322ef5fa9Smycroftmant_p: 93422ef5fa9Smycroft tst.l d6 ;check sign of ILOG 93522ef5fa9Smycroft bge.b wr_sgn ;if pos, don't set SE 93622ef5fa9Smycroft addq.l #1,d0 ;set bit 0 in d0 for SE 93722ef5fa9Smycroftwr_sgn: 93822ef5fa9Smycroft bfins d0,FP_SCR1(a6){0:2} ;insert SM and SE into FP_SCR1 93922ef5fa9Smycroft 94022ef5fa9Smycroft* Clean up and restore all registers used. 94122ef5fa9Smycroft 94222ef5fa9Smycroft fmove.l #0,FPSR ;clear possible inex2/ainex bits 94322ef5fa9Smycroft fmovem.x (a7)+,fp0-fp2 94422ef5fa9Smycroft movem.l (a7)+,d2-d7/a2 94522ef5fa9Smycroft rts 94622ef5fa9Smycroft 94722ef5fa9Smycroft end 948