| 1 | 1275 | phoenix | |
 | 
      
         | 2 |  |  | |       bindec.sa 3.4 1/3/91
 | 
      
         | 3 |  |  | |
 | 
      
         | 4 |  |  | |       bindec
 | 
      
         | 5 |  |  | |
 | 
      
         | 6 |  |  | |       Description:
 | 
      
         | 7 |  |  | |               Converts an input in extended precision format
 | 
      
         | 8 |  |  | |               to bcd format.
 | 
      
         | 9 |  |  | |
 | 
      
         | 10 |  |  | |       Input:
 | 
      
         | 11 |  |  | |               a0 points to the input extended precision value
 | 
      
         | 12 |  |  | |               value in memory; d0 contains the k-factor sign-extended
 | 
      
         | 13 |  |  | |               to 32-bits.  The input may be either normalized,
 | 
      
         | 14 |  |  | |               unnormalized, or denormalized.
 | 
      
         | 15 |  |  | |
 | 
      
         | 16 |  |  | |       Output: result in the FP_SCR1 space on the stack.
 | 
      
         | 17 |  |  | |
 | 
      
         | 18 |  |  | |       Saves and Modifies: D2-D7,A2,FP2
 | 
      
         | 19 |  |  | |
 | 
      
         | 20 |  |  | |       Algorithm:
 | 
      
         | 21 |  |  | |
 | 
      
         | 22 |  |  | |       A1.     Set RM and size ext;  Set SIGMA = sign of input.
 | 
      
         | 23 |  |  | |               The k-factor is saved for use in d7. Clear the
 | 
      
         | 24 |  |  | |               BINDEC_FLG for separating normalized/denormalized
 | 
      
         | 25 |  |  | |               input.  If input is unnormalized or denormalized,
 | 
      
         | 26 |  |  | |               normalize it.
 | 
      
         | 27 |  |  | |
 | 
      
         | 28 |  |  | |       A2.     Set X = abs(input).
 | 
      
         | 29 |  |  | |
 | 
      
         | 30 |  |  | |       A3.     Compute ILOG.
 | 
      
         | 31 |  |  | |               ILOG is the log base 10 of the input value.  It is
 | 
      
         | 32 |  |  | |               approximated by adding e + 0.f when the original
 | 
      
         | 33 |  |  | |               value is viewed as 2^^e * 1.f in extended precision.
 | 
      
         | 34 |  |  | |               This value is stored in d6.
 | 
      
         | 35 |  |  | |
 | 
      
         | 36 |  |  | |       A4.     Clr INEX bit.
 | 
      
         | 37 |  |  | |               The operation in A3 above may have set INEX2.
 | 
      
         | 38 |  |  | |
 | 
      
         | 39 |  |  | |       A5.     Set ICTR = 0;
 | 
      
         | 40 |  |  | |               ICTR is a flag used in A13.  It must be set before the
 | 
      
         | 41 |  |  | |               loop entry A6.
 | 
      
         | 42 |  |  | |
 | 
      
         | 43 |  |  | |       A6.     Calculate LEN.
 | 
      
         | 44 |  |  | |               LEN is the number of digits to be displayed.  The
 | 
      
         | 45 |  |  | |               k-factor can dictate either the total number of digits,
 | 
      
         | 46 |  |  | |               if it is a positive number, or the number of digits
 | 
      
         | 47 |  |  | |               after the decimal point which are to be included as
 | 
      
         | 48 |  |  | |               significant.  See the 68882 manual for examples.
 | 
      
         | 49 |  |  | |               If LEN is computed to be greater than 17, set OPERR in
 | 
      
         | 50 |  |  | |               USER_FPSR.  LEN is stored in d4.
 | 
      
         | 51 |  |  | |
 | 
      
         | 52 |  |  | |       A7.     Calculate SCALE.
 | 
      
         | 53 |  |  | |               SCALE is equal to 10^ISCALE, where ISCALE is the number
 | 
      
         | 54 |  |  | |               of decimal places needed to insure LEN integer digits
 | 
      
         | 55 |  |  | |               in the output before conversion to bcd. LAMBDA is the
 | 
      
         | 56 |  |  | |               sign of ISCALE, used in A9. Fp1 contains
 | 
      
         | 57 |  |  | |               10^^(abs(ISCALE)) using a rounding mode which is a
 | 
      
         | 58 |  |  | |               function of the original rounding mode and the signs
 | 
      
         | 59 |  |  | |               of ISCALE and X.  A table is given in the code.
 | 
      
         | 60 |  |  | |
 | 
      
         | 61 |  |  | |       A8.     Clr INEX; Force RZ.
 | 
      
         | 62 |  |  | |               The operation in A3 above may have set INEX2.
 | 
      
         | 63 |  |  | |               RZ mode is forced for the scaling operation to insure
 | 
      
         | 64 |  |  | |               only one rounding error.  The grs bits are collected in
 | 
      
         | 65 |  |  | |               the INEX flag for use in A10.
 | 
      
         | 66 |  |  | |
 | 
      
         | 67 |  |  | |       A9.     Scale X -> Y.
 | 
      
         | 68 |  |  | |               The mantissa is scaled to the desired number of
 | 
      
         | 69 |  |  | |               significant digits.  The excess digits are collected
 | 
      
         | 70 |  |  | |               in INEX2.
 | 
      
         | 71 |  |  | |
 | 
      
         | 72 |  |  | |       A10.    Or in INEX.
 | 
      
         | 73 |  |  | |               If INEX is set, round error occurred.  This is
 | 
      
         | 74 |  |  | |               compensated for by 'or-ing' in the INEX2 flag to
 | 
      
         | 75 |  |  | |               the lsb of Y.
 | 
      
         | 76 |  |  | |
 | 
      
         | 77 |  |  | |       A11.    Restore original FPCR; set size ext.
 | 
      
         | 78 |  |  | |               Perform FINT operation in the user's rounding mode.
 | 
      
         | 79 |  |  | |               Keep the size to extended.
 | 
      
         | 80 |  |  | |
 | 
      
         | 81 |  |  | |       A12.    Calculate YINT = FINT(Y) according to user's rounding
 | 
      
         | 82 |  |  | |               mode.  The FPSP routine sintd0 is used.  The output
 | 
      
         | 83 |  |  | |               is in fp0.
 | 
      
         | 84 |  |  | |
 | 
      
         | 85 |  |  | |       A13.    Check for LEN digits.
 | 
      
         | 86 |  |  | |               If the int operation results in more than LEN digits,
 | 
      
         | 87 |  |  | |               or less than LEN -1 digits, adjust ILOG and repeat from
 | 
      
         | 88 |  |  | |               A6.  This test occurs only on the first pass.  If the
 | 
      
         | 89 |  |  | |               result is exactly 10^LEN, decrement ILOG and divide
 | 
      
         | 90 |  |  | |               the mantissa by 10.
 | 
      
         | 91 |  |  | |
 | 
      
         | 92 |  |  | |       A14.    Convert the mantissa to bcd.
 | 
      
         | 93 |  |  | |               The binstr routine is used to convert the LEN digit
 | 
      
         | 94 |  |  | |               mantissa to bcd in memory.  The input to binstr is
 | 
      
         | 95 |  |  | |               to be a fraction; i.e. (mantissa)/10^LEN and adjusted
 | 
      
         | 96 |  |  | |               such that the decimal point is to the left of bit 63.
 | 
      
         | 97 |  |  | |               The bcd digits are stored in the correct position in
 | 
      
         | 98 |  |  | |               the final string area in memory.
 | 
      
         | 99 |  |  | |
 | 
      
         | 100 |  |  | |       A15.    Convert the exponent to bcd.
 | 
      
         | 101 |  |  | |               As in A14 above, the exp is converted to bcd and the
 | 
      
         | 102 |  |  | |               digits are stored in the final string.
 | 
      
         | 103 |  |  | |               Test the length of the final exponent string.  If the
 | 
      
         | 104 |  |  | |               length is 4, set operr.
 | 
      
         | 105 |  |  | |
 | 
      
         | 106 |  |  | |       A16.    Write sign bits to final string.
 | 
      
         | 107 |  |  | |
 | 
      
         | 108 |  |  | |       Implementation Notes:
 | 
      
         | 109 |  |  | |
 | 
      
         | 110 |  |  | |       The registers are used as follows:
 | 
      
         | 111 |  |  | |
 | 
      
         | 112 |  |  | |               d0: scratch; LEN input to binstr
 | 
      
         | 113 |  |  | |               d1: scratch
 | 
      
         | 114 |  |  | |               d2: upper 32-bits of mantissa for binstr
 | 
      
         | 115 |  |  | |               d3: scratch;lower 32-bits of mantissa for binstr
 | 
      
         | 116 |  |  | |               d4: LEN
 | 
      
         | 117 |  |  | |               d5: LAMBDA/ICTR
 | 
      
         | 118 |  |  | |               d6: ILOG
 | 
      
         | 119 |  |  | |               d7: k-factor
 | 
      
         | 120 |  |  | |               a0: ptr for original operand/final result
 | 
      
         | 121 |  |  | |               a1: scratch pointer
 | 
      
         | 122 |  |  | |               a2: pointer to FP_X; abs(original value) in ext
 | 
      
         | 123 |  |  | |               fp0: scratch
 | 
      
         | 124 |  |  | |               fp1: scratch
 | 
      
         | 125 |  |  | |               fp2: scratch
 | 
      
         | 126 |  |  | |               F_SCR1:
 | 
      
         | 127 |  |  | |               F_SCR2:
 | 
      
         | 128 |  |  | |               L_SCR1:
 | 
      
         | 129 |  |  | |               L_SCR2:
 | 
      
         | 130 |  |  |  
 | 
      
         | 131 |  |  | |               Copyright (C) Motorola, Inc. 1990
 | 
      
         | 132 |  |  | |                       All Rights Reserved
 | 
      
         | 133 |  |  | |
 | 
      
         | 134 |  |  | |       THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
 | 
      
         | 135 |  |  | |       The copyright notice above does not evidence any
 | 
      
         | 136 |  |  | |       actual or intended publication of such source code.
 | 
      
         | 137 |  |  |  
 | 
      
         | 138 |  |  | |BINDEC    idnt    2,1 | Motorola 040 Floating Point Software Package
 | 
      
         | 139 |  |  |  
 | 
      
         | 140 |  |  |         .include "fpsp.h"
 | 
      
         | 141 |  |  |  
 | 
      
         | 142 |  |  |         |section        8
 | 
      
         | 143 |  |  |  
 | 
      
         | 144 |  |  | | Constants in extended precision
 | 
      
         | 145 |  |  | LOG2:   .long   0x3FFD0000,0x9A209A84,0xFBCFF798,0x00000000
 | 
      
         | 146 |  |  | LOG2UP1:        .long   0x3FFD0000,0x9A209A84,0xFBCFF799,0x00000000
 | 
      
         | 147 |  |  |  
 | 
      
         | 148 |  |  | | Constants in single precision
 | 
      
         | 149 |  |  | FONE:   .long   0x3F800000,0x00000000,0x00000000,0x00000000
 | 
      
         | 150 |  |  | FTWO:   .long   0x40000000,0x00000000,0x00000000,0x00000000
 | 
      
         | 151 |  |  | FTEN:   .long   0x41200000,0x00000000,0x00000000,0x00000000
 | 
      
         | 152 |  |  | F4933:  .long   0x459A2800,0x00000000,0x00000000,0x00000000
 | 
      
         | 153 |  |  |  
 | 
      
         | 154 |  |  | RBDTBL:         .byte   0,0,0,0
 | 
      
         | 155 |  |  |         .byte   3,3,2,2
 | 
      
         | 156 |  |  |         .byte   3,2,2,3
 | 
      
         | 157 |  |  |         .byte   2,3,3,2
 | 
      
         | 158 |  |  |  
 | 
      
         | 159 |  |  |         |xref   binstr
 | 
      
         | 160 |  |  |         |xref   sintdo
 | 
      
         | 161 |  |  |         |xref   ptenrn,ptenrm,ptenrp
 | 
      
         | 162 |  |  |  
 | 
      
         | 163 |  |  |         .global bindec
 | 
      
         | 164 |  |  |         .global sc_mul
 | 
      
         | 165 |  |  | bindec:
 | 
      
         | 166 |  |  |         moveml  %d2-%d7/%a2,-(%a7)
 | 
      
         | 167 |  |  |         fmovemx %fp0-%fp2,-(%a7)
 | 
      
         | 168 |  |  |  
 | 
      
         | 169 |  |  | | A1. Set RM and size ext. Set SIGMA = sign input;
 | 
      
         | 170 |  |  | |     The k-factor is saved for use in d7.  Clear BINDEC_FLG for
 | 
      
         | 171 |  |  | |     separating  normalized/denormalized input.  If the input
 | 
      
         | 172 |  |  | |     is a denormalized number, set the BINDEC_FLG memory word
 | 
      
         | 173 |  |  | |     to signal denorm.  If the input is unnormalized, normalize
 | 
      
         | 174 |  |  | |     the input and test for denormalized result.
 | 
      
         | 175 |  |  | |
 | 
      
         | 176 |  |  |         fmovel  #rm_mode,%FPCR  |set RM and ext
 | 
      
         | 177 |  |  |         movel   (%a0),L_SCR2(%a6)       |save exponent for sign check
 | 
      
         | 178 |  |  |         movel   %d0,%d7         |move k-factor to d7
 | 
      
         | 179 |  |  |         clrb    BINDEC_FLG(%a6) |clr norm/denorm flag
 | 
      
         | 180 |  |  |         movew   STAG(%a6),%d0   |get stag
 | 
      
         | 181 |  |  |         andiw   #0xe000,%d0     |isolate stag bits
 | 
      
         | 182 |  |  |         beq     A2_str          |if zero, input is norm
 | 
      
         | 183 |  |  | |
 | 
      
         | 184 |  |  | | Normalize the denorm
 | 
      
         | 185 |  |  | |
 | 
      
         | 186 |  |  | un_de_norm:
 | 
      
         | 187 |  |  |         movew   (%a0),%d0
 | 
      
         | 188 |  |  |         andiw   #0x7fff,%d0     |strip sign of normalized exp
 | 
      
         | 189 |  |  |         movel   4(%a0),%d1
 | 
      
         | 190 |  |  |         movel   8(%a0),%d2
 | 
      
         | 191 |  |  | norm_loop:
 | 
      
         | 192 |  |  |         subw    #1,%d0
 | 
      
         | 193 |  |  |         lsll    #1,%d2
 | 
      
         | 194 |  |  |         roxll   #1,%d1
 | 
      
         | 195 |  |  |         tstl    %d1
 | 
      
         | 196 |  |  |         bges    norm_loop
 | 
      
         | 197 |  |  | |
 | 
      
         | 198 |  |  | | Test if the normalized input is denormalized
 | 
      
         | 199 |  |  | |
 | 
      
         | 200 |  |  |         tstw    %d0
 | 
      
         | 201 |  |  |         bgts    pos_exp         |if greater than zero, it is a norm
 | 
      
         | 202 |  |  |         st      BINDEC_FLG(%a6) |set flag for denorm
 | 
      
         | 203 |  |  | pos_exp:
 | 
      
         | 204 |  |  |         andiw   #0x7fff,%d0     |strip sign of normalized exp
 | 
      
         | 205 |  |  |         movew   %d0,(%a0)
 | 
      
         | 206 |  |  |         movel   %d1,4(%a0)
 | 
      
         | 207 |  |  |         movel   %d2,8(%a0)
 | 
      
         | 208 |  |  |  
 | 
      
         | 209 |  |  | | A2. Set X = abs(input).
 | 
      
         | 210 |  |  | |
 | 
      
         | 211 |  |  | A2_str:
 | 
      
         | 212 |  |  |         movel   (%a0),FP_SCR2(%a6) | move input to work space
 | 
      
         | 213 |  |  |         movel   4(%a0),FP_SCR2+4(%a6) | move input to work space
 | 
      
         | 214 |  |  |         movel   8(%a0),FP_SCR2+8(%a6) | move input to work space
 | 
      
         | 215 |  |  |         andil   #0x7fffffff,FP_SCR2(%a6) |create abs(X)
 | 
      
         | 216 |  |  |  
 | 
      
         | 217 |  |  | | A3. Compute ILOG.
 | 
      
         | 218 |  |  | |     ILOG is the log base 10 of the input value.  It is approx-
 | 
      
         | 219 |  |  | |     imated by adding e + 0.f when the original value is viewed
 | 
      
         | 220 |  |  | |     as 2^^e * 1.f in extended precision.  This value is stored
 | 
      
         | 221 |  |  | |     in d6.
 | 
      
         | 222 |  |  | |
 | 
      
         | 223 |  |  | | Register usage:
 | 
      
         | 224 |  |  | |       Input/Output
 | 
      
         | 225 |  |  | |       d0: k-factor/exponent
 | 
      
         | 226 |  |  | |       d2: x/x
 | 
      
         | 227 |  |  | |       d3: x/x
 | 
      
         | 228 |  |  | |       d4: x/x
 | 
      
         | 229 |  |  | |       d5: x/x
 | 
      
         | 230 |  |  | |       d6: x/ILOG
 | 
      
         | 231 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 232 |  |  | |       a0: ptr for original operand/final result
 | 
      
         | 233 |  |  | |       a1: x/x
 | 
      
         | 234 |  |  | |       a2: x/x
 | 
      
         | 235 |  |  | |       fp0: x/float(ILOG)
 | 
      
         | 236 |  |  | |       fp1: x/x
 | 
      
         | 237 |  |  | |       fp2: x/x
 | 
      
         | 238 |  |  | |       F_SCR1:x/x
 | 
      
         | 239 |  |  | |       F_SCR2:Abs(X)/Abs(X) with $3fff exponent
 | 
      
         | 240 |  |  | |       L_SCR1:x/x
 | 
      
         | 241 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 242 |  |  |  
 | 
      
         | 243 |  |  |         tstb    BINDEC_FLG(%a6) |check for denorm
 | 
      
         | 244 |  |  |         beqs    A3_cont         |if clr, continue with norm
 | 
      
         | 245 |  |  |         movel   #-4933,%d6      |force ILOG = -4933
 | 
      
         | 246 |  |  |         bras    A4_str
 | 
      
         | 247 |  |  | A3_cont:
 | 
      
         | 248 |  |  |         movew   FP_SCR2(%a6),%d0        |move exp to d0
 | 
      
         | 249 |  |  |         movew   #0x3fff,FP_SCR2(%a6) |replace exponent with 0x3fff
 | 
      
         | 250 |  |  |         fmovex  FP_SCR2(%a6),%fp0       |now fp0 has 1.f
 | 
      
         | 251 |  |  |         subw    #0x3fff,%d0     |strip off bias
 | 
      
         | 252 |  |  |         faddw   %d0,%fp0                |add in exp
 | 
      
         | 253 |  |  |         fsubs   FONE,%fp0       |subtract off 1.0
 | 
      
         | 254 |  |  |         fbge    pos_res         |if pos, branch
 | 
      
         | 255 |  |  |         fmulx   LOG2UP1,%fp0    |if neg, mul by LOG2UP1
 | 
      
         | 256 |  |  |         fmovel  %fp0,%d6                |put ILOG in d6 as a lword
 | 
      
         | 257 |  |  |         bras    A4_str          |go move out ILOG
 | 
      
         | 258 |  |  | pos_res:
 | 
      
         | 259 |  |  |         fmulx   LOG2,%fp0       |if pos, mul by LOG2
 | 
      
         | 260 |  |  |         fmovel  %fp0,%d6                |put ILOG in d6 as a lword
 | 
      
         | 261 |  |  |  
 | 
      
         | 262 |  |  |  
 | 
      
         | 263 |  |  | | A4. Clr INEX bit.
 | 
      
         | 264 |  |  | |     The operation in A3 above may have set INEX2.
 | 
      
         | 265 |  |  |  
 | 
      
         | 266 |  |  | A4_str:
 | 
      
         | 267 |  |  |         fmovel  #0,%FPSR                |zero all of fpsr - nothing needed
 | 
      
         | 268 |  |  |  
 | 
      
         | 269 |  |  |  
 | 
      
         | 270 |  |  | | A5. Set ICTR = 0;
 | 
      
         | 271 |  |  | |     ICTR is a flag used in A13.  It must be set before the
 | 
      
         | 272 |  |  | |     loop entry A6. The lower word of d5 is used for ICTR.
 | 
      
         | 273 |  |  |  
 | 
      
         | 274 |  |  |         clrw    %d5             |clear ICTR
 | 
      
         | 275 |  |  |  
 | 
      
         | 276 |  |  |  
 | 
      
         | 277 |  |  | | A6. Calculate LEN.
 | 
      
         | 278 |  |  | |     LEN is the number of digits to be displayed.  The k-factor
 | 
      
         | 279 |  |  | |     can dictate either the total number of digits, if it is
 | 
      
         | 280 |  |  | |     a positive number, or the number of digits after the
 | 
      
         | 281 |  |  | |     original decimal point which are to be included as
 | 
      
         | 282 |  |  | |     significant.  See the 68882 manual for examples.
 | 
      
         | 283 |  |  | |     If LEN is computed to be greater than 17, set OPERR in
 | 
      
         | 284 |  |  | |     USER_FPSR.  LEN is stored in d4.
 | 
      
         | 285 |  |  | |
 | 
      
         | 286 |  |  | | Register usage:
 | 
      
         | 287 |  |  | |       Input/Output
 | 
      
         | 288 |  |  | |       d0: exponent/Unchanged
 | 
      
         | 289 |  |  | |       d2: x/x/scratch
 | 
      
         | 290 |  |  | |       d3: x/x
 | 
      
         | 291 |  |  | |       d4: exc picture/LEN
 | 
      
         | 292 |  |  | |       d5: ICTR/Unchanged
 | 
      
         | 293 |  |  | |       d6: ILOG/Unchanged
 | 
      
         | 294 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 295 |  |  | |       a0: ptr for original operand/final result
 | 
      
         | 296 |  |  | |       a1: x/x
 | 
      
         | 297 |  |  | |       a2: x/x
 | 
      
         | 298 |  |  | |       fp0: float(ILOG)/Unchanged
 | 
      
         | 299 |  |  | |       fp1: x/x
 | 
      
         | 300 |  |  | |       fp2: x/x
 | 
      
         | 301 |  |  | |       F_SCR1:x/x
 | 
      
         | 302 |  |  | |       F_SCR2:Abs(X) with $3fff exponent/Unchanged
 | 
      
         | 303 |  |  | |       L_SCR1:x/x
 | 
      
         | 304 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 305 |  |  |  
 | 
      
         | 306 |  |  | A6_str:
 | 
      
         | 307 |  |  |         tstl    %d7             |branch on sign of k
 | 
      
         | 308 |  |  |         bles    k_neg           |if k <= 0, LEN = ILOG + 1 - k
 | 
      
         | 309 |  |  |         movel   %d7,%d4         |if k > 0, LEN = k
 | 
      
         | 310 |  |  |         bras    len_ck          |skip to LEN check
 | 
      
         | 311 |  |  | k_neg:
 | 
      
         | 312 |  |  |         movel   %d6,%d4         |first load ILOG to d4
 | 
      
         | 313 |  |  |         subl    %d7,%d4         |subtract off k
 | 
      
         | 314 |  |  |         addql   #1,%d4          |add in the 1
 | 
      
         | 315 |  |  | len_ck:
 | 
      
         | 316 |  |  |         tstl    %d4             |LEN check: branch on sign of LEN
 | 
      
         | 317 |  |  |         bles    LEN_ng          |if neg, set LEN = 1
 | 
      
         | 318 |  |  |         cmpl    #17,%d4         |test if LEN > 17
 | 
      
         | 319 |  |  |         bles    A7_str          |if not, forget it
 | 
      
         | 320 |  |  |         movel   #17,%d4         |set max LEN = 17
 | 
      
         | 321 |  |  |         tstl    %d7             |if negative, never set OPERR
 | 
      
         | 322 |  |  |         bles    A7_str          |if positive, continue
 | 
      
         | 323 |  |  |         orl     #opaop_mask,USER_FPSR(%a6) |set OPERR & AIOP in USER_FPSR
 | 
      
         | 324 |  |  |         bras    A7_str          |finished here
 | 
      
         | 325 |  |  | LEN_ng:
 | 
      
         | 326 |  |  |         moveql  #1,%d4          |min LEN is 1
 | 
      
         | 327 |  |  |  
 | 
      
         | 328 |  |  |  
 | 
      
         | 329 |  |  | | A7. Calculate SCALE.
 | 
      
         | 330 |  |  | |     SCALE is equal to 10^ISCALE, where ISCALE is the number
 | 
      
         | 331 |  |  | |     of decimal places needed to insure LEN integer digits
 | 
      
         | 332 |  |  | |     in the output before conversion to bcd. LAMBDA is the sign
 | 
      
         | 333 |  |  | |     of ISCALE, used in A9.  Fp1 contains 10^^(abs(ISCALE)) using
 | 
      
         | 334 |  |  | |     the rounding mode as given in the following table (see
 | 
      
         | 335 |  |  | |     Coonen, p. 7.23 as ref.; however, the SCALE variable is
 | 
      
         | 336 |  |  | |     of opposite sign in bindec.sa from Coonen).
 | 
      
         | 337 |  |  | |
 | 
      
         | 338 |  |  | |       Initial                                 USE
 | 
      
         | 339 |  |  | |       FPCR[6:5]       LAMBDA  SIGN(X)         FPCR[6:5]
 | 
      
         | 340 |  |  | |       ----------------------------------------------
 | 
      
         | 341 |  |  | |        RN     00         0       0            00/0    RN
 | 
      
         | 342 |  |  | |        RN     00         0       1            00/0    RN
 | 
      
         | 343 |  |  | |        RN     00         1       0            00/0    RN
 | 
      
         | 344 |  |  | |        RN     00         1       1            00/0    RN
 | 
      
         | 345 |  |  | |        RZ     01         0       0            11/3    RP
 | 
      
         | 346 |  |  | |        RZ     01         0       1            11/3    RP
 | 
      
         | 347 |  |  | |        RZ     01         1       0            10/2    RM
 | 
      
         | 348 |  |  | |        RZ     01         1       1            10/2    RM
 | 
      
         | 349 |  |  | |        RM     10         0       0            11/3    RP
 | 
      
         | 350 |  |  | |        RM     10         0       1            10/2    RM
 | 
      
         | 351 |  |  | |        RM     10         1       0            10/2    RM
 | 
      
         | 352 |  |  | |        RM     10         1       1            11/3    RP
 | 
      
         | 353 |  |  | |        RP     11         0       0            10/2    RM
 | 
      
         | 354 |  |  | |        RP     11         0       1            11/3    RP
 | 
      
         | 355 |  |  | |        RP     11         1       0            11/3    RP
 | 
      
         | 356 |  |  | |        RP     11         1       1            10/2    RM
 | 
      
         | 357 |  |  | |
 | 
      
         | 358 |  |  | | Register usage:
 | 
      
         | 359 |  |  | |       Input/Output
 | 
      
         | 360 |  |  | |       d0: exponent/scratch - final is 0
 | 
      
         | 361 |  |  | |       d2: x/0 or 24 for A9
 | 
      
         | 362 |  |  | |       d3: x/scratch - offset ptr into PTENRM array
 | 
      
         | 363 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 364 |  |  | |       d5: 0/ICTR:LAMBDA
 | 
      
         | 365 |  |  | |       d6: ILOG/ILOG or k if ((k<=0)&(ILOG
 | 
      
         | 366 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 367 |  |  | |       a0: ptr for original operand/final result
 | 
      
         | 368 |  |  | |       a1: x/ptr to PTENRM array
 | 
      
         | 369 |  |  | |       a2: x/x
 | 
      
         | 370 |  |  | |       fp0: float(ILOG)/Unchanged
 | 
      
         | 371 |  |  | |       fp1: x/10^ISCALE
 | 
      
         | 372 |  |  | |       fp2: x/x
 | 
      
         | 373 |  |  | |       F_SCR1:x/x
 | 
      
         | 374 |  |  | |       F_SCR2:Abs(X) with $3fff exponent/Unchanged
 | 
      
         | 375 |  |  | |       L_SCR1:x/x
 | 
      
         | 376 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 377 |  |  |  
 | 
      
         | 378 |  |  | A7_str:
 | 
      
         | 379 |  |  |         tstl    %d7             |test sign of k
 | 
      
         | 380 |  |  |         bgts    k_pos           |if pos and > 0, skip this
 | 
      
         | 381 |  |  |         cmpl    %d6,%d7         |test k - ILOG
 | 
      
         | 382 |  |  |         blts    k_pos           |if ILOG >= k, skip this
 | 
      
         | 383 |  |  |         movel   %d7,%d6         |if ((k<0) & (ILOG < k)) ILOG = k
 | 
      
         | 384 |  |  | k_pos:
 | 
      
         | 385 |  |  |         movel   %d6,%d0         |calc ILOG + 1 - LEN in d0
 | 
      
         | 386 |  |  |         addql   #1,%d0          |add the 1
 | 
      
         | 387 |  |  |         subl    %d4,%d0         |sub off LEN
 | 
      
         | 388 |  |  |         swap    %d5             |use upper word of d5 for LAMBDA
 | 
      
         | 389 |  |  |         clrw    %d5             |set it zero initially
 | 
      
         | 390 |  |  |         clrw    %d2             |set up d2 for very small case
 | 
      
         | 391 |  |  |         tstl    %d0             |test sign of ISCALE
 | 
      
         | 392 |  |  |         bges    iscale          |if pos, skip next inst
 | 
      
         | 393 |  |  |         addqw   #1,%d5          |if neg, set LAMBDA true
 | 
      
         | 394 |  |  |         cmpl    #0xffffecd4,%d0 |test iscale <= -4908
 | 
      
         | 395 |  |  |         bgts    no_inf          |if false, skip rest
 | 
      
         | 396 |  |  |         addil   #24,%d0         |add in 24 to iscale
 | 
      
         | 397 |  |  |         movel   #24,%d2         |put 24 in d2 for A9
 | 
      
         | 398 |  |  | no_inf:
 | 
      
         | 399 |  |  |         negl    %d0             |and take abs of ISCALE
 | 
      
         | 400 |  |  | iscale:
 | 
      
         | 401 |  |  |         fmoves  FONE,%fp1       |init fp1 to 1
 | 
      
         | 402 |  |  |         bfextu  USER_FPCR(%a6){#26:#2},%d1 |get initial rmode bits
 | 
      
         | 403 |  |  |         lslw    #1,%d1          |put them in bits 2:1
 | 
      
         | 404 |  |  |         addw    %d5,%d1         |add in LAMBDA
 | 
      
         | 405 |  |  |         lslw    #1,%d1          |put them in bits 3:1
 | 
      
         | 406 |  |  |         tstl    L_SCR2(%a6)     |test sign of original x
 | 
      
         | 407 |  |  |         bges    x_pos           |if pos, don't set bit 0
 | 
      
         | 408 |  |  |         addql   #1,%d1          |if neg, set bit 0
 | 
      
         | 409 |  |  | x_pos:
 | 
      
         | 410 |  |  |         leal    RBDTBL,%a2      |load rbdtbl base
 | 
      
         | 411 |  |  |         moveb   (%a2,%d1),%d3   |load d3 with new rmode
 | 
      
         | 412 |  |  |         lsll    #4,%d3          |put bits in proper position
 | 
      
         | 413 |  |  |         fmovel  %d3,%fpcr               |load bits into fpu
 | 
      
         | 414 |  |  |         lsrl    #4,%d3          |put bits in proper position
 | 
      
         | 415 |  |  |         tstb    %d3             |decode new rmode for pten table
 | 
      
         | 416 |  |  |         bnes    not_rn          |if zero, it is RN
 | 
      
         | 417 |  |  |         leal    PTENRN,%a1      |load a1 with RN table base
 | 
      
         | 418 |  |  |         bras    rmode           |exit decode
 | 
      
         | 419 |  |  | not_rn:
 | 
      
         | 420 |  |  |         lsrb    #1,%d3          |get lsb in carry
 | 
      
         | 421 |  |  |         bccs    not_rp          |if carry clear, it is RM
 | 
      
         | 422 |  |  |         leal    PTENRP,%a1      |load a1 with RP table base
 | 
      
         | 423 |  |  |         bras    rmode           |exit decode
 | 
      
         | 424 |  |  | not_rp:
 | 
      
         | 425 |  |  |         leal    PTENRM,%a1      |load a1 with RM table base
 | 
      
         | 426 |  |  | rmode:
 | 
      
         | 427 |  |  |         clrl    %d3             |clr table index
 | 
      
         | 428 |  |  | e_loop:
 | 
      
         | 429 |  |  |         lsrl    #1,%d0          |shift next bit into carry
 | 
      
         | 430 |  |  |         bccs    e_next          |if zero, skip the mul
 | 
      
         | 431 |  |  |         fmulx   (%a1,%d3),%fp1  |mul by 10**(d3_bit_no)
 | 
      
         | 432 |  |  | e_next:
 | 
      
         | 433 |  |  |         addl    #12,%d3         |inc d3 to next pwrten table entry
 | 
      
         | 434 |  |  |         tstl    %d0             |test if ISCALE is zero
 | 
      
         | 435 |  |  |         bnes    e_loop          |if not, loop
 | 
      
         | 436 |  |  |  
 | 
      
         | 437 |  |  |  
 | 
      
         | 438 |  |  | | A8. Clr INEX; Force RZ.
 | 
      
         | 439 |  |  | |     The operation in A3 above may have set INEX2.
 | 
      
         | 440 |  |  | |     RZ mode is forced for the scaling operation to insure
 | 
      
         | 441 |  |  | |     only one rounding error.  The grs bits are collected in
 | 
      
         | 442 |  |  | |     the INEX flag for use in A10.
 | 
      
         | 443 |  |  | |
 | 
      
         | 444 |  |  | | Register usage:
 | 
      
         | 445 |  |  | |       Input/Output
 | 
      
         | 446 |  |  |  
 | 
      
         | 447 |  |  |         fmovel  #0,%FPSR                |clr INEX
 | 
      
         | 448 |  |  |         fmovel  #rz_mode,%FPCR  |set RZ rounding mode
 | 
      
         | 449 |  |  |  
 | 
      
         | 450 |  |  |  
 | 
      
         | 451 |  |  | | A9. Scale X -> Y.
 | 
      
         | 452 |  |  | |     The mantissa is scaled to the desired number of significant
 | 
      
         | 453 |  |  | |     digits.  The excess digits are collected in INEX2. If mul,
 | 
      
         | 454 |  |  | |     Check d2 for excess 10 exponential value.  If not zero,
 | 
      
         | 455 |  |  | |     the iscale value would have caused the pwrten calculation
 | 
      
         | 456 |  |  | |     to overflow.  Only a negative iscale can cause this, so
 | 
      
         | 457 |  |  | |     multiply by 10^(d2), which is now only allowed to be 24,
 | 
      
         | 458 |  |  | |     with a multiply by 10^8 and 10^16, which is exact since
 | 
      
         | 459 |  |  | |     10^24 is exact.  If the input was denormalized, we must
 | 
      
         | 460 |  |  | |     create a busy stack frame with the mul command and the
 | 
      
         | 461 |  |  | |     two operands, and allow the fpu to complete the multiply.
 | 
      
         | 462 |  |  | |
 | 
      
         | 463 |  |  | | Register usage:
 | 
      
         | 464 |  |  | |       Input/Output
 | 
      
         | 465 |  |  | |       d0: FPCR with RZ mode/Unchanged
 | 
      
         | 466 |  |  | |       d2: 0 or 24/unchanged
 | 
      
         | 467 |  |  | |       d3: x/x
 | 
      
         | 468 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 469 |  |  | |       d5: ICTR:LAMBDA
 | 
      
         | 470 |  |  | |       d6: ILOG/Unchanged
 | 
      
         | 471 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 472 |  |  | |       a0: ptr for original operand/final result
 | 
      
         | 473 |  |  | |       a1: ptr to PTENRM array/Unchanged
 | 
      
         | 474 |  |  | |       a2: x/x
 | 
      
         | 475 |  |  | |       fp0: float(ILOG)/X adjusted for SCALE (Y)
 | 
      
         | 476 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 477 |  |  | |       fp2: x/x
 | 
      
         | 478 |  |  | |       F_SCR1:x/x
 | 
      
         | 479 |  |  | |       F_SCR2:Abs(X) with $3fff exponent/Unchanged
 | 
      
         | 480 |  |  | |       L_SCR1:x/x
 | 
      
         | 481 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 482 |  |  |  
 | 
      
         | 483 |  |  | A9_str:
 | 
      
         | 484 |  |  |         fmovex  (%a0),%fp0      |load X from memory
 | 
      
         | 485 |  |  |         fabsx   %fp0            |use abs(X)
 | 
      
         | 486 |  |  |         tstw    %d5             |LAMBDA is in lower word of d5
 | 
      
         | 487 |  |  |         bne     sc_mul          |if neg (LAMBDA = 1), scale by mul
 | 
      
         | 488 |  |  |         fdivx   %fp1,%fp0               |calculate X / SCALE -> Y to fp0
 | 
      
         | 489 |  |  |         bras    A10_st          |branch to A10
 | 
      
         | 490 |  |  |  
 | 
      
         | 491 |  |  | sc_mul:
 | 
      
         | 492 |  |  |         tstb    BINDEC_FLG(%a6) |check for denorm
 | 
      
         | 493 |  |  |         beqs    A9_norm         |if norm, continue with mul
 | 
      
         | 494 |  |  |         fmovemx %fp1-%fp1,-(%a7)        |load ETEMP with 10^ISCALE
 | 
      
         | 495 |  |  |         movel   8(%a0),-(%a7)   |load FPTEMP with input arg
 | 
      
         | 496 |  |  |         movel   4(%a0),-(%a7)
 | 
      
         | 497 |  |  |         movel   (%a0),-(%a7)
 | 
      
         | 498 |  |  |         movel   #18,%d3         |load count for busy stack
 | 
      
         | 499 |  |  | A9_loop:
 | 
      
         | 500 |  |  |         clrl    -(%a7)          |clear lword on stack
 | 
      
         | 501 |  |  |         dbf     %d3,A9_loop
 | 
      
         | 502 |  |  |         moveb   VER_TMP(%a6),(%a7) |write current version number
 | 
      
         | 503 |  |  |         moveb   #BUSY_SIZE-4,1(%a7) |write current busy size
 | 
      
         | 504 |  |  |         moveb   #0x10,0x44(%a7) |set fcefpte[15] bit
 | 
      
         | 505 |  |  |         movew   #0x0023,0x40(%a7)       |load cmdreg1b with mul command
 | 
      
         | 506 |  |  |         moveb   #0xfe,0x8(%a7)  |load all 1s to cu savepc
 | 
      
         | 507 |  |  |         frestore (%a7)+         |restore frame to fpu for completion
 | 
      
         | 508 |  |  |         fmulx   36(%a1),%fp0    |multiply fp0 by 10^8
 | 
      
         | 509 |  |  |         fmulx   48(%a1),%fp0    |multiply fp0 by 10^16
 | 
      
         | 510 |  |  |         bras    A10_st
 | 
      
         | 511 |  |  | A9_norm:
 | 
      
         | 512 |  |  |         tstw    %d2             |test for small exp case
 | 
      
         | 513 |  |  |         beqs    A9_con          |if zero, continue as normal
 | 
      
         | 514 |  |  |         fmulx   36(%a1),%fp0    |multiply fp0 by 10^8
 | 
      
         | 515 |  |  |         fmulx   48(%a1),%fp0    |multiply fp0 by 10^16
 | 
      
         | 516 |  |  | A9_con:
 | 
      
         | 517 |  |  |         fmulx   %fp1,%fp0               |calculate X * SCALE -> Y to fp0
 | 
      
         | 518 |  |  |  
 | 
      
         | 519 |  |  |  
 | 
      
         | 520 |  |  | | A10. Or in INEX.
 | 
      
         | 521 |  |  | |      If INEX is set, round error occurred.  This is compensated
 | 
      
         | 522 |  |  | |      for by 'or-ing' in the INEX2 flag to the lsb of Y.
 | 
      
         | 523 |  |  | |
 | 
      
         | 524 |  |  | | Register usage:
 | 
      
         | 525 |  |  | |       Input/Output
 | 
      
         | 526 |  |  | |       d0: FPCR with RZ mode/FPSR with INEX2 isolated
 | 
      
         | 527 |  |  | |       d2: x/x
 | 
      
         | 528 |  |  | |       d3: x/x
 | 
      
         | 529 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 530 |  |  | |       d5: ICTR:LAMBDA
 | 
      
         | 531 |  |  | |       d6: ILOG/Unchanged
 | 
      
         | 532 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 533 |  |  | |       a0: ptr for original operand/final result
 | 
      
         | 534 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 535 |  |  | |       a2: x/ptr to FP_SCR2(a6)
 | 
      
         | 536 |  |  | |       fp0: Y/Y with lsb adjusted
 | 
      
         | 537 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 538 |  |  | |       fp2: x/x
 | 
      
         | 539 |  |  |  
 | 
      
         | 540 |  |  | A10_st:
 | 
      
         | 541 |  |  |         fmovel  %FPSR,%d0               |get FPSR
 | 
      
         | 542 |  |  |         fmovex  %fp0,FP_SCR2(%a6)       |move Y to memory
 | 
      
         | 543 |  |  |         leal    FP_SCR2(%a6),%a2        |load a2 with ptr to FP_SCR2
 | 
      
         | 544 |  |  |         btstl   #9,%d0          |check if INEX2 set
 | 
      
         | 545 |  |  |         beqs    A11_st          |if clear, skip rest
 | 
      
         | 546 |  |  |         oril    #1,8(%a2)       |or in 1 to lsb of mantissa
 | 
      
         | 547 |  |  |         fmovex  FP_SCR2(%a6),%fp0       |write adjusted Y back to fpu
 | 
      
         | 548 |  |  |  
 | 
      
         | 549 |  |  |  
 | 
      
         | 550 |  |  | | A11. Restore original FPCR; set size ext.
 | 
      
         | 551 |  |  | |      Perform FINT operation in the user's rounding mode.  Keep
 | 
      
         | 552 |  |  | |      the size to extended.  The sintdo entry point in the sint
 | 
      
         | 553 |  |  | |      routine expects the FPCR value to be in USER_FPCR for
 | 
      
         | 554 |  |  | |      mode and precision.  The original FPCR is saved in L_SCR1.
 | 
      
         | 555 |  |  |  
 | 
      
         | 556 |  |  | A11_st:
 | 
      
         | 557 |  |  |         movel   USER_FPCR(%a6),L_SCR1(%a6) |save it for later
 | 
      
         | 558 |  |  |         andil   #0x00000030,USER_FPCR(%a6) |set size to ext,
 | 
      
         | 559 |  |  | |                                       ;block exceptions
 | 
      
         | 560 |  |  |  
 | 
      
         | 561 |  |  |  
 | 
      
         | 562 |  |  | | A12. Calculate YINT = FINT(Y) according to user's rounding mode.
 | 
      
         | 563 |  |  | |      The FPSP routine sintd0 is used.  The output is in fp0.
 | 
      
         | 564 |  |  | |
 | 
      
         | 565 |  |  | | Register usage:
 | 
      
         | 566 |  |  | |       Input/Output
 | 
      
         | 567 |  |  | |       d0: FPSR with AINEX cleared/FPCR with size set to ext
 | 
      
         | 568 |  |  | |       d2: x/x/scratch
 | 
      
         | 569 |  |  | |       d3: x/x
 | 
      
         | 570 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 571 |  |  | |       d5: ICTR:LAMBDA/Unchanged
 | 
      
         | 572 |  |  | |       d6: ILOG/Unchanged
 | 
      
         | 573 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 574 |  |  | |       a0: ptr for original operand/src ptr for sintdo
 | 
      
         | 575 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 576 |  |  | |       a2: ptr to FP_SCR2(a6)/Unchanged
 | 
      
         | 577 |  |  | |       a6: temp pointer to FP_SCR2(a6) - orig value saved and restored
 | 
      
         | 578 |  |  | |       fp0: Y/YINT
 | 
      
         | 579 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 580 |  |  | |       fp2: x/x
 | 
      
         | 581 |  |  | |       F_SCR1:x/x
 | 
      
         | 582 |  |  | |       F_SCR2:Y adjusted for inex/Y with original exponent
 | 
      
         | 583 |  |  | |       L_SCR1:x/original USER_FPCR
 | 
      
         | 584 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 585 |  |  |  
 | 
      
         | 586 |  |  | A12_st:
 | 
      
         | 587 |  |  |         moveml  %d0-%d1/%a0-%a1,-(%a7)  |save regs used by sintd0
 | 
      
         | 588 |  |  |         movel   L_SCR1(%a6),-(%a7)
 | 
      
         | 589 |  |  |         movel   L_SCR2(%a6),-(%a7)
 | 
      
         | 590 |  |  |         leal    FP_SCR2(%a6),%a0                |a0 is ptr to F_SCR2(a6)
 | 
      
         | 591 |  |  |         fmovex  %fp0,(%a0)              |move Y to memory at FP_SCR2(a6)
 | 
      
         | 592 |  |  |         tstl    L_SCR2(%a6)             |test sign of original operand
 | 
      
         | 593 |  |  |         bges    do_fint                 |if pos, use Y
 | 
      
         | 594 |  |  |         orl     #0x80000000,(%a0)               |if neg, use -Y
 | 
      
         | 595 |  |  | do_fint:
 | 
      
         | 596 |  |  |         movel   USER_FPSR(%a6),-(%a7)
 | 
      
         | 597 |  |  |         bsr     sintdo                  |sint routine returns int in fp0
 | 
      
         | 598 |  |  |         moveb   (%a7),USER_FPSR(%a6)
 | 
      
         | 599 |  |  |         addl    #4,%a7
 | 
      
         | 600 |  |  |         movel   (%a7)+,L_SCR2(%a6)
 | 
      
         | 601 |  |  |         movel   (%a7)+,L_SCR1(%a6)
 | 
      
         | 602 |  |  |         moveml  (%a7)+,%d0-%d1/%a0-%a1  |restore regs used by sint
 | 
      
         | 603 |  |  |         movel   L_SCR2(%a6),FP_SCR2(%a6)        |restore original exponent
 | 
      
         | 604 |  |  |         movel   L_SCR1(%a6),USER_FPCR(%a6) |restore user's FPCR
 | 
      
         | 605 |  |  |  
 | 
      
         | 606 |  |  |  
 | 
      
         | 607 |  |  | | A13. Check for LEN digits.
 | 
      
         | 608 |  |  | |      If the int operation results in more than LEN digits,
 | 
      
         | 609 |  |  | |      or less than LEN -1 digits, adjust ILOG and repeat from
 | 
      
         | 610 |  |  | |      A6.  This test occurs only on the first pass.  If the
 | 
      
         | 611 |  |  | |      result is exactly 10^LEN, decrement ILOG and divide
 | 
      
         | 612 |  |  | |      the mantissa by 10.  The calculation of 10^LEN cannot
 | 
      
         | 613 |  |  | |      be inexact, since all powers of ten upto 10^27 are exact
 | 
      
         | 614 |  |  | |      in extended precision, so the use of a previous power-of-ten
 | 
      
         | 615 |  |  | |      table will introduce no error.
 | 
      
         | 616 |  |  | |
 | 
      
         | 617 |  |  | |
 | 
      
         | 618 |  |  | | Register usage:
 | 
      
         | 619 |  |  | |       Input/Output
 | 
      
         | 620 |  |  | |       d0: FPCR with size set to ext/scratch final = 0
 | 
      
         | 621 |  |  | |       d2: x/x
 | 
      
         | 622 |  |  | |       d3: x/scratch final = x
 | 
      
         | 623 |  |  | |       d4: LEN/LEN adjusted
 | 
      
         | 624 |  |  | |       d5: ICTR:LAMBDA/LAMBDA:ICTR
 | 
      
         | 625 |  |  | |       d6: ILOG/ILOG adjusted
 | 
      
         | 626 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 627 |  |  | |       a0: pointer into memory for packed bcd string formation
 | 
      
         | 628 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 629 |  |  | |       a2: ptr to FP_SCR2(a6)/Unchanged
 | 
      
         | 630 |  |  | |       fp0: int portion of Y/abs(YINT) adjusted
 | 
      
         | 631 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 632 |  |  | |       fp2: x/10^LEN
 | 
      
         | 633 |  |  | |       F_SCR1:x/x
 | 
      
         | 634 |  |  | |       F_SCR2:Y with original exponent/Unchanged
 | 
      
         | 635 |  |  | |       L_SCR1:original USER_FPCR/Unchanged
 | 
      
         | 636 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 637 |  |  |  
 | 
      
         | 638 |  |  | A13_st:
 | 
      
         | 639 |  |  |         swap    %d5             |put ICTR in lower word of d5
 | 
      
         | 640 |  |  |         tstw    %d5             |check if ICTR = 0
 | 
      
         | 641 |  |  |         bne     not_zr          |if non-zero, go to second test
 | 
      
         | 642 |  |  | |
 | 
      
         | 643 |  |  | | Compute 10^(LEN-1)
 | 
      
         | 644 |  |  | |
 | 
      
         | 645 |  |  |         fmoves  FONE,%fp2       |init fp2 to 1.0
 | 
      
         | 646 |  |  |         movel   %d4,%d0         |put LEN in d0
 | 
      
         | 647 |  |  |         subql   #1,%d0          |d0 = LEN -1
 | 
      
         | 648 |  |  |         clrl    %d3             |clr table index
 | 
      
         | 649 |  |  | l_loop:
 | 
      
         | 650 |  |  |         lsrl    #1,%d0          |shift next bit into carry
 | 
      
         | 651 |  |  |         bccs    l_next          |if zero, skip the mul
 | 
      
         | 652 |  |  |         fmulx   (%a1,%d3),%fp2  |mul by 10**(d3_bit_no)
 | 
      
         | 653 |  |  | l_next:
 | 
      
         | 654 |  |  |         addl    #12,%d3         |inc d3 to next pwrten table entry
 | 
      
         | 655 |  |  |         tstl    %d0             |test if LEN is zero
 | 
      
         | 656 |  |  |         bnes    l_loop          |if not, loop
 | 
      
         | 657 |  |  | |
 | 
      
         | 658 |  |  | | 10^LEN-1 is computed for this test and A14.  If the input was
 | 
      
         | 659 |  |  | | denormalized, check only the case in which YINT > 10^LEN.
 | 
      
         | 660 |  |  | |
 | 
      
         | 661 |  |  |         tstb    BINDEC_FLG(%a6) |check if input was norm
 | 
      
         | 662 |  |  |         beqs    A13_con         |if norm, continue with checking
 | 
      
         | 663 |  |  |         fabsx   %fp0            |take abs of YINT
 | 
      
         | 664 |  |  |         bra     test_2
 | 
      
         | 665 |  |  | |
 | 
      
         | 666 |  |  | | Compare abs(YINT) to 10^(LEN-1) and 10^LEN
 | 
      
         | 667 |  |  | |
 | 
      
         | 668 |  |  | A13_con:
 | 
      
         | 669 |  |  |         fabsx   %fp0            |take abs of YINT
 | 
      
         | 670 |  |  |         fcmpx   %fp2,%fp0               |compare abs(YINT) with 10^(LEN-1)
 | 
      
         | 671 |  |  |         fbge    test_2          |if greater, do next test
 | 
      
         | 672 |  |  |         subql   #1,%d6          |subtract 1 from ILOG
 | 
      
         | 673 |  |  |         movew   #1,%d5          |set ICTR
 | 
      
         | 674 |  |  |         fmovel  #rm_mode,%FPCR  |set rmode to RM
 | 
      
         | 675 |  |  |         fmuls   FTEN,%fp2       |compute 10^LEN
 | 
      
         | 676 |  |  |         bra     A6_str          |return to A6 and recompute YINT
 | 
      
         | 677 |  |  | test_2:
 | 
      
         | 678 |  |  |         fmuls   FTEN,%fp2       |compute 10^LEN
 | 
      
         | 679 |  |  |         fcmpx   %fp2,%fp0               |compare abs(YINT) with 10^LEN
 | 
      
         | 680 |  |  |         fblt    A14_st          |if less, all is ok, go to A14
 | 
      
         | 681 |  |  |         fbgt    fix_ex          |if greater, fix and redo
 | 
      
         | 682 |  |  |         fdivs   FTEN,%fp0       |if equal, divide by 10
 | 
      
         | 683 |  |  |         addql   #1,%d6          | and inc ILOG
 | 
      
         | 684 |  |  |         bras    A14_st          | and continue elsewhere
 | 
      
         | 685 |  |  | fix_ex:
 | 
      
         | 686 |  |  |         addql   #1,%d6          |increment ILOG by 1
 | 
      
         | 687 |  |  |         movew   #1,%d5          |set ICTR
 | 
      
         | 688 |  |  |         fmovel  #rm_mode,%FPCR  |set rmode to RM
 | 
      
         | 689 |  |  |         bra     A6_str          |return to A6 and recompute YINT
 | 
      
         | 690 |  |  | |
 | 
      
         | 691 |  |  | | Since ICTR <> 0, we have already been through one adjustment,
 | 
      
         | 692 |  |  | | and shouldn't have another; this is to check if abs(YINT) = 10^LEN
 | 
      
         | 693 |  |  | | 10^LEN is again computed using whatever table is in a1 since the
 | 
      
         | 694 |  |  | | value calculated cannot be inexact.
 | 
      
         | 695 |  |  | |
 | 
      
         | 696 |  |  | not_zr:
 | 
      
         | 697 |  |  |         fmoves  FONE,%fp2       |init fp2 to 1.0
 | 
      
         | 698 |  |  |         movel   %d4,%d0         |put LEN in d0
 | 
      
         | 699 |  |  |         clrl    %d3             |clr table index
 | 
      
         | 700 |  |  | z_loop:
 | 
      
         | 701 |  |  |         lsrl    #1,%d0          |shift next bit into carry
 | 
      
         | 702 |  |  |         bccs    z_next          |if zero, skip the mul
 | 
      
         | 703 |  |  |         fmulx   (%a1,%d3),%fp2  |mul by 10**(d3_bit_no)
 | 
      
         | 704 |  |  | z_next:
 | 
      
         | 705 |  |  |         addl    #12,%d3         |inc d3 to next pwrten table entry
 | 
      
         | 706 |  |  |         tstl    %d0             |test if LEN is zero
 | 
      
         | 707 |  |  |         bnes    z_loop          |if not, loop
 | 
      
         | 708 |  |  |         fabsx   %fp0            |get abs(YINT)
 | 
      
         | 709 |  |  |         fcmpx   %fp2,%fp0               |check if abs(YINT) = 10^LEN
 | 
      
         | 710 |  |  |         fbne    A14_st          |if not, skip this
 | 
      
         | 711 |  |  |         fdivs   FTEN,%fp0       |divide abs(YINT) by 10
 | 
      
         | 712 |  |  |         addql   #1,%d6          |and inc ILOG by 1
 | 
      
         | 713 |  |  |         addql   #1,%d4          | and inc LEN
 | 
      
         | 714 |  |  |         fmuls   FTEN,%fp2       | if LEN++, the get 10^^LEN
 | 
      
         | 715 |  |  |  
 | 
      
         | 716 |  |  |  
 | 
      
         | 717 |  |  | | A14. Convert the mantissa to bcd.
 | 
      
         | 718 |  |  | |      The binstr routine is used to convert the LEN digit
 | 
      
         | 719 |  |  | |      mantissa to bcd in memory.  The input to binstr is
 | 
      
         | 720 |  |  | |      to be a fraction; i.e. (mantissa)/10^LEN and adjusted
 | 
      
         | 721 |  |  | |      such that the decimal point is to the left of bit 63.
 | 
      
         | 722 |  |  | |      The bcd digits are stored in the correct position in
 | 
      
         | 723 |  |  | |      the final string area in memory.
 | 
      
         | 724 |  |  | |
 | 
      
         | 725 |  |  | |
 | 
      
         | 726 |  |  | | Register usage:
 | 
      
         | 727 |  |  | |       Input/Output
 | 
      
         | 728 |  |  | |       d0: x/LEN call to binstr - final is 0
 | 
      
         | 729 |  |  | |       d1: x/0
 | 
      
         | 730 |  |  | |       d2: x/ms 32-bits of mant of abs(YINT)
 | 
      
         | 731 |  |  | |       d3: x/ls 32-bits of mant of abs(YINT)
 | 
      
         | 732 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 733 |  |  | |       d5: ICTR:LAMBDA/LAMBDA:ICTR
 | 
      
         | 734 |  |  | |       d6: ILOG
 | 
      
         | 735 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 736 |  |  | |       a0: pointer into memory for packed bcd string formation
 | 
      
         | 737 |  |  | |           /ptr to first mantissa byte in result string
 | 
      
         | 738 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 739 |  |  | |       a2: ptr to FP_SCR2(a6)/Unchanged
 | 
      
         | 740 |  |  | |       fp0: int portion of Y/abs(YINT) adjusted
 | 
      
         | 741 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 742 |  |  | |       fp2: 10^LEN/Unchanged
 | 
      
         | 743 |  |  | |       F_SCR1:x/Work area for final result
 | 
      
         | 744 |  |  | |       F_SCR2:Y with original exponent/Unchanged
 | 
      
         | 745 |  |  | |       L_SCR1:original USER_FPCR/Unchanged
 | 
      
         | 746 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 747 |  |  |  
 | 
      
         | 748 |  |  | A14_st:
 | 
      
         | 749 |  |  |         fmovel  #rz_mode,%FPCR  |force rz for conversion
 | 
      
         | 750 |  |  |         fdivx   %fp2,%fp0               |divide abs(YINT) by 10^LEN
 | 
      
         | 751 |  |  |         leal    FP_SCR1(%a6),%a0
 | 
      
         | 752 |  |  |         fmovex  %fp0,(%a0)      |move abs(YINT)/10^LEN to memory
 | 
      
         | 753 |  |  |         movel   4(%a0),%d2      |move 2nd word of FP_RES to d2
 | 
      
         | 754 |  |  |         movel   8(%a0),%d3      |move 3rd word of FP_RES to d3
 | 
      
         | 755 |  |  |         clrl    4(%a0)          |zero word 2 of FP_RES
 | 
      
         | 756 |  |  |         clrl    8(%a0)          |zero word 3 of FP_RES
 | 
      
         | 757 |  |  |         movel   (%a0),%d0               |move exponent to d0
 | 
      
         | 758 |  |  |         swap    %d0             |put exponent in lower word
 | 
      
         | 759 |  |  |         beqs    no_sft          |if zero, don't shift
 | 
      
         | 760 |  |  |         subil   #0x3ffd,%d0     |sub bias less 2 to make fract
 | 
      
         | 761 |  |  |         tstl    %d0             |check if > 1
 | 
      
         | 762 |  |  |         bgts    no_sft          |if so, don't shift
 | 
      
         | 763 |  |  |         negl    %d0             |make exp positive
 | 
      
         | 764 |  |  | m_loop:
 | 
      
         | 765 |  |  |         lsrl    #1,%d2          |shift d2:d3 right, add 0s
 | 
      
         | 766 |  |  |         roxrl   #1,%d3          |the number of places
 | 
      
         | 767 |  |  |         dbf     %d0,m_loop      |given in d0
 | 
      
         | 768 |  |  | no_sft:
 | 
      
         | 769 |  |  |         tstl    %d2             |check for mantissa of zero
 | 
      
         | 770 |  |  |         bnes    no_zr           |if not, go on
 | 
      
         | 771 |  |  |         tstl    %d3             |continue zero check
 | 
      
         | 772 |  |  |         beqs    zer_m           |if zero, go directly to binstr
 | 
      
         | 773 |  |  | no_zr:
 | 
      
         | 774 |  |  |         clrl    %d1             |put zero in d1 for addx
 | 
      
         | 775 |  |  |         addil   #0x00000080,%d3 |inc at bit 7
 | 
      
         | 776 |  |  |         addxl   %d1,%d2         |continue inc
 | 
      
         | 777 |  |  |         andil   #0xffffff80,%d3 |strip off lsb not used by 882
 | 
      
         | 778 |  |  | zer_m:
 | 
      
         | 779 |  |  |         movel   %d4,%d0         |put LEN in d0 for binstr call
 | 
      
         | 780 |  |  |         addql   #3,%a0          |a0 points to M16 byte in result
 | 
      
         | 781 |  |  |         bsr     binstr          |call binstr to convert mant
 | 
      
         | 782 |  |  |  
 | 
      
         | 783 |  |  |  
 | 
      
         | 784 |  |  | | A15. Convert the exponent to bcd.
 | 
      
         | 785 |  |  | |      As in A14 above, the exp is converted to bcd and the
 | 
      
         | 786 |  |  | |      digits are stored in the final string.
 | 
      
         | 787 |  |  | |
 | 
      
         | 788 |  |  | |      Digits are stored in L_SCR1(a6) on return from BINDEC as:
 | 
      
         | 789 |  |  | |
 | 
      
         | 790 |  |  | |        32               16 15                0
 | 
      
         | 791 |  |  | |       -----------------------------------------
 | 
      
         | 792 |  |  | |       |  0 | e3 | e2 | e1 | e4 |  X |  X |  X |
 | 
      
         | 793 |  |  | |       -----------------------------------------
 | 
      
         | 794 |  |  | |
 | 
      
         | 795 |  |  | | And are moved into their proper places in FP_SCR1.  If digit e4
 | 
      
         | 796 |  |  | | is non-zero, OPERR is signaled.  In all cases, all 4 digits are
 | 
      
         | 797 |  |  | | written as specified in the 881/882 manual for packed decimal.
 | 
      
         | 798 |  |  | |
 | 
      
         | 799 |  |  | | Register usage:
 | 
      
         | 800 |  |  | |       Input/Output
 | 
      
         | 801 |  |  | |       d0: x/LEN call to binstr - final is 0
 | 
      
         | 802 |  |  | |       d1: x/scratch (0);shift count for final exponent packing
 | 
      
         | 803 |  |  | |       d2: x/ms 32-bits of exp fraction/scratch
 | 
      
         | 804 |  |  | |       d3: x/ls 32-bits of exp fraction
 | 
      
         | 805 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 806 |  |  | |       d5: ICTR:LAMBDA/LAMBDA:ICTR
 | 
      
         | 807 |  |  | |       d6: ILOG
 | 
      
         | 808 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 809 |  |  | |       a0: ptr to result string/ptr to L_SCR1(a6)
 | 
      
         | 810 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 811 |  |  | |       a2: ptr to FP_SCR2(a6)/Unchanged
 | 
      
         | 812 |  |  | |       fp0: abs(YINT) adjusted/float(ILOG)
 | 
      
         | 813 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 814 |  |  | |       fp2: 10^LEN/Unchanged
 | 
      
         | 815 |  |  | |       F_SCR1:Work area for final result/BCD result
 | 
      
         | 816 |  |  | |       F_SCR2:Y with original exponent/ILOG/10^4
 | 
      
         | 817 |  |  | |       L_SCR1:original USER_FPCR/Exponent digits on return from binstr
 | 
      
         | 818 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 819 |  |  |  
 | 
      
         | 820 |  |  | A15_st:
 | 
      
         | 821 |  |  |         tstb    BINDEC_FLG(%a6) |check for denorm
 | 
      
         | 822 |  |  |         beqs    not_denorm
 | 
      
         | 823 |  |  |         ftstx   %fp0            |test for zero
 | 
      
         | 824 |  |  |         fbeq    den_zero        |if zero, use k-factor or 4933
 | 
      
         | 825 |  |  |         fmovel  %d6,%fp0                |float ILOG
 | 
      
         | 826 |  |  |         fabsx   %fp0            |get abs of ILOG
 | 
      
         | 827 |  |  |         bras    convrt
 | 
      
         | 828 |  |  | den_zero:
 | 
      
         | 829 |  |  |         tstl    %d7             |check sign of the k-factor
 | 
      
         | 830 |  |  |         blts    use_ilog        |if negative, use ILOG
 | 
      
         | 831 |  |  |         fmoves  F4933,%fp0      |force exponent to 4933
 | 
      
         | 832 |  |  |         bras    convrt          |do it
 | 
      
         | 833 |  |  | use_ilog:
 | 
      
         | 834 |  |  |         fmovel  %d6,%fp0                |float ILOG
 | 
      
         | 835 |  |  |         fabsx   %fp0            |get abs of ILOG
 | 
      
         | 836 |  |  |         bras    convrt
 | 
      
         | 837 |  |  | not_denorm:
 | 
      
         | 838 |  |  |         ftstx   %fp0            |test for zero
 | 
      
         | 839 |  |  |         fbne    not_zero        |if zero, force exponent
 | 
      
         | 840 |  |  |         fmoves  FONE,%fp0       |force exponent to 1
 | 
      
         | 841 |  |  |         bras    convrt          |do it
 | 
      
         | 842 |  |  | not_zero:
 | 
      
         | 843 |  |  |         fmovel  %d6,%fp0                |float ILOG
 | 
      
         | 844 |  |  |         fabsx   %fp0            |get abs of ILOG
 | 
      
         | 845 |  |  | convrt:
 | 
      
         | 846 |  |  |         fdivx   24(%a1),%fp0    |compute ILOG/10^4
 | 
      
         | 847 |  |  |         fmovex  %fp0,FP_SCR2(%a6)       |store fp0 in memory
 | 
      
         | 848 |  |  |         movel   4(%a2),%d2      |move word 2 to d2
 | 
      
         | 849 |  |  |         movel   8(%a2),%d3      |move word 3 to d3
 | 
      
         | 850 |  |  |         movew   (%a2),%d0               |move exp to d0
 | 
      
         | 851 |  |  |         beqs    x_loop_fin      |if zero, skip the shift
 | 
      
         | 852 |  |  |         subiw   #0x3ffd,%d0     |subtract off bias
 | 
      
         | 853 |  |  |         negw    %d0             |make exp positive
 | 
      
         | 854 |  |  | x_loop:
 | 
      
         | 855 |  |  |         lsrl    #1,%d2          |shift d2:d3 right
 | 
      
         | 856 |  |  |         roxrl   #1,%d3          |the number of places
 | 
      
         | 857 |  |  |         dbf     %d0,x_loop      |given in d0
 | 
      
         | 858 |  |  | x_loop_fin:
 | 
      
         | 859 |  |  |         clrl    %d1             |put zero in d1 for addx
 | 
      
         | 860 |  |  |         addil   #0x00000080,%d3 |inc at bit 6
 | 
      
         | 861 |  |  |         addxl   %d1,%d2         |continue inc
 | 
      
         | 862 |  |  |         andil   #0xffffff80,%d3 |strip off lsb not used by 882
 | 
      
         | 863 |  |  |         movel   #4,%d0          |put 4 in d0 for binstr call
 | 
      
         | 864 |  |  |         leal    L_SCR1(%a6),%a0 |a0 is ptr to L_SCR1 for exp digits
 | 
      
         | 865 |  |  |         bsr     binstr          |call binstr to convert exp
 | 
      
         | 866 |  |  |         movel   L_SCR1(%a6),%d0 |load L_SCR1 lword to d0
 | 
      
         | 867 |  |  |         movel   #12,%d1         |use d1 for shift count
 | 
      
         | 868 |  |  |         lsrl    %d1,%d0         |shift d0 right by 12
 | 
      
         | 869 |  |  |         bfins   %d0,FP_SCR1(%a6){#4:#12} |put e3:e2:e1 in FP_SCR1
 | 
      
         | 870 |  |  |         lsrl    %d1,%d0         |shift d0 right by 12
 | 
      
         | 871 |  |  |         bfins   %d0,FP_SCR1(%a6){#16:#4} |put e4 in FP_SCR1
 | 
      
         | 872 |  |  |         tstb    %d0             |check if e4 is zero
 | 
      
         | 873 |  |  |         beqs    A16_st          |if zero, skip rest
 | 
      
         | 874 |  |  |         orl     #opaop_mask,USER_FPSR(%a6) |set OPERR & AIOP in USER_FPSR
 | 
      
         | 875 |  |  |  
 | 
      
         | 876 |  |  |  
 | 
      
         | 877 |  |  | | A16. Write sign bits to final string.
 | 
      
         | 878 |  |  | |          Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
 | 
      
         | 879 |  |  | |
 | 
      
         | 880 |  |  | | Register usage:
 | 
      
         | 881 |  |  | |       Input/Output
 | 
      
         | 882 |  |  | |       d0: x/scratch - final is x
 | 
      
         | 883 |  |  | |       d2: x/x
 | 
      
         | 884 |  |  | |       d3: x/x
 | 
      
         | 885 |  |  | |       d4: LEN/Unchanged
 | 
      
         | 886 |  |  | |       d5: ICTR:LAMBDA/LAMBDA:ICTR
 | 
      
         | 887 |  |  | |       d6: ILOG/ILOG adjusted
 | 
      
         | 888 |  |  | |       d7: k-factor/Unchanged
 | 
      
         | 889 |  |  | |       a0: ptr to L_SCR1(a6)/Unchanged
 | 
      
         | 890 |  |  | |       a1: ptr to PTENxx array/Unchanged
 | 
      
         | 891 |  |  | |       a2: ptr to FP_SCR2(a6)/Unchanged
 | 
      
         | 892 |  |  | |       fp0: float(ILOG)/Unchanged
 | 
      
         | 893 |  |  | |       fp1: 10^ISCALE/Unchanged
 | 
      
         | 894 |  |  | |       fp2: 10^LEN/Unchanged
 | 
      
         | 895 |  |  | |       F_SCR1:BCD result with correct signs
 | 
      
         | 896 |  |  | |       F_SCR2:ILOG/10^4
 | 
      
         | 897 |  |  | |       L_SCR1:Exponent digits on return from binstr
 | 
      
         | 898 |  |  | |       L_SCR2:first word of X packed/Unchanged
 | 
      
         | 899 |  |  |  
 | 
      
         | 900 |  |  | A16_st:
 | 
      
         | 901 |  |  |         clrl    %d0             |clr d0 for collection of signs
 | 
      
         | 902 |  |  |         andib   #0x0f,FP_SCR1(%a6) |clear first nibble of FP_SCR1
 | 
      
         | 903 |  |  |         tstl    L_SCR2(%a6)     |check sign of original mantissa
 | 
      
         | 904 |  |  |         bges    mant_p          |if pos, don't set SM
 | 
      
         | 905 |  |  |         moveql  #2,%d0          |move 2 in to d0 for SM
 | 
      
         | 906 |  |  | mant_p:
 | 
      
         | 907 |  |  |         tstl    %d6             |check sign of ILOG
 | 
      
         | 908 |  |  |         bges    wr_sgn          |if pos, don't set SE
 | 
      
         | 909 |  |  |         addql   #1,%d0          |set bit 0 in d0 for SE
 | 
      
         | 910 |  |  | wr_sgn:
 | 
      
         | 911 |  |  |         bfins   %d0,FP_SCR1(%a6){#0:#2} |insert SM and SE into FP_SCR1
 | 
      
         | 912 |  |  |  
 | 
      
         | 913 |  |  | | Clean up and restore all registers used.
 | 
      
         | 914 |  |  |  
 | 
      
         | 915 |  |  |         fmovel  #0,%FPSR                |clear possible inex2/ainex bits
 | 
      
         | 916 |  |  |         fmovemx (%a7)+,%fp0-%fp2
 | 
      
         | 917 |  |  |         moveml  (%a7)+,%d2-%d7/%a2
 | 
      
         | 918 |  |  |         rts
 | 
      
         | 919 |  |  |  
 | 
      
         | 920 |  |  |         |end
 |