bindec.sa revision 1.3 1 1.3 cgd * $NetBSD: bindec.sa,v 1.3 1994/10/26 07:48:51 cgd 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.1 mycroft * If INEX is set, round error occured. 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.1 mycroft bne.b 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.1 mycroft tst.b BINDEC_FLG(a6) ;check for denorm
519 1.1 mycroft beq.b A9_norm ;if norm, continue with mul
520 1.1 mycroft fmovem.x fp1,-(a7) ;load ETEMP with 10^ISCALE
521 1.1 mycroft move.l 8(a0),-(a7) ;load FPTEMP with input arg
522 1.1 mycroft move.l 4(a0),-(a7)
523 1.1 mycroft move.l (a0),-(a7)
524 1.1 mycroft move.l #18,d3 ;load count for busy stack
525 1.1 mycroft A9_loop:
526 1.1 mycroft clr.l -(a7) ;clear lword on stack
527 1.1 mycroft dbf.w d3,A9_loop
528 1.1 mycroft move.b VER_TMP(a6),(a7) ;write current version number
529 1.1 mycroft move.b #BUSY_SIZE-4,1(a7) ;write current busy size
530 1.1 mycroft move.b #$10,$44(a7) ;set fcefpte[15] bit
531 1.1 mycroft move.w #$0023,$40(a7) ;load cmdreg1b with mul command
532 1.1 mycroft move.b #$fe,$8(a7) ;load all 1s to cu savepc
533 1.1 mycroft frestore (a7)+ ;restore frame to fpu for completion
534 1.1 mycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8
535 1.1 mycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16
536 1.1 mycroft bra.b A10_st
537 1.1 mycroft A9_norm:
538 1.1 mycroft tst.w d2 ;test for small exp case
539 1.1 mycroft beq.b A9_con ;if zero, continue as normal
540 1.1 mycroft fmul.x 36(a1),fp0 ;multiply fp0 by 10^8
541 1.1 mycroft fmul.x 48(a1),fp0 ;multiply fp0 by 10^16
542 1.1 mycroft A9_con:
543 1.1 mycroft fmul.x fp1,fp0 ;calculate X * SCALE -> Y to fp0
544 1.1 mycroft
545 1.1 mycroft
546 1.1 mycroft * A10. Or in INEX.
547 1.1 mycroft * If INEX is set, round error occured. This is compensated
548 1.1 mycroft * for by 'or-ing' in the INEX2 flag to the lsb of Y.
549 1.1 mycroft *
550 1.1 mycroft * Register usage:
551 1.1 mycroft * Input/Output
552 1.1 mycroft * d0: FPCR with RZ mode/FPSR with INEX2 isolated
553 1.1 mycroft * d2: x/x
554 1.1 mycroft * d3: x/x
555 1.1 mycroft * d4: LEN/Unchanged
556 1.1 mycroft * d5: ICTR:LAMBDA
557 1.1 mycroft * d6: ILOG/Unchanged
558 1.1 mycroft * d7: k-factor/Unchanged
559 1.1 mycroft * a0: ptr for original operand/final result
560 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
561 1.1 mycroft * a2: x/ptr to FP_SCR2(a6)
562 1.1 mycroft * fp0: Y/Y with lsb adjusted
563 1.1 mycroft * fp1: 10^ISCALE/Unchanged
564 1.1 mycroft * fp2: x/x
565 1.1 mycroft
566 1.1 mycroft A10_st:
567 1.1 mycroft fmove.l FPSR,d0 ;get FPSR
568 1.1 mycroft fmove.x fp0,FP_SCR2(a6) ;move Y to memory
569 1.1 mycroft lea.l FP_SCR2(a6),a2 ;load a2 with ptr to FP_SCR2
570 1.1 mycroft btst.l #9,d0 ;check if INEX2 set
571 1.1 mycroft beq.b A11_st ;if clear, skip rest
572 1.1 mycroft ori.l #1,8(a2) ;or in 1 to lsb of mantissa
573 1.1 mycroft fmove.x FP_SCR2(a6),fp0 ;write adjusted Y back to fpu
574 1.1 mycroft
575 1.1 mycroft
576 1.1 mycroft * A11. Restore original FPCR; set size ext.
577 1.1 mycroft * Perform FINT operation in the user's rounding mode. Keep
578 1.1 mycroft * the size to extended. The sintdo entry point in the sint
579 1.1 mycroft * routine expects the FPCR value to be in USER_FPCR for
580 1.1 mycroft * mode and precision. The original FPCR is saved in L_SCR1.
581 1.1 mycroft
582 1.1 mycroft A11_st:
583 1.1 mycroft move.l USER_FPCR(a6),L_SCR1(a6) ;save it for later
584 1.1 mycroft andi.l #$00000030,USER_FPCR(a6) ;set size to ext,
585 1.1 mycroft * ;block exceptions
586 1.1 mycroft
587 1.1 mycroft
588 1.1 mycroft * A12. Calculate YINT = FINT(Y) according to user's rounding mode.
589 1.1 mycroft * The FPSP routine sintd0 is used. The output is in fp0.
590 1.1 mycroft *
591 1.1 mycroft * Register usage:
592 1.1 mycroft * Input/Output
593 1.1 mycroft * d0: FPSR with AINEX cleared/FPCR with size set to ext
594 1.1 mycroft * d2: x/x/scratch
595 1.1 mycroft * d3: x/x
596 1.1 mycroft * d4: LEN/Unchanged
597 1.1 mycroft * d5: ICTR:LAMBDA/Unchanged
598 1.1 mycroft * d6: ILOG/Unchanged
599 1.1 mycroft * d7: k-factor/Unchanged
600 1.1 mycroft * a0: ptr for original operand/src ptr for sintdo
601 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
602 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
603 1.1 mycroft * a6: temp pointer to FP_SCR2(a6) - orig value saved and restored
604 1.1 mycroft * fp0: Y/YINT
605 1.1 mycroft * fp1: 10^ISCALE/Unchanged
606 1.1 mycroft * fp2: x/x
607 1.1 mycroft * F_SCR1:x/x
608 1.1 mycroft * F_SCR2:Y adjusted for inex/Y with original exponent
609 1.1 mycroft * L_SCR1:x/original USER_FPCR
610 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
611 1.1 mycroft
612 1.1 mycroft A12_st:
613 1.1 mycroft movem.l d0-d1/a0-a1,-(a7) ;save regs used by sintd0
614 1.1 mycroft move.l L_SCR1(a6),-(a7)
615 1.1 mycroft move.l L_SCR2(a6),-(a7)
616 1.1 mycroft lea.l FP_SCR2(a6),a0 ;a0 is ptr to F_SCR2(a6)
617 1.1 mycroft fmove.x fp0,(a0) ;move Y to memory at FP_SCR2(a6)
618 1.1 mycroft tst.l L_SCR2(a6) ;test sign of original operand
619 1.1 mycroft bge.b do_fint ;if pos, use Y
620 1.1 mycroft or.l #$80000000,(a0) ;if neg, use -Y
621 1.1 mycroft do_fint:
622 1.1 mycroft move.l USER_FPSR(a6),-(a7)
623 1.1 mycroft bsr sintdo ;sint routine returns int in fp0
624 1.1 mycroft move.b (a7),USER_FPSR(a6)
625 1.1 mycroft add.l #4,a7
626 1.1 mycroft move.l (a7)+,L_SCR2(a6)
627 1.1 mycroft move.l (a7)+,L_SCR1(a6)
628 1.1 mycroft movem.l (a7)+,d0-d1/a0-a1 ;restore regs used by sint
629 1.1 mycroft move.l L_SCR2(a6),FP_SCR2(a6) ;restore original exponent
630 1.1 mycroft move.l L_SCR1(a6),USER_FPCR(a6) ;restore user's FPCR
631 1.1 mycroft
632 1.1 mycroft
633 1.1 mycroft * A13. Check for LEN digits.
634 1.1 mycroft * If the int operation results in more than LEN digits,
635 1.1 mycroft * or less than LEN -1 digits, adjust ILOG and repeat from
636 1.1 mycroft * A6. This test occurs only on the first pass. If the
637 1.1 mycroft * result is exactly 10^LEN, decrement ILOG and divide
638 1.1 mycroft * the mantissa by 10. The calculation of 10^LEN cannot
639 1.1 mycroft * be inexact, since all powers of ten upto 10^27 are exact
640 1.1 mycroft * in extended precision, so the use of a previous power-of-ten
641 1.1 mycroft * table will introduce no error.
642 1.1 mycroft *
643 1.1 mycroft *
644 1.1 mycroft * Register usage:
645 1.1 mycroft * Input/Output
646 1.1 mycroft * d0: FPCR with size set to ext/scratch final = 0
647 1.1 mycroft * d2: x/x
648 1.1 mycroft * d3: x/scratch final = x
649 1.1 mycroft * d4: LEN/LEN adjusted
650 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
651 1.1 mycroft * d6: ILOG/ILOG adjusted
652 1.1 mycroft * d7: k-factor/Unchanged
653 1.1 mycroft * a0: pointer into memory for packed bcd string formation
654 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
655 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
656 1.1 mycroft * fp0: int portion of Y/abs(YINT) adjusted
657 1.1 mycroft * fp1: 10^ISCALE/Unchanged
658 1.1 mycroft * fp2: x/10^LEN
659 1.1 mycroft * F_SCR1:x/x
660 1.1 mycroft * F_SCR2:Y with original exponent/Unchanged
661 1.1 mycroft * L_SCR1:original USER_FPCR/Unchanged
662 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
663 1.1 mycroft
664 1.1 mycroft A13_st:
665 1.1 mycroft swap d5 ;put ICTR in lower word of d5
666 1.1 mycroft tst.w d5 ;check if ICTR = 0
667 1.1 mycroft bne not_zr ;if non-zero, go to second test
668 1.1 mycroft *
669 1.1 mycroft * Compute 10^(LEN-1)
670 1.1 mycroft *
671 1.1 mycroft fmove.s FONE,fp2 ;init fp2 to 1.0
672 1.1 mycroft move.l d4,d0 ;put LEN in d0
673 1.1 mycroft subq.l #1,d0 ;d0 = LEN -1
674 1.1 mycroft clr.l d3 ;clr table index
675 1.1 mycroft l_loop:
676 1.1 mycroft lsr.l #1,d0 ;shift next bit into carry
677 1.1 mycroft bcc.b l_next ;if zero, skip the mul
678 1.1 mycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no)
679 1.1 mycroft l_next:
680 1.1 mycroft add.l #12,d3 ;inc d3 to next pwrten table entry
681 1.1 mycroft tst.l d0 ;test if LEN is zero
682 1.1 mycroft bne.b l_loop ;if not, loop
683 1.1 mycroft *
684 1.1 mycroft * 10^LEN-1 is computed for this test and A14. If the input was
685 1.1 mycroft * denormalized, check only the case in which YINT > 10^LEN.
686 1.1 mycroft *
687 1.1 mycroft tst.b BINDEC_FLG(a6) ;check if input was norm
688 1.1 mycroft beq.b A13_con ;if norm, continue with checking
689 1.1 mycroft fabs.x fp0 ;take abs of YINT
690 1.1 mycroft bra test_2
691 1.1 mycroft *
692 1.1 mycroft * Compare abs(YINT) to 10^(LEN-1) and 10^LEN
693 1.1 mycroft *
694 1.1 mycroft A13_con:
695 1.1 mycroft fabs.x fp0 ;take abs of YINT
696 1.1 mycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^(LEN-1)
697 1.1 mycroft fbge.w test_2 ;if greater, do next test
698 1.1 mycroft subq.l #1,d6 ;subtract 1 from ILOG
699 1.1 mycroft move.w #1,d5 ;set ICTR
700 1.1 mycroft fmove.l #rm_mode,FPCR ;set rmode to RM
701 1.1 mycroft fmul.s FTEN,fp2 ;compute 10^LEN
702 1.1 mycroft bra.w A6_str ;return to A6 and recompute YINT
703 1.1 mycroft test_2:
704 1.1 mycroft fmul.s FTEN,fp2 ;compute 10^LEN
705 1.1 mycroft fcmp.x fp2,fp0 ;compare abs(YINT) with 10^LEN
706 1.1 mycroft fblt.w A14_st ;if less, all is ok, go to A14
707 1.1 mycroft fbgt.w fix_ex ;if greater, fix and redo
708 1.1 mycroft fdiv.s FTEN,fp0 ;if equal, divide by 10
709 1.1 mycroft addq.l #1,d6 ; and inc ILOG
710 1.1 mycroft bra.b A14_st ; and continue elsewhere
711 1.1 mycroft fix_ex:
712 1.1 mycroft addq.l #1,d6 ;increment ILOG by 1
713 1.1 mycroft move.w #1,d5 ;set ICTR
714 1.1 mycroft fmove.l #rm_mode,FPCR ;set rmode to RM
715 1.1 mycroft bra.w A6_str ;return to A6 and recompute YINT
716 1.1 mycroft *
717 1.1 mycroft * Since ICTR <> 0, we have already been through one adjustment,
718 1.1 mycroft * and shouldn't have another; this is to check if abs(YINT) = 10^LEN
719 1.1 mycroft * 10^LEN is again computed using whatever table is in a1 since the
720 1.1 mycroft * value calculated cannot be inexact.
721 1.1 mycroft *
722 1.1 mycroft not_zr:
723 1.1 mycroft fmove.s FONE,fp2 ;init fp2 to 1.0
724 1.1 mycroft move.l d4,d0 ;put LEN in d0
725 1.1 mycroft clr.l d3 ;clr table index
726 1.1 mycroft z_loop:
727 1.1 mycroft lsr.l #1,d0 ;shift next bit into carry
728 1.1 mycroft bcc.b z_next ;if zero, skip the mul
729 1.1 mycroft fmul.x (a1,d3),fp2 ;mul by 10**(d3_bit_no)
730 1.1 mycroft z_next:
731 1.1 mycroft add.l #12,d3 ;inc d3 to next pwrten table entry
732 1.1 mycroft tst.l d0 ;test if LEN is zero
733 1.1 mycroft bne.b z_loop ;if not, loop
734 1.1 mycroft fabs.x fp0 ;get abs(YINT)
735 1.1 mycroft fcmp.x fp2,fp0 ;check if abs(YINT) = 10^LEN
736 1.1 mycroft fbne.w A14_st ;if not, skip this
737 1.1 mycroft fdiv.s FTEN,fp0 ;divide abs(YINT) by 10
738 1.1 mycroft addq.l #1,d6 ;and inc ILOG by 1
739 1.1 mycroft addq.l #1,d4 ; and inc LEN
740 1.1 mycroft fmul.s FTEN,fp2 ; if LEN++, the get 10^^LEN
741 1.1 mycroft
742 1.1 mycroft
743 1.1 mycroft * A14. Convert the mantissa to bcd.
744 1.1 mycroft * The binstr routine is used to convert the LEN digit
745 1.1 mycroft * mantissa to bcd in memory. The input to binstr is
746 1.1 mycroft * to be a fraction; i.e. (mantissa)/10^LEN and adjusted
747 1.1 mycroft * such that the decimal point is to the left of bit 63.
748 1.1 mycroft * The bcd digits are stored in the correct position in
749 1.1 mycroft * the final string area in memory.
750 1.1 mycroft *
751 1.1 mycroft *
752 1.1 mycroft * Register usage:
753 1.1 mycroft * Input/Output
754 1.1 mycroft * d0: x/LEN call to binstr - final is 0
755 1.1 mycroft * d1: x/0
756 1.1 mycroft * d2: x/ms 32-bits of mant of abs(YINT)
757 1.1 mycroft * d3: x/ls 32-bits of mant of abs(YINT)
758 1.1 mycroft * d4: LEN/Unchanged
759 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
760 1.1 mycroft * d6: ILOG
761 1.1 mycroft * d7: k-factor/Unchanged
762 1.1 mycroft * a0: pointer into memory for packed bcd string formation
763 1.1 mycroft * /ptr to first mantissa byte in result string
764 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
765 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
766 1.1 mycroft * fp0: int portion of Y/abs(YINT) adjusted
767 1.1 mycroft * fp1: 10^ISCALE/Unchanged
768 1.1 mycroft * fp2: 10^LEN/Unchanged
769 1.1 mycroft * F_SCR1:x/Work area for final result
770 1.1 mycroft * F_SCR2:Y with original exponent/Unchanged
771 1.1 mycroft * L_SCR1:original USER_FPCR/Unchanged
772 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
773 1.1 mycroft
774 1.1 mycroft A14_st:
775 1.1 mycroft fmove.l #rz_mode,FPCR ;force rz for conversion
776 1.1 mycroft fdiv.x fp2,fp0 ;divide abs(YINT) by 10^LEN
777 1.1 mycroft lea.l FP_SCR1(a6),a0
778 1.1 mycroft fmove.x fp0,(a0) ;move abs(YINT)/10^LEN to memory
779 1.1 mycroft move.l 4(a0),d2 ;move 2nd word of FP_RES to d2
780 1.1 mycroft move.l 8(a0),d3 ;move 3rd word of FP_RES to d3
781 1.1 mycroft clr.l 4(a0) ;zero word 2 of FP_RES
782 1.1 mycroft clr.l 8(a0) ;zero word 3 of FP_RES
783 1.1 mycroft move.l (a0),d0 ;move exponent to d0
784 1.1 mycroft swap d0 ;put exponent in lower word
785 1.1 mycroft beq.b no_sft ;if zero, don't shift
786 1.1 mycroft subi.l #$3ffd,d0 ;sub bias less 2 to make fract
787 1.1 mycroft tst.l d0 ;check if > 1
788 1.1 mycroft bgt.b no_sft ;if so, don't shift
789 1.1 mycroft neg.l d0 ;make exp positive
790 1.1 mycroft m_loop:
791 1.1 mycroft lsr.l #1,d2 ;shift d2:d3 right, add 0s
792 1.1 mycroft roxr.l #1,d3 ;the number of places
793 1.1 mycroft dbf.w d0,m_loop ;given in d0
794 1.1 mycroft no_sft:
795 1.1 mycroft tst.l d2 ;check for mantissa of zero
796 1.1 mycroft bne.b no_zr ;if not, go on
797 1.1 mycroft tst.l d3 ;continue zero check
798 1.1 mycroft beq.b zer_m ;if zero, go directly to binstr
799 1.1 mycroft no_zr:
800 1.1 mycroft clr.l d1 ;put zero in d1 for addx
801 1.1 mycroft addi.l #$00000080,d3 ;inc at bit 7
802 1.1 mycroft addx.l d1,d2 ;continue inc
803 1.1 mycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882
804 1.1 mycroft zer_m:
805 1.1 mycroft move.l d4,d0 ;put LEN in d0 for binstr call
806 1.1 mycroft addq.l #3,a0 ;a0 points to M16 byte in result
807 1.1 mycroft bsr binstr ;call binstr to convert mant
808 1.1 mycroft
809 1.1 mycroft
810 1.1 mycroft * A15. Convert the exponent to bcd.
811 1.1 mycroft * As in A14 above, the exp is converted to bcd and the
812 1.1 mycroft * digits are stored in the final string.
813 1.1 mycroft *
814 1.1 mycroft * Digits are stored in L_SCR1(a6) on return from BINDEC as:
815 1.1 mycroft *
816 1.1 mycroft * 32 16 15 0
817 1.1 mycroft * -----------------------------------------
818 1.1 mycroft * | 0 | e3 | e2 | e1 | e4 | X | X | X |
819 1.1 mycroft * -----------------------------------------
820 1.1 mycroft *
821 1.1 mycroft * And are moved into their proper places in FP_SCR1. If digit e4
822 1.1 mycroft * is non-zero, OPERR is signaled. In all cases, all 4 digits are
823 1.1 mycroft * written as specified in the 881/882 manual for packed decimal.
824 1.1 mycroft *
825 1.1 mycroft * Register usage:
826 1.1 mycroft * Input/Output
827 1.1 mycroft * d0: x/LEN call to binstr - final is 0
828 1.1 mycroft * d1: x/scratch (0);shift count for final exponent packing
829 1.1 mycroft * d2: x/ms 32-bits of exp fraction/scratch
830 1.1 mycroft * d3: x/ls 32-bits of exp fraction
831 1.1 mycroft * d4: LEN/Unchanged
832 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
833 1.1 mycroft * d6: ILOG
834 1.1 mycroft * d7: k-factor/Unchanged
835 1.1 mycroft * a0: ptr to result string/ptr to L_SCR1(a6)
836 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
837 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
838 1.1 mycroft * fp0: abs(YINT) adjusted/float(ILOG)
839 1.1 mycroft * fp1: 10^ISCALE/Unchanged
840 1.1 mycroft * fp2: 10^LEN/Unchanged
841 1.1 mycroft * F_SCR1:Work area for final result/BCD result
842 1.1 mycroft * F_SCR2:Y with original exponent/ILOG/10^4
843 1.1 mycroft * L_SCR1:original USER_FPCR/Exponent digits on return from binstr
844 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
845 1.1 mycroft
846 1.1 mycroft A15_st:
847 1.1 mycroft tst.b BINDEC_FLG(a6) ;check for denorm
848 1.1 mycroft beq.b not_denorm
849 1.1 mycroft ftst.x fp0 ;test for zero
850 1.1 mycroft fbeq.w den_zero ;if zero, use k-factor or 4933
851 1.1 mycroft fmove.l d6,fp0 ;float ILOG
852 1.1 mycroft fabs.x fp0 ;get abs of ILOG
853 1.1 mycroft bra.b convrt
854 1.1 mycroft den_zero:
855 1.1 mycroft tst.l d7 ;check sign of the k-factor
856 1.1 mycroft blt.b use_ilog ;if negative, use ILOG
857 1.1 mycroft fmove.s F4933,fp0 ;force exponent to 4933
858 1.1 mycroft bra.b convrt ;do it
859 1.1 mycroft use_ilog:
860 1.1 mycroft fmove.l d6,fp0 ;float ILOG
861 1.1 mycroft fabs.x fp0 ;get abs of ILOG
862 1.1 mycroft bra.b convrt
863 1.1 mycroft not_denorm:
864 1.1 mycroft ftst.x fp0 ;test for zero
865 1.1 mycroft fbne.w not_zero ;if zero, force exponent
866 1.1 mycroft fmove.s FONE,fp0 ;force exponent to 1
867 1.1 mycroft bra.b convrt ;do it
868 1.1 mycroft not_zero:
869 1.1 mycroft fmove.l d6,fp0 ;float ILOG
870 1.1 mycroft fabs.x fp0 ;get abs of ILOG
871 1.1 mycroft convrt:
872 1.1 mycroft fdiv.x 24(a1),fp0 ;compute ILOG/10^4
873 1.1 mycroft fmove.x fp0,FP_SCR2(a6) ;store fp0 in memory
874 1.1 mycroft move.l 4(a2),d2 ;move word 2 to d2
875 1.1 mycroft move.l 8(a2),d3 ;move word 3 to d3
876 1.1 mycroft move.w (a2),d0 ;move exp to d0
877 1.1 mycroft beq.b x_loop_fin ;if zero, skip the shift
878 1.1 mycroft subi.w #$3ffd,d0 ;subtract off bias
879 1.1 mycroft neg.w d0 ;make exp positive
880 1.1 mycroft x_loop:
881 1.1 mycroft lsr.l #1,d2 ;shift d2:d3 right
882 1.1 mycroft roxr.l #1,d3 ;the number of places
883 1.1 mycroft dbf.w d0,x_loop ;given in d0
884 1.1 mycroft x_loop_fin:
885 1.1 mycroft clr.l d1 ;put zero in d1 for addx
886 1.1 mycroft addi.l #$00000080,d3 ;inc at bit 6
887 1.1 mycroft addx.l d1,d2 ;continue inc
888 1.1 mycroft andi.l #$ffffff80,d3 ;strip off lsb not used by 882
889 1.1 mycroft move.l #4,d0 ;put 4 in d0 for binstr call
890 1.1 mycroft lea.l L_SCR1(a6),a0 ;a0 is ptr to L_SCR1 for exp digits
891 1.1 mycroft bsr binstr ;call binstr to convert exp
892 1.1 mycroft move.l L_SCR1(a6),d0 ;load L_SCR1 lword to d0
893 1.1 mycroft move.l #12,d1 ;use d1 for shift count
894 1.1 mycroft lsr.l d1,d0 ;shift d0 right by 12
895 1.1 mycroft bfins d0,FP_SCR1(a6){4:12} ;put e3:e2:e1 in FP_SCR1
896 1.1 mycroft lsr.l d1,d0 ;shift d0 right by 12
897 1.1 mycroft bfins d0,FP_SCR1(a6){16:4} ;put e4 in FP_SCR1
898 1.1 mycroft tst.b d0 ;check if e4 is zero
899 1.1 mycroft beq.b A16_st ;if zero, skip rest
900 1.1 mycroft or.l #opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR
901 1.1 mycroft
902 1.1 mycroft
903 1.1 mycroft * A16. Write sign bits to final string.
904 1.1 mycroft * Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
905 1.1 mycroft *
906 1.1 mycroft * Register usage:
907 1.1 mycroft * Input/Output
908 1.1 mycroft * d0: x/scratch - final is x
909 1.1 mycroft * d2: x/x
910 1.1 mycroft * d3: x/x
911 1.1 mycroft * d4: LEN/Unchanged
912 1.1 mycroft * d5: ICTR:LAMBDA/LAMBDA:ICTR
913 1.1 mycroft * d6: ILOG/ILOG adjusted
914 1.1 mycroft * d7: k-factor/Unchanged
915 1.1 mycroft * a0: ptr to L_SCR1(a6)/Unchanged
916 1.1 mycroft * a1: ptr to PTENxx array/Unchanged
917 1.1 mycroft * a2: ptr to FP_SCR2(a6)/Unchanged
918 1.1 mycroft * fp0: float(ILOG)/Unchanged
919 1.1 mycroft * fp1: 10^ISCALE/Unchanged
920 1.1 mycroft * fp2: 10^LEN/Unchanged
921 1.1 mycroft * F_SCR1:BCD result with correct signs
922 1.1 mycroft * F_SCR2:ILOG/10^4
923 1.1 mycroft * L_SCR1:Exponent digits on return from binstr
924 1.1 mycroft * L_SCR2:first word of X packed/Unchanged
925 1.1 mycroft
926 1.1 mycroft A16_st:
927 1.1 mycroft clr.l d0 ;clr d0 for collection of signs
928 1.1 mycroft andi.b #$0f,FP_SCR1(a6) ;clear first nibble of FP_SCR1
929 1.1 mycroft tst.l L_SCR2(a6) ;check sign of original mantissa
930 1.1 mycroft bge.b mant_p ;if pos, don't set SM
931 1.1 mycroft moveq.l #2,d0 ;move 2 in to d0 for SM
932 1.1 mycroft mant_p:
933 1.1 mycroft tst.l d6 ;check sign of ILOG
934 1.1 mycroft bge.b wr_sgn ;if pos, don't set SE
935 1.1 mycroft addq.l #1,d0 ;set bit 0 in d0 for SE
936 1.1 mycroft wr_sgn:
937 1.1 mycroft bfins d0,FP_SCR1(a6){0:2} ;insert SM and SE into FP_SCR1
938 1.1 mycroft
939 1.1 mycroft * Clean up and restore all registers used.
940 1.1 mycroft
941 1.1 mycroft fmove.l #0,FPSR ;clear possible inex2/ainex bits
942 1.1 mycroft fmovem.x (a7)+,fp0-fp2
943 1.1 mycroft movem.l (a7)+,d2-d7/a2
944 1.1 mycroft rts
945 1.1 mycroft
946 1.1 mycroft end
947