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